blob: da72ecd129dde454d230806b430ac40093412334 [file] [log] [blame]
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001// Copyright 2012 the V8 project authors. All rights reserved.
Steve Blocka7e24c12009-10-30 11:49:00 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
Ben Murdochb8a8cc12014-11-26 15:28:44 +000028#include <climits>
29#include <csignal>
30#include <map>
31#include <string>
Steve Blocka7e24c12009-10-30 11:49:00 +000032
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000033#include "test/cctest/test-api.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000034
Ben Murdochb8a8cc12014-11-26 15:28:44 +000035#if V8_OS_POSIX
36#include <unistd.h> // NOLINT
37#endif
38
39#include "include/v8-util.h"
40#include "src/api.h"
41#include "src/arguments.h"
42#include "src/base/platform/platform.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000043#include "src/base/smart-pointers.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000044#include "src/compilation-cache.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000045#include "src/debug/debug.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000046#include "src/execution.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000047#include "src/futex-emulation.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000048#include "src/objects.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000049#include "src/parsing/parser.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000050#include "src/unicode-inl.h"
51#include "src/utils.h"
52#include "src/vm-state.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000053#include "test/cctest/heap/heap-tester.h"
54#include "test/cctest/heap/utils-inl.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000055
Ben Murdoch257744e2011-11-30 15:57:28 +000056static const bool kLogThreading = false;
Steve Blockd0582a62009-12-15 09:54:21 +000057
Ben Murdochb8a8cc12014-11-26 15:28:44 +000058using ::v8::Boolean;
59using ::v8::BooleanObject;
Steve Block44f0eee2011-05-26 01:26:41 +010060using ::v8::Context;
Steve Blocka7e24c12009-10-30 11:49:00 +000061using ::v8::Extension;
Steve Block44f0eee2011-05-26 01:26:41 +010062using ::v8::Function;
Ben Murdoch8b112d22011-06-08 16:22:53 +010063using ::v8::FunctionTemplate;
Steve Block44f0eee2011-05-26 01:26:41 +010064using ::v8::HandleScope;
65using ::v8::Local;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000066using ::v8::Maybe;
Ben Murdoch8b112d22011-06-08 16:22:53 +010067using ::v8::Message;
68using ::v8::MessageCallback;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000069using ::v8::Name;
70using ::v8::None;
Steve Block44f0eee2011-05-26 01:26:41 +010071using ::v8::Object;
72using ::v8::ObjectTemplate;
73using ::v8::Persistent;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000074using ::v8::PropertyAttribute;
Steve Block44f0eee2011-05-26 01:26:41 +010075using ::v8::Script;
Ben Murdoch8b112d22011-06-08 16:22:53 +010076using ::v8::StackTrace;
Steve Block44f0eee2011-05-26 01:26:41 +010077using ::v8::String;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000078using ::v8::Symbol;
Ben Murdoch8b112d22011-06-08 16:22:53 +010079using ::v8::TryCatch;
80using ::v8::Undefined;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000081using ::v8::UniqueId;
Steve Block44f0eee2011-05-26 01:26:41 +010082using ::v8::V8;
Ben Murdoch8b112d22011-06-08 16:22:53 +010083using ::v8::Value;
Steve Blocka7e24c12009-10-30 11:49:00 +000084
Steve Blocka7e24c12009-10-30 11:49:00 +000085
Ben Murdochb8a8cc12014-11-26 15:28:44 +000086#define THREADED_PROFILED_TEST(Name) \
87 static void Test##Name(); \
88 TEST(Name##WithProfiler) { \
89 RunWithProfiler(&Test##Name); \
90 } \
91 THREADED_TEST(Name)
Leon Clarked91b9f72010-01-27 17:25:45 +000092
93
Ben Murdochb8a8cc12014-11-26 15:28:44 +000094void RunWithProfiler(void (*test)()) {
95 LocalContext env;
96 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000097 v8::Local<v8::String> profile_name = v8_str("my_profile1");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000098 v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler();
Leon Clarkef7060e22010-06-03 12:02:55 +010099
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000100 cpu_profiler->StartProfiling(profile_name);
101 (*test)();
102 reinterpret_cast<i::CpuProfiler*>(cpu_profiler)->DeleteAllProfiles();
Iain Merrick75681382010-08-19 15:07:18 +0100103}
104
105
Steve Blocka7e24c12009-10-30 11:49:00 +0000106static int signature_callback_count;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000107static Local<Value> signature_expected_receiver;
108static void IncrementingSignatureCallback(
109 const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000110 ApiTestFuzzer::Fuzz();
111 signature_callback_count++;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000112 CHECK(signature_expected_receiver->Equals(
113 args.GetIsolate()->GetCurrentContext(),
114 args.Holder())
115 .FromJust());
116 CHECK(signature_expected_receiver->Equals(
117 args.GetIsolate()->GetCurrentContext(),
118 args.This())
119 .FromJust());
120 v8::Local<v8::Array> result =
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000121 v8::Array::New(args.GetIsolate(), args.Length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000122 for (int i = 0; i < args.Length(); i++) {
123 CHECK(result->Set(args.GetIsolate()->GetCurrentContext(),
124 v8::Integer::New(args.GetIsolate(), i), args[i])
125 .FromJust());
126 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000127 args.GetReturnValue().Set(result);
Steve Blocka7e24c12009-10-30 11:49:00 +0000128}
129
130
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000131static void Returns42(const v8::FunctionCallbackInfo<v8::Value>& info) {
132 info.GetReturnValue().Set(42);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000133}
134
135
136// Tests that call v8::V8::Dispose() cannot be threaded.
137UNINITIALIZED_TEST(InitializeAndDisposeOnce) {
138 CHECK(v8::V8::Initialize());
139 CHECK(v8::V8::Dispose());
140}
141
142
143// Tests that call v8::V8::Dispose() cannot be threaded.
144UNINITIALIZED_TEST(InitializeAndDisposeMultiple) {
145 for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
146 for (int i = 0; i < 3; ++i) CHECK(v8::V8::Initialize());
147 for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
148 for (int i = 0; i < 3; ++i) CHECK(v8::V8::Initialize());
149 for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
Steve Blocka7e24c12009-10-30 11:49:00 +0000150}
151
152
153THREADED_TEST(Handles) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000154 v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +0000155 Local<Context> local_env;
156 {
157 LocalContext env;
158 local_env = env.local();
159 }
160
161 // Local context should still be live.
162 CHECK(!local_env.IsEmpty());
163 local_env->Enter();
164
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000165 v8::Local<v8::Primitive> undef = v8::Undefined(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +0000166 CHECK(!undef.IsEmpty());
167 CHECK(undef->IsUndefined());
168
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000169 const char* source = "1 + 2 + 3";
170 Local<Script> script = v8_compile(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000171 CHECK_EQ(6, v8_run_int32value(script));
Steve Blocka7e24c12009-10-30 11:49:00 +0000172
173 local_env->Exit();
174}
175
176
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000177THREADED_TEST(IsolateOfContext) {
178 v8::HandleScope scope(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000179 v8::Local<Context> env = Context::New(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +0000180
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000181 CHECK(!env->GetIsolate()->InContext());
182 CHECK(env->GetIsolate() == CcTest::isolate());
183 env->Enter();
184 CHECK(env->GetIsolate()->InContext());
185 CHECK(env->GetIsolate() == CcTest::isolate());
186 env->Exit();
187 CHECK(!env->GetIsolate()->InContext());
188 CHECK(env->GetIsolate() == CcTest::isolate());
189}
190
191
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400192static void TestSignature(const char* loop_js, Local<Value> receiver,
193 v8::Isolate* isolate) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000194 i::ScopedVector<char> source(200);
195 i::SNPrintF(source,
196 "for (var i = 0; i < 10; i++) {"
197 " %s"
198 "}",
199 loop_js);
200 signature_callback_count = 0;
201 signature_expected_receiver = receiver;
202 bool expected_to_throw = receiver.IsEmpty();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000203 v8::TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000204 CompileRun(source.start());
205 CHECK_EQ(expected_to_throw, try_catch.HasCaught());
206 if (!expected_to_throw) {
207 CHECK_EQ(10, signature_callback_count);
208 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000209 CHECK(v8_str("TypeError: Illegal invocation")
210 ->Equals(isolate->GetCurrentContext(),
211 try_catch.Exception()
212 ->ToString(isolate->GetCurrentContext())
213 .ToLocalChecked())
214 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000215 }
216}
217
218
219THREADED_TEST(ReceiverSignature) {
220 LocalContext env;
221 v8::Isolate* isolate = env->GetIsolate();
222 v8::HandleScope scope(isolate);
223 // Setup templates.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000224 v8::Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(isolate);
225 v8::Local<v8::Signature> sig = v8::Signature::New(isolate, fun);
226 v8::Local<v8::FunctionTemplate> callback_sig = v8::FunctionTemplate::New(
227 isolate, IncrementingSignatureCallback, Local<Value>(), sig);
228 v8::Local<v8::FunctionTemplate> callback =
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000229 v8::FunctionTemplate::New(isolate, IncrementingSignatureCallback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000230 v8::Local<v8::FunctionTemplate> sub_fun = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000231 sub_fun->Inherit(fun);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000232 v8::Local<v8::FunctionTemplate> unrel_fun =
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000233 v8::FunctionTemplate::New(isolate);
234 // Install properties.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000235 v8::Local<v8::ObjectTemplate> fun_proto = fun->PrototypeTemplate();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000236 fun_proto->Set(v8_str("prop_sig"), callback_sig);
237 fun_proto->Set(v8_str("prop"), callback);
238 fun_proto->SetAccessorProperty(
239 v8_str("accessor_sig"), callback_sig, callback_sig);
240 fun_proto->SetAccessorProperty(v8_str("accessor"), callback, callback);
241 // Instantiate templates.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000242 Local<Value> fun_instance =
243 fun->InstanceTemplate()->NewInstance(env.local()).ToLocalChecked();
244 Local<Value> sub_fun_instance =
245 sub_fun->InstanceTemplate()->NewInstance(env.local()).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000246 // Setup global variables.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000247 CHECK(env->Global()
248 ->Set(env.local(), v8_str("Fun"),
249 fun->GetFunction(env.local()).ToLocalChecked())
250 .FromJust());
251 CHECK(env->Global()
252 ->Set(env.local(), v8_str("UnrelFun"),
253 unrel_fun->GetFunction(env.local()).ToLocalChecked())
254 .FromJust());
255 CHECK(env->Global()
256 ->Set(env.local(), v8_str("fun_instance"), fun_instance)
257 .FromJust());
258 CHECK(env->Global()
259 ->Set(env.local(), v8_str("sub_fun_instance"), sub_fun_instance)
260 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +0000261 CompileRun(
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000262 "var accessor_sig_key = 'accessor_sig';"
263 "var accessor_key = 'accessor';"
264 "var prop_sig_key = 'prop_sig';"
265 "var prop_key = 'prop';"
266 ""
267 "function copy_props(obj) {"
268 " var keys = [accessor_sig_key, accessor_key, prop_sig_key, prop_key];"
269 " var source = Fun.prototype;"
270 " for (var i in keys) {"
271 " var key = keys[i];"
272 " var desc = Object.getOwnPropertyDescriptor(source, key);"
273 " Object.defineProperty(obj, key, desc);"
274 " }"
275 "}"
276 ""
277 "var obj = {};"
278 "copy_props(obj);"
279 "var unrel = new UnrelFun();"
280 "copy_props(unrel);");
281 // Test with and without ICs
282 const char* test_objects[] = {
283 "fun_instance", "sub_fun_instance", "obj", "unrel" };
284 unsigned bad_signature_start_offset = 2;
285 for (unsigned i = 0; i < arraysize(test_objects); i++) {
286 i::ScopedVector<char> source(200);
287 i::SNPrintF(
288 source, "var test_object = %s; test_object", test_objects[i]);
289 Local<Value> test_object = CompileRun(source.start());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400290 TestSignature("test_object.prop();", test_object, isolate);
291 TestSignature("test_object.accessor;", test_object, isolate);
292 TestSignature("test_object[accessor_key];", test_object, isolate);
293 TestSignature("test_object.accessor = 1;", test_object, isolate);
294 TestSignature("test_object[accessor_key] = 1;", test_object, isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000295 if (i >= bad_signature_start_offset) test_object = Local<Value>();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400296 TestSignature("test_object.prop_sig();", test_object, isolate);
297 TestSignature("test_object.accessor_sig;", test_object, isolate);
298 TestSignature("test_object[accessor_sig_key];", test_object, isolate);
299 TestSignature("test_object.accessor_sig = 1;", test_object, isolate);
300 TestSignature("test_object[accessor_sig_key] = 1;", test_object, isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000301 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000302}
303
304
Steve Blocka7e24c12009-10-30 11:49:00 +0000305THREADED_TEST(HulIgennem) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000306 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000307 v8::Isolate* isolate = env->GetIsolate();
308 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000309 v8::Local<v8::Primitive> undef = v8::Undefined(isolate);
310 Local<String> undef_str = undef->ToString(env.local()).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000311 char* value = i::NewArray<char>(undef_str->Utf8Length() + 1);
312 undef_str->WriteUtf8(value);
Steve Blocka7e24c12009-10-30 11:49:00 +0000313 CHECK_EQ(0, strcmp(value, "undefined"));
314 i::DeleteArray(value);
315}
316
317
318THREADED_TEST(Access) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000319 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000320 v8::Isolate* isolate = env->GetIsolate();
321 v8::HandleScope scope(isolate);
322 Local<v8::Object> obj = v8::Object::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000323 Local<Value> foo_before =
324 obj->Get(env.local(), v8_str("foo")).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +0000325 CHECK(foo_before->IsUndefined());
326 Local<String> bar_str = v8_str("bar");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000327 CHECK(obj->Set(env.local(), v8_str("foo"), bar_str).FromJust());
328 Local<Value> foo_after =
329 obj->Get(env.local(), v8_str("foo")).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +0000330 CHECK(!foo_after->IsUndefined());
331 CHECK(foo_after->IsString());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000332 CHECK(bar_str->Equals(env.local(), foo_after).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +0000333}
334
335
Steve Block6ded16b2010-05-10 14:33:55 +0100336THREADED_TEST(AccessElement) {
Steve Block6ded16b2010-05-10 14:33:55 +0100337 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000338 v8::HandleScope scope(env->GetIsolate());
339 Local<v8::Object> obj = v8::Object::New(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000340 Local<Value> before = obj->Get(env.local(), 1).ToLocalChecked();
Steve Block6ded16b2010-05-10 14:33:55 +0100341 CHECK(before->IsUndefined());
342 Local<String> bar_str = v8_str("bar");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000343 CHECK(obj->Set(env.local(), 1, bar_str).FromJust());
344 Local<Value> after = obj->Get(env.local(), 1).ToLocalChecked();
Steve Block6ded16b2010-05-10 14:33:55 +0100345 CHECK(!after->IsUndefined());
346 CHECK(after->IsString());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000347 CHECK(bar_str->Equals(env.local(), after).FromJust());
Steve Block6ded16b2010-05-10 14:33:55 +0100348
349 Local<v8::Array> value = CompileRun("[\"a\", \"b\"]").As<v8::Array>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000350 CHECK(v8_str("a")
351 ->Equals(env.local(), value->Get(env.local(), 0).ToLocalChecked())
352 .FromJust());
353 CHECK(v8_str("b")
354 ->Equals(env.local(), value->Get(env.local(), 1).ToLocalChecked())
355 .FromJust());
Steve Block6ded16b2010-05-10 14:33:55 +0100356}
357
358
Steve Blocka7e24c12009-10-30 11:49:00 +0000359THREADED_TEST(Script) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000360 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000361 v8::HandleScope scope(env->GetIsolate());
362 const char* source = "1 + 2 + 3";
363 Local<Script> script = v8_compile(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000364 CHECK_EQ(6, v8_run_int32value(script));
Steve Blocka7e24c12009-10-30 11:49:00 +0000365}
366
367
Steve Blocka7e24c12009-10-30 11:49:00 +0000368class TestResource: public String::ExternalStringResource {
369 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000370 explicit TestResource(uint16_t* data, int* counter = NULL,
371 bool owning_data = true)
372 : data_(data), length_(0), counter_(counter), owning_data_(owning_data) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000373 while (data[length_]) ++length_;
374 }
375
376 ~TestResource() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000377 if (owning_data_) i::DeleteArray(data_);
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000378 if (counter_ != NULL) ++*counter_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000379 }
380
381 const uint16_t* data() const {
382 return data_;
383 }
384
385 size_t length() const {
386 return length_;
387 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000388
Steve Blocka7e24c12009-10-30 11:49:00 +0000389 private:
390 uint16_t* data_;
391 size_t length_;
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000392 int* counter_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000393 bool owning_data_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000394};
395
396
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000397class TestOneByteResource : public String::ExternalOneByteStringResource {
Steve Blocka7e24c12009-10-30 11:49:00 +0000398 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000399 explicit TestOneByteResource(const char* data, int* counter = NULL,
400 size_t offset = 0)
401 : orig_data_(data),
402 data_(data + offset),
403 length_(strlen(data) - offset),
404 counter_(counter) {}
Steve Blocka7e24c12009-10-30 11:49:00 +0000405
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000406 ~TestOneByteResource() {
407 i::DeleteArray(orig_data_);
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000408 if (counter_ != NULL) ++*counter_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000409 }
410
411 const char* data() const {
412 return data_;
413 }
414
415 size_t length() const {
416 return length_;
417 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000418
Steve Blocka7e24c12009-10-30 11:49:00 +0000419 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000420 const char* orig_data_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000421 const char* data_;
422 size_t length_;
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000423 int* counter_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000424};
425
426
Steve Blocka7e24c12009-10-30 11:49:00 +0000427THREADED_TEST(ScriptUsingStringResource) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000428 int dispose_count = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +0000429 const char* c_source = "1 + 2 * 3";
430 uint16_t* two_byte_source = AsciiToTwoByteString(c_source);
431 {
Steve Blocka7e24c12009-10-30 11:49:00 +0000432 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000433 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000434 TestResource* resource = new TestResource(two_byte_source, &dispose_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000435 Local<String> source =
436 String::NewExternalTwoByte(env->GetIsolate(), resource)
437 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000438 Local<Script> script = v8_compile(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000439 Local<Value> value = script->Run(env.local()).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +0000440 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000441 CHECK_EQ(7, value->Int32Value(env.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +0000442 CHECK(source->IsExternal());
443 CHECK_EQ(resource,
444 static_cast<TestResource*>(source->GetExternalStringResource()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000445 String::Encoding encoding = String::UNKNOWN_ENCODING;
446 CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
447 source->GetExternalStringResourceBase(&encoding));
448 CHECK_EQ(String::TWO_BYTE_ENCODING, encoding);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000449 CcTest::heap()->CollectAllGarbage();
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000450 CHECK_EQ(0, dispose_count);
Steve Blocka7e24c12009-10-30 11:49:00 +0000451 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000452 CcTest::i_isolate()->compilation_cache()->Clear();
453 CcTest::heap()->CollectAllAvailableGarbage();
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000454 CHECK_EQ(1, dispose_count);
Steve Blocka7e24c12009-10-30 11:49:00 +0000455}
456
457
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000458THREADED_TEST(ScriptUsingOneByteStringResource) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000459 int dispose_count = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +0000460 const char* c_source = "1 + 2 * 3";
461 {
Steve Blocka7e24c12009-10-30 11:49:00 +0000462 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000463 v8::HandleScope scope(env->GetIsolate());
464 TestOneByteResource* resource =
465 new TestOneByteResource(i::StrDup(c_source), &dispose_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000466 Local<String> source =
467 String::NewExternalOneByte(env->GetIsolate(), resource)
468 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000469 CHECK(source->IsExternalOneByte());
470 CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
471 source->GetExternalOneByteStringResource());
472 String::Encoding encoding = String::UNKNOWN_ENCODING;
473 CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
474 source->GetExternalStringResourceBase(&encoding));
475 CHECK_EQ(String::ONE_BYTE_ENCODING, encoding);
476 Local<Script> script = v8_compile(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000477 Local<Value> value = script->Run(env.local()).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +0000478 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000479 CHECK_EQ(7, value->Int32Value(env.local()).FromJust());
480 CcTest::heap()->CollectAllGarbage();
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000481 CHECK_EQ(0, dispose_count);
Steve Blocka7e24c12009-10-30 11:49:00 +0000482 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000483 CcTest::i_isolate()->compilation_cache()->Clear();
484 CcTest::heap()->CollectAllAvailableGarbage();
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000485 CHECK_EQ(1, dispose_count);
Steve Blocka7e24c12009-10-30 11:49:00 +0000486}
487
488
489THREADED_TEST(ScriptMakingExternalString) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000490 int dispose_count = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +0000491 uint16_t* two_byte_source = AsciiToTwoByteString("1 + 2 * 3");
492 {
Steve Blocka7e24c12009-10-30 11:49:00 +0000493 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000494 v8::HandleScope scope(env->GetIsolate());
495 Local<String> source =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000496 String::NewFromTwoByte(env->GetIsolate(), two_byte_source,
497 v8::NewStringType::kNormal)
498 .ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +0000499 // Trigger GCs so that the newly allocated string moves to old gen.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000500 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
501 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
502 CHECK_EQ(source->IsExternal(), false);
503 CHECK_EQ(source->IsExternalOneByte(), false);
504 String::Encoding encoding = String::UNKNOWN_ENCODING;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000505 CHECK(!source->GetExternalStringResourceBase(&encoding));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000506 CHECK_EQ(String::ONE_BYTE_ENCODING, encoding);
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000507 bool success = source->MakeExternal(new TestResource(two_byte_source,
508 &dispose_count));
Steve Blocka7e24c12009-10-30 11:49:00 +0000509 CHECK(success);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000510 Local<Script> script = v8_compile(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000511 Local<Value> value = script->Run(env.local()).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +0000512 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000513 CHECK_EQ(7, value->Int32Value(env.local()).FromJust());
514 CcTest::heap()->CollectAllGarbage();
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000515 CHECK_EQ(0, dispose_count);
Steve Blocka7e24c12009-10-30 11:49:00 +0000516 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000517 CcTest::i_isolate()->compilation_cache()->Clear();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000518 CcTest::heap()->CollectAllGarbage();
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000519 CHECK_EQ(1, dispose_count);
Steve Blocka7e24c12009-10-30 11:49:00 +0000520}
521
522
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000523THREADED_TEST(ScriptMakingExternalOneByteString) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000524 int dispose_count = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +0000525 const char* c_source = "1 + 2 * 3";
526 {
Steve Blocka7e24c12009-10-30 11:49:00 +0000527 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000528 v8::HandleScope scope(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +0000529 Local<String> source = v8_str(c_source);
Andrei Popescu402d9372010-02-26 13:31:12 +0000530 // Trigger GCs so that the newly allocated string moves to old gen.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000531 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
532 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
Steve Blocka7e24c12009-10-30 11:49:00 +0000533 bool success = source->MakeExternal(
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000534 new TestOneByteResource(i::StrDup(c_source), &dispose_count));
Steve Blocka7e24c12009-10-30 11:49:00 +0000535 CHECK(success);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000536 Local<Script> script = v8_compile(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000537 Local<Value> value = script->Run(env.local()).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +0000538 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000539 CHECK_EQ(7, value->Int32Value(env.local()).FromJust());
540 CcTest::heap()->CollectAllGarbage();
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000541 CHECK_EQ(0, dispose_count);
Steve Blocka7e24c12009-10-30 11:49:00 +0000542 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000543 CcTest::i_isolate()->compilation_cache()->Clear();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000544 CcTest::heap()->CollectAllGarbage();
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000545 CHECK_EQ(1, dispose_count);
Steve Blocka7e24c12009-10-30 11:49:00 +0000546}
547
548
Andrei Popescu402d9372010-02-26 13:31:12 +0000549TEST(MakingExternalStringConditions) {
Andrei Popescu402d9372010-02-26 13:31:12 +0000550 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000551 v8::HandleScope scope(env->GetIsolate());
Andrei Popescu402d9372010-02-26 13:31:12 +0000552
553 // Free some space in the new space so that we can check freshness.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000554 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
555 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
Andrei Popescu402d9372010-02-26 13:31:12 +0000556
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100557 uint16_t* two_byte_string = AsciiToTwoByteString("s1");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000558 Local<String> small_string =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000559 String::NewFromTwoByte(env->GetIsolate(), two_byte_string,
560 v8::NewStringType::kNormal)
561 .ToLocalChecked();
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100562 i::DeleteArray(two_byte_string);
563
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000564 // We should refuse to externalize small strings.
Andrei Popescu402d9372010-02-26 13:31:12 +0000565 CHECK(!small_string->CanMakeExternal());
566 // Trigger GCs so that the newly allocated string moves to old gen.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000567 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
568 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
Andrei Popescu402d9372010-02-26 13:31:12 +0000569 // Old space strings should be accepted.
570 CHECK(small_string->CanMakeExternal());
571
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100572 two_byte_string = AsciiToTwoByteString("small string 2");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000573 small_string = String::NewFromTwoByte(env->GetIsolate(), two_byte_string,
574 v8::NewStringType::kNormal)
575 .ToLocalChecked();
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100576 i::DeleteArray(two_byte_string);
577
Andrei Popescu402d9372010-02-26 13:31:12 +0000578 const int buf_size = 10 * 1024;
579 char* buf = i::NewArray<char>(buf_size);
580 memset(buf, 'a', buf_size);
581 buf[buf_size - 1] = '\0';
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100582
583 two_byte_string = AsciiToTwoByteString(buf);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000584 Local<String> large_string =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000585 String::NewFromTwoByte(env->GetIsolate(), two_byte_string,
586 v8::NewStringType::kNormal)
587 .ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +0000588 i::DeleteArray(buf);
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100589 i::DeleteArray(two_byte_string);
Andrei Popescu402d9372010-02-26 13:31:12 +0000590 // Large strings should be immediately accepted.
591 CHECK(large_string->CanMakeExternal());
592}
593
594
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000595TEST(MakingExternalOneByteStringConditions) {
Andrei Popescu402d9372010-02-26 13:31:12 +0000596 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000597 v8::HandleScope scope(env->GetIsolate());
Andrei Popescu402d9372010-02-26 13:31:12 +0000598
599 // Free some space in the new space so that we can check freshness.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000600 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
601 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
Andrei Popescu402d9372010-02-26 13:31:12 +0000602
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000603 Local<String> small_string = v8_str("s1");
604 // We should refuse to externalize small strings.
Andrei Popescu402d9372010-02-26 13:31:12 +0000605 CHECK(!small_string->CanMakeExternal());
606 // Trigger GCs so that the newly allocated string moves to old gen.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000607 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
608 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
Andrei Popescu402d9372010-02-26 13:31:12 +0000609 // Old space strings should be accepted.
610 CHECK(small_string->CanMakeExternal());
611
Andrei Popescu402d9372010-02-26 13:31:12 +0000612 const int buf_size = 10 * 1024;
613 char* buf = i::NewArray<char>(buf_size);
614 memset(buf, 'a', buf_size);
615 buf[buf_size - 1] = '\0';
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000616 Local<String> large_string = v8_str(buf);
Andrei Popescu402d9372010-02-26 13:31:12 +0000617 i::DeleteArray(buf);
618 // Large strings should be immediately accepted.
619 CHECK(large_string->CanMakeExternal());
620}
621
622
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000623TEST(MakingExternalUnalignedOneByteString) {
624 LocalContext env;
625 v8::HandleScope scope(env->GetIsolate());
626
627 CompileRun("function cons(a, b) { return a + b; }"
628 "function slice(a) { return a.substring(1); }");
629 // Create a cons string that will land in old pointer space.
630 Local<String> cons = Local<String>::Cast(CompileRun(
631 "cons('abcdefghijklm', 'nopqrstuvwxyz');"));
632 // Create a sliced string that will land in old pointer space.
633 Local<String> slice = Local<String>::Cast(CompileRun(
634 "slice('abcdefghijklmnopqrstuvwxyz');"));
635
636 // Trigger GCs so that the newly allocated string moves to old gen.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000637 SimulateFullSpace(CcTest::heap()->old_space());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000638 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
639 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
640
641 // Turn into external string with unaligned resource data.
642 const char* c_cons = "_abcdefghijklmnopqrstuvwxyz";
643 bool success =
644 cons->MakeExternal(new TestOneByteResource(i::StrDup(c_cons), NULL, 1));
645 CHECK(success);
646 const char* c_slice = "_bcdefghijklmnopqrstuvwxyz";
647 success =
648 slice->MakeExternal(new TestOneByteResource(i::StrDup(c_slice), NULL, 1));
649 CHECK(success);
650
651 // Trigger GCs and force evacuation.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000652 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000653 CcTest::heap()->CollectAllGarbage(i::Heap::kReduceMemoryFootprintMask);
Steve Blocka7e24c12009-10-30 11:49:00 +0000654}
655
656
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000657THREADED_TEST(UsingExternalString) {
658 i::Factory* factory = CcTest::i_isolate()->factory();
Steve Blocka7e24c12009-10-30 11:49:00 +0000659 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000660 v8::HandleScope scope(CcTest::isolate());
661 uint16_t* two_byte_string = AsciiToTwoByteString("test string");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000662 Local<String> string =
663 String::NewExternalTwoByte(CcTest::isolate(),
664 new TestResource(two_byte_string))
665 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +0000666 i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
667 // Trigger GCs so that the newly allocated string moves to old gen.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000668 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
669 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
670 i::Handle<i::String> isymbol =
671 factory->InternalizeString(istring);
672 CHECK(isymbol->IsInternalizedString());
Steve Blocka7e24c12009-10-30 11:49:00 +0000673 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000674 CcTest::heap()->CollectAllGarbage();
675 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000676}
677
678
679THREADED_TEST(UsingExternalOneByteString) {
680 i::Factory* factory = CcTest::i_isolate()->factory();
681 {
682 v8::HandleScope scope(CcTest::isolate());
683 const char* one_byte_string = "test string";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000684 Local<String> string =
685 String::NewExternalOneByte(
686 CcTest::isolate(),
687 new TestOneByteResource(i::StrDup(one_byte_string)))
688 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000689 i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
690 // Trigger GCs so that the newly allocated string moves to old gen.
691 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
692 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
693 i::Handle<i::String> isymbol =
694 factory->InternalizeString(istring);
695 CHECK(isymbol->IsInternalizedString());
696 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000697 CcTest::heap()->CollectAllGarbage();
698 CcTest::heap()->CollectAllGarbage();
Steve Blocka7e24c12009-10-30 11:49:00 +0000699}
700
701
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400702class RandomLengthResource : public v8::String::ExternalStringResource {
703 public:
704 explicit RandomLengthResource(int length) : length_(length) {}
705 virtual const uint16_t* data() const { return string_; }
706 virtual size_t length() const { return length_; }
707
708 private:
709 uint16_t string_[10];
710 int length_;
711};
712
713
714class RandomLengthOneByteResource
715 : public v8::String::ExternalOneByteStringResource {
716 public:
717 explicit RandomLengthOneByteResource(int length) : length_(length) {}
718 virtual const char* data() const { return string_; }
719 virtual size_t length() const { return length_; }
720
721 private:
722 char string_[10];
723 int length_;
724};
725
726
727THREADED_TEST(NewExternalForVeryLongString) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000728 auto isolate = CcTest::isolate();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400729 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000730 v8::HandleScope scope(isolate);
731 v8::TryCatch try_catch(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400732 RandomLengthOneByteResource r(1 << 30);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000733 v8::MaybeLocal<v8::String> maybe_str =
734 v8::String::NewExternalOneByte(isolate, &r);
735 CHECK(maybe_str.IsEmpty());
736 CHECK(!try_catch.HasCaught());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400737 }
738
739 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000740 v8::HandleScope scope(isolate);
741 v8::TryCatch try_catch(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400742 RandomLengthResource r(1 << 30);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000743 v8::MaybeLocal<v8::String> maybe_str =
744 v8::String::NewExternalTwoByte(isolate, &r);
745 CHECK(maybe_str.IsEmpty());
746 CHECK(!try_catch.HasCaught());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400747 }
748}
749
750
Leon Clarkee46be812010-01-19 14:06:41 +0000751THREADED_TEST(ScavengeExternalString) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000752 i::FLAG_stress_compaction = false;
753 i::FLAG_gc_global = false;
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000754 int dispose_count = 0;
Steve Block6ded16b2010-05-10 14:33:55 +0100755 bool in_new_space = false;
Leon Clarkee46be812010-01-19 14:06:41 +0000756 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000757 v8::HandleScope scope(CcTest::isolate());
Leon Clarkee46be812010-01-19 14:06:41 +0000758 uint16_t* two_byte_string = AsciiToTwoByteString("test string");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000759 Local<String> string =
760 String::NewExternalTwoByte(
761 CcTest::isolate(),
762 new TestResource(two_byte_string, &dispose_count))
763 .ToLocalChecked();
Leon Clarkee46be812010-01-19 14:06:41 +0000764 i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000765 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
766 in_new_space = CcTest::heap()->InNewSpace(*istring);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000767 CHECK(in_new_space || CcTest::heap()->old_space()->Contains(*istring));
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000768 CHECK_EQ(0, dispose_count);
Leon Clarkee46be812010-01-19 14:06:41 +0000769 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000770 CcTest::heap()->CollectGarbage(in_new_space ? i::NEW_SPACE : i::OLD_SPACE);
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000771 CHECK_EQ(1, dispose_count);
Leon Clarkee46be812010-01-19 14:06:41 +0000772}
773
774
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000775THREADED_TEST(ScavengeExternalOneByteString) {
776 i::FLAG_stress_compaction = false;
777 i::FLAG_gc_global = false;
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000778 int dispose_count = 0;
Steve Block6ded16b2010-05-10 14:33:55 +0100779 bool in_new_space = false;
Leon Clarkee46be812010-01-19 14:06:41 +0000780 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000781 v8::HandleScope scope(CcTest::isolate());
Leon Clarkee46be812010-01-19 14:06:41 +0000782 const char* one_byte_string = "test string";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000783 Local<String> string =
784 String::NewExternalOneByte(
785 CcTest::isolate(),
786 new TestOneByteResource(i::StrDup(one_byte_string), &dispose_count))
787 .ToLocalChecked();
Leon Clarkee46be812010-01-19 14:06:41 +0000788 i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000789 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
790 in_new_space = CcTest::heap()->InNewSpace(*istring);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000791 CHECK(in_new_space || CcTest::heap()->old_space()->Contains(*istring));
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000792 CHECK_EQ(0, dispose_count);
Leon Clarkee46be812010-01-19 14:06:41 +0000793 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000794 CcTest::heap()->CollectGarbage(in_new_space ? i::NEW_SPACE : i::OLD_SPACE);
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000795 CHECK_EQ(1, dispose_count);
Leon Clarkee46be812010-01-19 14:06:41 +0000796}
797
798
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000799class TestOneByteResourceWithDisposeControl : public TestOneByteResource {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100800 public:
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000801 // Only used by non-threaded tests, so it can use static fields.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100802 static int dispose_calls;
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000803 static int dispose_count;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100804
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000805 TestOneByteResourceWithDisposeControl(const char* data, bool dispose)
806 : TestOneByteResource(data, &dispose_count), dispose_(dispose) {}
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100807
808 void Dispose() {
809 ++dispose_calls;
810 if (dispose_) delete this;
811 }
812 private:
813 bool dispose_;
814};
815
816
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000817int TestOneByteResourceWithDisposeControl::dispose_count = 0;
818int TestOneByteResourceWithDisposeControl::dispose_calls = 0;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100819
820
821TEST(ExternalStringWithDisposeHandling) {
822 const char* c_source = "1 + 2 * 3";
823
824 // Use a stack allocated external string resource allocated object.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000825 TestOneByteResourceWithDisposeControl::dispose_count = 0;
826 TestOneByteResourceWithDisposeControl::dispose_calls = 0;
827 TestOneByteResourceWithDisposeControl res_stack(i::StrDup(c_source), false);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100828 {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100829 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000830 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000831 Local<String> source =
832 String::NewExternalOneByte(env->GetIsolate(), &res_stack)
833 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000834 Local<Script> script = v8_compile(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000835 Local<Value> value = script->Run(env.local()).ToLocalChecked();
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100836 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000837 CHECK_EQ(7, value->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000838 CcTest::heap()->CollectAllAvailableGarbage();
839 CHECK_EQ(0, TestOneByteResourceWithDisposeControl::dispose_count);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100840 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000841 CcTest::i_isolate()->compilation_cache()->Clear();
842 CcTest::heap()->CollectAllAvailableGarbage();
843 CHECK_EQ(1, TestOneByteResourceWithDisposeControl::dispose_calls);
844 CHECK_EQ(0, TestOneByteResourceWithDisposeControl::dispose_count);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100845
846 // Use a heap allocated external string resource allocated object.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000847 TestOneByteResourceWithDisposeControl::dispose_count = 0;
848 TestOneByteResourceWithDisposeControl::dispose_calls = 0;
849 TestOneByteResource* res_heap =
850 new TestOneByteResourceWithDisposeControl(i::StrDup(c_source), true);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100851 {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100852 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000853 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000854 Local<String> source =
855 String::NewExternalOneByte(env->GetIsolate(), res_heap)
856 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000857 Local<Script> script = v8_compile(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000858 Local<Value> value = script->Run(env.local()).ToLocalChecked();
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100859 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000860 CHECK_EQ(7, value->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000861 CcTest::heap()->CollectAllAvailableGarbage();
862 CHECK_EQ(0, TestOneByteResourceWithDisposeControl::dispose_count);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100863 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000864 CcTest::i_isolate()->compilation_cache()->Clear();
865 CcTest::heap()->CollectAllAvailableGarbage();
866 CHECK_EQ(1, TestOneByteResourceWithDisposeControl::dispose_calls);
867 CHECK_EQ(1, TestOneByteResourceWithDisposeControl::dispose_count);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100868}
869
870
Steve Block3ce2e202009-11-05 08:53:23 +0000871THREADED_TEST(StringConcat) {
872 {
Steve Block3ce2e202009-11-05 08:53:23 +0000873 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000874 v8::HandleScope scope(env->GetIsolate());
Steve Block3ce2e202009-11-05 08:53:23 +0000875 const char* one_byte_string_1 = "function a_times_t";
876 const char* two_byte_string_1 = "wo_plus_b(a, b) {return ";
877 const char* one_byte_extern_1 = "a * 2 + b;} a_times_two_plus_b(4, 8) + ";
878 const char* two_byte_extern_1 = "a_times_two_plus_b(4, 8) + ";
879 const char* one_byte_string_2 = "a_times_two_plus_b(4, 8) + ";
880 const char* two_byte_string_2 = "a_times_two_plus_b(4, 8) + ";
881 const char* two_byte_extern_2 = "a_times_two_plus_b(1, 2);";
882 Local<String> left = v8_str(one_byte_string_1);
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100883
884 uint16_t* two_byte_source = AsciiToTwoByteString(two_byte_string_1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000885 Local<String> right =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000886 String::NewFromTwoByte(env->GetIsolate(), two_byte_source,
887 v8::NewStringType::kNormal)
888 .ToLocalChecked();
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100889 i::DeleteArray(two_byte_source);
890
Steve Block3ce2e202009-11-05 08:53:23 +0000891 Local<String> source = String::Concat(left, right);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000892 right = String::NewExternalOneByte(
893 env->GetIsolate(),
894 new TestOneByteResource(i::StrDup(one_byte_extern_1)))
895 .ToLocalChecked();
Steve Block3ce2e202009-11-05 08:53:23 +0000896 source = String::Concat(source, right);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000897 right = String::NewExternalTwoByte(
898 env->GetIsolate(),
899 new TestResource(AsciiToTwoByteString(two_byte_extern_1)))
900 .ToLocalChecked();
Steve Block3ce2e202009-11-05 08:53:23 +0000901 source = String::Concat(source, right);
902 right = v8_str(one_byte_string_2);
903 source = String::Concat(source, right);
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100904
905 two_byte_source = AsciiToTwoByteString(two_byte_string_2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000906 right = String::NewFromTwoByte(env->GetIsolate(), two_byte_source,
907 v8::NewStringType::kNormal)
908 .ToLocalChecked();
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100909 i::DeleteArray(two_byte_source);
910
Steve Block3ce2e202009-11-05 08:53:23 +0000911 source = String::Concat(source, right);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000912 right = String::NewExternalTwoByte(
913 env->GetIsolate(),
914 new TestResource(AsciiToTwoByteString(two_byte_extern_2)))
915 .ToLocalChecked();
Steve Block3ce2e202009-11-05 08:53:23 +0000916 source = String::Concat(source, right);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000917 Local<Script> script = v8_compile(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000918 Local<Value> value = script->Run(env.local()).ToLocalChecked();
Steve Block3ce2e202009-11-05 08:53:23 +0000919 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000920 CHECK_EQ(68, value->Int32Value(env.local()).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +0000921 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000922 CcTest::i_isolate()->compilation_cache()->Clear();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000923 CcTest::heap()->CollectAllGarbage();
924 CcTest::heap()->CollectAllGarbage();
Steve Block3ce2e202009-11-05 08:53:23 +0000925}
926
927
Steve Blocka7e24c12009-10-30 11:49:00 +0000928THREADED_TEST(GlobalProperties) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000929 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000930 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000931 v8::Local<v8::Object> global = env->Global();
932 CHECK(global->Set(env.local(), v8_str("pi"), v8_num(3.1415926)).FromJust());
933 Local<Value> pi = global->Get(env.local(), v8_str("pi")).ToLocalChecked();
934 CHECK_EQ(3.1415926, pi->NumberValue(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000935}
936
937
938static void handle_callback_impl(const v8::FunctionCallbackInfo<Value>& info,
939 i::Address callback) {
940 ApiTestFuzzer::Fuzz();
941 CheckReturnValue(info, callback);
942 info.GetReturnValue().Set(v8_str("bad value"));
943 info.GetReturnValue().Set(v8_num(102));
944}
945
946
947static void handle_callback(const v8::FunctionCallbackInfo<Value>& info) {
948 return handle_callback_impl(info, FUNCTION_ADDR(handle_callback));
949}
950
951
952static void handle_callback_2(const v8::FunctionCallbackInfo<Value>& info) {
953 return handle_callback_impl(info, FUNCTION_ADDR(handle_callback_2));
954}
955
956static void construct_callback(
957 const v8::FunctionCallbackInfo<Value>& info) {
958 ApiTestFuzzer::Fuzz();
959 CheckReturnValue(info, FUNCTION_ADDR(construct_callback));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000960 CHECK(
961 info.This()
962 ->Set(info.GetIsolate()->GetCurrentContext(), v8_str("x"), v8_num(1))
963 .FromJust());
964 CHECK(
965 info.This()
966 ->Set(info.GetIsolate()->GetCurrentContext(), v8_str("y"), v8_num(2))
967 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000968 info.GetReturnValue().Set(v8_str("bad value"));
969 info.GetReturnValue().Set(info.This());
970}
971
972
973static void Return239Callback(
974 Local<String> name, const v8::PropertyCallbackInfo<Value>& info) {
975 ApiTestFuzzer::Fuzz();
976 CheckReturnValue(info, FUNCTION_ADDR(Return239Callback));
977 info.GetReturnValue().Set(v8_str("bad value"));
978 info.GetReturnValue().Set(v8_num(239));
979}
980
981
982template<typename Handler>
983static void TestFunctionTemplateInitializer(Handler handler,
984 Handler handler_2) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000985 // Test constructor calls.
986 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000987 LocalContext env;
988 v8::Isolate* isolate = env->GetIsolate();
989 v8::HandleScope scope(isolate);
990
Steve Blocka7e24c12009-10-30 11:49:00 +0000991 Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000992 v8::FunctionTemplate::New(isolate, handler);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000993 Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
994 CHECK(env->Global()->Set(env.local(), v8_str("obj"), fun).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000995 Local<Script> script = v8_compile("obj()");
996 for (int i = 0; i < 30; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000997 CHECK_EQ(102, v8_run_int32value(script));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000998 }
999 }
1000 // Use SetCallHandler to initialize a function template, should work like
1001 // the previous one.
1002 {
1003 LocalContext env;
1004 v8::Isolate* isolate = env->GetIsolate();
1005 v8::HandleScope scope(isolate);
1006
1007 Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(isolate);
1008 fun_templ->SetCallHandler(handler_2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001009 Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
1010 CHECK(env->Global()->Set(env.local(), v8_str("obj"), fun).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001011 Local<Script> script = v8_compile("obj()");
1012 for (int i = 0; i < 30; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001013 CHECK_EQ(102, v8_run_int32value(script));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001014 }
1015 }
1016}
1017
1018
1019template<typename Constructor, typename Accessor>
1020static void TestFunctionTemplateAccessor(Constructor constructor,
1021 Accessor accessor) {
1022 LocalContext env;
1023 v8::HandleScope scope(env->GetIsolate());
1024
1025 Local<v8::FunctionTemplate> fun_templ =
1026 v8::FunctionTemplate::New(env->GetIsolate(), constructor);
1027 fun_templ->SetClassName(v8_str("funky"));
1028 fun_templ->InstanceTemplate()->SetAccessor(v8_str("m"), accessor);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001029 Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
1030 CHECK(env->Global()->Set(env.local(), v8_str("obj"), fun).FromJust());
1031 Local<Value> result =
1032 v8_compile("(new obj()).toString()")->Run(env.local()).ToLocalChecked();
1033 CHECK(v8_str("[object funky]")->Equals(env.local(), result).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001034 CompileRun("var obj_instance = new obj();");
1035 Local<Script> script;
1036 script = v8_compile("obj_instance.x");
1037 for (int i = 0; i < 30; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001038 CHECK_EQ(1, v8_run_int32value(script));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001039 }
1040 script = v8_compile("obj_instance.m");
1041 for (int i = 0; i < 30; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001042 CHECK_EQ(239, v8_run_int32value(script));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001043 }
1044}
Steve Blocka7e24c12009-10-30 11:49:00 +00001045
Ben Murdochf87a2032010-10-22 12:50:53 +01001046
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001047THREADED_PROFILED_TEST(FunctionTemplate) {
1048 TestFunctionTemplateInitializer(handle_callback, handle_callback_2);
1049 TestFunctionTemplateAccessor(construct_callback, Return239Callback);
1050}
1051
1052
1053static void SimpleCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
1054 ApiTestFuzzer::Fuzz();
1055 CheckReturnValue(info, FUNCTION_ADDR(SimpleCallback));
1056 info.GetReturnValue().Set(v8_num(51423 + info.Length()));
1057}
1058
1059
1060template<typename Callback>
1061static void TestSimpleCallback(Callback callback) {
1062 LocalContext env;
1063 v8::Isolate* isolate = env->GetIsolate();
1064 v8::HandleScope scope(isolate);
1065
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001066 v8::Local<v8::ObjectTemplate> object_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001067 v8::ObjectTemplate::New(isolate);
1068 object_template->Set(isolate, "callback",
1069 v8::FunctionTemplate::New(isolate, callback));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001070 v8::Local<v8::Object> object =
1071 object_template->NewInstance(env.local()).ToLocalChecked();
1072 CHECK((*env)
1073 ->Global()
1074 ->Set(env.local(), v8_str("callback_object"), object)
1075 .FromJust());
1076 v8::Local<v8::Script> script;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001077 script = v8_compile("callback_object.callback(17)");
1078 for (int i = 0; i < 30; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001079 CHECK_EQ(51424, v8_run_int32value(script));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001080 }
1081 script = v8_compile("callback_object.callback(17, 24)");
1082 for (int i = 0; i < 30; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001083 CHECK_EQ(51425, v8_run_int32value(script));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001084 }
1085}
1086
1087
1088THREADED_PROFILED_TEST(SimpleCallback) {
1089 TestSimpleCallback(SimpleCallback);
1090}
1091
1092
1093template<typename T>
1094void FastReturnValueCallback(const v8::FunctionCallbackInfo<v8::Value>& info);
1095
1096// constant return values
1097static int32_t fast_return_value_int32 = 471;
1098static uint32_t fast_return_value_uint32 = 571;
1099static const double kFastReturnValueDouble = 2.7;
1100// variable return values
1101static bool fast_return_value_bool = false;
1102enum ReturnValueOddball {
1103 kNullReturnValue,
1104 kUndefinedReturnValue,
1105 kEmptyStringReturnValue
1106};
1107static ReturnValueOddball fast_return_value_void;
1108static bool fast_return_value_object_is_empty = false;
1109
1110// Helper function to avoid compiler error: insufficient contextual information
1111// to determine type when applying FUNCTION_ADDR to a template function.
1112static i::Address address_of(v8::FunctionCallback callback) {
1113 return FUNCTION_ADDR(callback);
1114}
1115
1116template<>
1117void FastReturnValueCallback<int32_t>(
1118 const v8::FunctionCallbackInfo<v8::Value>& info) {
1119 CheckReturnValue(info, address_of(FastReturnValueCallback<int32_t>));
1120 info.GetReturnValue().Set(fast_return_value_int32);
1121}
1122
1123template<>
1124void FastReturnValueCallback<uint32_t>(
1125 const v8::FunctionCallbackInfo<v8::Value>& info) {
1126 CheckReturnValue(info, address_of(FastReturnValueCallback<uint32_t>));
1127 info.GetReturnValue().Set(fast_return_value_uint32);
1128}
1129
1130template<>
1131void FastReturnValueCallback<double>(
1132 const v8::FunctionCallbackInfo<v8::Value>& info) {
1133 CheckReturnValue(info, address_of(FastReturnValueCallback<double>));
1134 info.GetReturnValue().Set(kFastReturnValueDouble);
1135}
1136
1137template<>
1138void FastReturnValueCallback<bool>(
1139 const v8::FunctionCallbackInfo<v8::Value>& info) {
1140 CheckReturnValue(info, address_of(FastReturnValueCallback<bool>));
1141 info.GetReturnValue().Set(fast_return_value_bool);
1142}
1143
1144template<>
1145void FastReturnValueCallback<void>(
1146 const v8::FunctionCallbackInfo<v8::Value>& info) {
1147 CheckReturnValue(info, address_of(FastReturnValueCallback<void>));
1148 switch (fast_return_value_void) {
1149 case kNullReturnValue:
1150 info.GetReturnValue().SetNull();
1151 break;
1152 case kUndefinedReturnValue:
1153 info.GetReturnValue().SetUndefined();
1154 break;
1155 case kEmptyStringReturnValue:
1156 info.GetReturnValue().SetEmptyString();
1157 break;
1158 }
1159}
1160
1161template<>
1162void FastReturnValueCallback<Object>(
1163 const v8::FunctionCallbackInfo<v8::Value>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001164 v8::Local<v8::Object> object;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001165 if (!fast_return_value_object_is_empty) {
1166 object = Object::New(info.GetIsolate());
1167 }
1168 info.GetReturnValue().Set(object);
1169}
1170
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001171template <typename T>
1172Local<Value> TestFastReturnValues() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001173 LocalContext env;
1174 v8::Isolate* isolate = env->GetIsolate();
1175 v8::EscapableHandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001176 v8::Local<v8::ObjectTemplate> object_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001177 v8::ObjectTemplate::New(isolate);
1178 v8::FunctionCallback callback = &FastReturnValueCallback<T>;
1179 object_template->Set(isolate, "callback",
1180 v8::FunctionTemplate::New(isolate, callback));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001181 v8::Local<v8::Object> object =
1182 object_template->NewInstance(env.local()).ToLocalChecked();
1183 CHECK((*env)
1184 ->Global()
1185 ->Set(env.local(), v8_str("callback_object"), object)
1186 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001187 return scope.Escape(CompileRun("callback_object.callback()"));
1188}
1189
1190
1191THREADED_PROFILED_TEST(FastReturnValues) {
1192 LocalContext env;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001193 v8::Isolate* isolate = env->GetIsolate();
1194 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001195 v8::Local<v8::Value> value;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001196 // check int32_t and uint32_t
1197 int32_t int_values[] = {
1198 0, 234, -723,
1199 i::Smi::kMinValue, i::Smi::kMaxValue
1200 };
1201 for (size_t i = 0; i < arraysize(int_values); i++) {
1202 for (int modifier = -1; modifier <= 1; modifier++) {
1203 int int_value = int_values[i] + modifier;
1204 // check int32_t
1205 fast_return_value_int32 = int_value;
1206 value = TestFastReturnValues<int32_t>();
1207 CHECK(value->IsInt32());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001208 CHECK_EQ(fast_return_value_int32,
1209 value->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001210 // check uint32_t
1211 fast_return_value_uint32 = static_cast<uint32_t>(int_value);
1212 value = TestFastReturnValues<uint32_t>();
1213 CHECK(value->IsUint32());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001214 CHECK_EQ(fast_return_value_uint32,
1215 value->Uint32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001216 }
1217 }
1218 // check double
1219 value = TestFastReturnValues<double>();
1220 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001221 CHECK_EQ(kFastReturnValueDouble,
1222 value->ToNumber(env.local()).ToLocalChecked()->Value());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001223 // check bool values
1224 for (int i = 0; i < 2; i++) {
1225 fast_return_value_bool = i == 0;
1226 value = TestFastReturnValues<bool>();
1227 CHECK(value->IsBoolean());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001228 CHECK_EQ(fast_return_value_bool,
1229 value->ToBoolean(env.local()).ToLocalChecked()->Value());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001230 }
1231 // check oddballs
1232 ReturnValueOddball oddballs[] = {
1233 kNullReturnValue,
1234 kUndefinedReturnValue,
1235 kEmptyStringReturnValue
1236 };
1237 for (size_t i = 0; i < arraysize(oddballs); i++) {
1238 fast_return_value_void = oddballs[i];
1239 value = TestFastReturnValues<void>();
1240 switch (fast_return_value_void) {
1241 case kNullReturnValue:
1242 CHECK(value->IsNull());
1243 break;
1244 case kUndefinedReturnValue:
1245 CHECK(value->IsUndefined());
1246 break;
1247 case kEmptyStringReturnValue:
1248 CHECK(value->IsString());
1249 CHECK_EQ(0, v8::String::Cast(*value)->Length());
1250 break;
1251 }
1252 }
1253 // check handles
1254 fast_return_value_object_is_empty = false;
1255 value = TestFastReturnValues<Object>();
1256 CHECK(value->IsObject());
1257 fast_return_value_object_is_empty = true;
1258 value = TestFastReturnValues<Object>();
1259 CHECK(value->IsUndefined());
1260}
1261
1262
1263THREADED_TEST(FunctionTemplateSetLength) {
1264 LocalContext env;
1265 v8::Isolate* isolate = env->GetIsolate();
1266 v8::HandleScope scope(isolate);
1267 {
1268 Local<v8::FunctionTemplate> fun_templ =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001269 v8::FunctionTemplate::New(isolate, handle_callback, Local<v8::Value>(),
1270 Local<v8::Signature>(), 23);
1271 Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
1272 CHECK(env->Global()->Set(env.local(), v8_str("obj"), fun).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001273 Local<Script> script = v8_compile("obj.length");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001274 CHECK_EQ(23, v8_run_int32value(script));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001275 }
1276 {
1277 Local<v8::FunctionTemplate> fun_templ =
1278 v8::FunctionTemplate::New(isolate, handle_callback);
1279 fun_templ->SetLength(22);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001280 Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
1281 CHECK(env->Global()->Set(env.local(), v8_str("obj"), fun).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001282 Local<Script> script = v8_compile("obj.length");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001283 CHECK_EQ(22, v8_run_int32value(script));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001284 }
1285 {
1286 // Without setting length it defaults to 0.
1287 Local<v8::FunctionTemplate> fun_templ =
1288 v8::FunctionTemplate::New(isolate, handle_callback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001289 Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
1290 CHECK(env->Global()->Set(env.local(), v8_str("obj"), fun).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001291 Local<Script> script = v8_compile("obj.length");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001292 CHECK_EQ(0, v8_run_int32value(script));
Steve Blocka7e24c12009-10-30 11:49:00 +00001293 }
1294}
1295
1296
Ben Murdochb8e0da22011-05-16 14:20:40 +01001297static void* expected_ptr;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001298static void callback(const v8::FunctionCallbackInfo<v8::Value>& args) {
1299 void* ptr = v8::External::Cast(*args.Data())->Value();
Ben Murdochb8e0da22011-05-16 14:20:40 +01001300 CHECK_EQ(expected_ptr, ptr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001301 args.GetReturnValue().Set(true);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001302}
1303
1304
1305static void TestExternalPointerWrapping() {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001306 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001307 v8::Isolate* isolate = env->GetIsolate();
1308 v8::HandleScope scope(isolate);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001309
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001310 v8::Local<v8::Value> data = v8::External::New(isolate, expected_ptr);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001311
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001312 v8::Local<v8::Object> obj = v8::Object::New(isolate);
1313 CHECK(obj->Set(env.local(), v8_str("func"),
1314 v8::FunctionTemplate::New(isolate, callback, data)
1315 ->GetFunction(env.local())
1316 .ToLocalChecked())
1317 .FromJust());
1318 CHECK(env->Global()->Set(env.local(), v8_str("obj"), obj).FromJust());
Ben Murdochb8e0da22011-05-16 14:20:40 +01001319
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001320 CHECK(CompileRun("function foo() {\n"
1321 " for (var i = 0; i < 13; i++) obj.func();\n"
1322 "}\n"
1323 "foo(), true")
1324 ->BooleanValue(env.local())
1325 .FromJust());
Ben Murdochb8e0da22011-05-16 14:20:40 +01001326}
1327
1328
1329THREADED_TEST(ExternalWrap) {
1330 // Check heap allocated object.
1331 int* ptr = new int;
1332 expected_ptr = ptr;
1333 TestExternalPointerWrapping();
1334 delete ptr;
1335
1336 // Check stack allocated object.
1337 int foo;
1338 expected_ptr = &foo;
1339 TestExternalPointerWrapping();
1340
1341 // Check not aligned addresses.
1342 const int n = 100;
1343 char* s = new char[n];
1344 for (int i = 0; i < n; i++) {
1345 expected_ptr = s + i;
1346 TestExternalPointerWrapping();
1347 }
1348
1349 delete[] s;
1350
1351 // Check several invalid addresses.
1352 expected_ptr = reinterpret_cast<void*>(1);
1353 TestExternalPointerWrapping();
1354
1355 expected_ptr = reinterpret_cast<void*>(0xdeadbeef);
1356 TestExternalPointerWrapping();
1357
1358 expected_ptr = reinterpret_cast<void*>(0xdeadbeef + 1);
1359 TestExternalPointerWrapping();
1360
1361#if defined(V8_HOST_ARCH_X64)
Steve Block1e0659c2011-05-24 12:43:12 +01001362 // Check a value with a leading 1 bit in x64 Smi encoding.
1363 expected_ptr = reinterpret_cast<void*>(0x400000000);
1364 TestExternalPointerWrapping();
1365
Ben Murdochb8e0da22011-05-16 14:20:40 +01001366 expected_ptr = reinterpret_cast<void*>(0xdeadbeefdeadbeef);
1367 TestExternalPointerWrapping();
1368
1369 expected_ptr = reinterpret_cast<void*>(0xdeadbeefdeadbeef + 1);
1370 TestExternalPointerWrapping();
1371#endif
1372}
1373
1374
Steve Blocka7e24c12009-10-30 11:49:00 +00001375THREADED_TEST(FindInstanceInPrototypeChain) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001376 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001377 v8::Isolate* isolate = env->GetIsolate();
1378 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001379
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001380 Local<v8::FunctionTemplate> base = v8::FunctionTemplate::New(isolate);
1381 Local<v8::FunctionTemplate> derived = v8::FunctionTemplate::New(isolate);
1382 Local<v8::FunctionTemplate> other = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001383 derived->Inherit(base);
1384
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001385 Local<v8::Function> base_function =
1386 base->GetFunction(env.local()).ToLocalChecked();
1387 Local<v8::Function> derived_function =
1388 derived->GetFunction(env.local()).ToLocalChecked();
1389 Local<v8::Function> other_function =
1390 other->GetFunction(env.local()).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001391
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001392 Local<v8::Object> base_instance =
1393 base_function->NewInstance(env.local()).ToLocalChecked();
1394 Local<v8::Object> derived_instance =
1395 derived_function->NewInstance(env.local()).ToLocalChecked();
1396 Local<v8::Object> derived_instance2 =
1397 derived_function->NewInstance(env.local()).ToLocalChecked();
1398 Local<v8::Object> other_instance =
1399 other_function->NewInstance(env.local()).ToLocalChecked();
1400 CHECK(
1401 derived_instance2->Set(env.local(), v8_str("__proto__"), derived_instance)
1402 .FromJust());
1403 CHECK(other_instance->Set(env.local(), v8_str("__proto__"), derived_instance2)
1404 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00001405
1406 // base_instance is only an instance of base.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001407 CHECK(base_instance->Equals(env.local(),
1408 base_instance->FindInstanceInPrototypeChain(base))
1409 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00001410 CHECK(base_instance->FindInstanceInPrototypeChain(derived).IsEmpty());
1411 CHECK(base_instance->FindInstanceInPrototypeChain(other).IsEmpty());
1412
1413 // derived_instance is an instance of base and derived.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001414 CHECK(derived_instance->Equals(env.local(),
1415 derived_instance->FindInstanceInPrototypeChain(
1416 base))
1417 .FromJust());
1418 CHECK(derived_instance->Equals(env.local(),
1419 derived_instance->FindInstanceInPrototypeChain(
1420 derived))
1421 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00001422 CHECK(derived_instance->FindInstanceInPrototypeChain(other).IsEmpty());
1423
1424 // other_instance is an instance of other and its immediate
1425 // prototype derived_instance2 is an instance of base and derived.
1426 // Note, derived_instance is an instance of base and derived too,
1427 // but it comes after derived_instance2 in the prototype chain of
1428 // other_instance.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001429 CHECK(derived_instance2->Equals(
1430 env.local(),
1431 other_instance->FindInstanceInPrototypeChain(base))
1432 .FromJust());
1433 CHECK(derived_instance2->Equals(env.local(),
1434 other_instance->FindInstanceInPrototypeChain(
1435 derived))
1436 .FromJust());
1437 CHECK(other_instance->Equals(
1438 env.local(),
1439 other_instance->FindInstanceInPrototypeChain(other))
1440 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00001441}
1442
1443
Steve Block3ce2e202009-11-05 08:53:23 +00001444THREADED_TEST(TinyInteger) {
Steve Block3ce2e202009-11-05 08:53:23 +00001445 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001446 v8::Isolate* isolate = env->GetIsolate();
1447 v8::HandleScope scope(isolate);
1448
Steve Block3ce2e202009-11-05 08:53:23 +00001449 int32_t value = 239;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001450 Local<v8::Integer> value_obj = v8::Integer::New(isolate, value);
1451 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1452
1453 value_obj = v8::Integer::New(isolate, value);
Steve Block3ce2e202009-11-05 08:53:23 +00001454 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1455}
1456
1457
1458THREADED_TEST(BigSmiInteger) {
Steve Block3ce2e202009-11-05 08:53:23 +00001459 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001460 v8::HandleScope scope(env->GetIsolate());
1461 v8::Isolate* isolate = CcTest::isolate();
1462
Steve Block3ce2e202009-11-05 08:53:23 +00001463 int32_t value = i::Smi::kMaxValue;
1464 // We cannot add one to a Smi::kMaxValue without wrapping.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001465 if (i::SmiValuesAre31Bits()) {
Steve Block3ce2e202009-11-05 08:53:23 +00001466 CHECK(i::Smi::IsValid(value));
1467 CHECK(!i::Smi::IsValid(value + 1));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001468
1469 Local<v8::Integer> value_obj = v8::Integer::New(isolate, value);
1470 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1471
1472 value_obj = v8::Integer::New(isolate, value);
Steve Block3ce2e202009-11-05 08:53:23 +00001473 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1474 }
1475}
1476
1477
1478THREADED_TEST(BigInteger) {
Steve Block3ce2e202009-11-05 08:53:23 +00001479 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001480 v8::HandleScope scope(env->GetIsolate());
1481 v8::Isolate* isolate = CcTest::isolate();
1482
Steve Block3ce2e202009-11-05 08:53:23 +00001483 // We cannot add one to a Smi::kMaxValue without wrapping.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001484 if (i::SmiValuesAre31Bits()) {
Steve Block3ce2e202009-11-05 08:53:23 +00001485 // The casts allow this to compile, even if Smi::kMaxValue is 2^31-1.
1486 // The code will not be run in that case, due to the "if" guard.
1487 int32_t value =
1488 static_cast<int32_t>(static_cast<uint32_t>(i::Smi::kMaxValue) + 1);
1489 CHECK(value > i::Smi::kMaxValue);
1490 CHECK(!i::Smi::IsValid(value));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001491
1492 Local<v8::Integer> value_obj = v8::Integer::New(isolate, value);
1493 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1494
1495 value_obj = v8::Integer::New(isolate, value);
Steve Block3ce2e202009-11-05 08:53:23 +00001496 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1497 }
1498}
1499
1500
1501THREADED_TEST(TinyUnsignedInteger) {
Steve Block3ce2e202009-11-05 08:53:23 +00001502 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001503 v8::HandleScope scope(env->GetIsolate());
1504 v8::Isolate* isolate = CcTest::isolate();
1505
Steve Block3ce2e202009-11-05 08:53:23 +00001506 uint32_t value = 239;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001507
1508 Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
1509 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1510
1511 value_obj = v8::Integer::NewFromUnsigned(isolate, value);
Steve Block3ce2e202009-11-05 08:53:23 +00001512 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1513}
1514
1515
1516THREADED_TEST(BigUnsignedSmiInteger) {
Steve Block3ce2e202009-11-05 08:53:23 +00001517 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001518 v8::HandleScope scope(env->GetIsolate());
1519 v8::Isolate* isolate = CcTest::isolate();
1520
Steve Block3ce2e202009-11-05 08:53:23 +00001521 uint32_t value = static_cast<uint32_t>(i::Smi::kMaxValue);
1522 CHECK(i::Smi::IsValid(value));
1523 CHECK(!i::Smi::IsValid(value + 1));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001524
1525 Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
1526 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1527
1528 value_obj = v8::Integer::NewFromUnsigned(isolate, value);
Steve Block3ce2e202009-11-05 08:53:23 +00001529 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1530}
1531
1532
1533THREADED_TEST(BigUnsignedInteger) {
Steve Block3ce2e202009-11-05 08:53:23 +00001534 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001535 v8::HandleScope scope(env->GetIsolate());
1536 v8::Isolate* isolate = CcTest::isolate();
1537
Steve Block3ce2e202009-11-05 08:53:23 +00001538 uint32_t value = static_cast<uint32_t>(i::Smi::kMaxValue) + 1;
1539 CHECK(value > static_cast<uint32_t>(i::Smi::kMaxValue));
1540 CHECK(!i::Smi::IsValid(value));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001541
1542 Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
1543 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1544
1545 value_obj = v8::Integer::NewFromUnsigned(isolate, value);
Steve Block3ce2e202009-11-05 08:53:23 +00001546 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1547}
1548
1549
1550THREADED_TEST(OutOfSignedRangeUnsignedInteger) {
Steve Block3ce2e202009-11-05 08:53:23 +00001551 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001552 v8::HandleScope scope(env->GetIsolate());
1553 v8::Isolate* isolate = CcTest::isolate();
1554
Steve Block3ce2e202009-11-05 08:53:23 +00001555 uint32_t INT32_MAX_AS_UINT = (1U << 31) - 1;
1556 uint32_t value = INT32_MAX_AS_UINT + 1;
1557 CHECK(value > INT32_MAX_AS_UINT); // No overflow.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001558
1559 Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
1560 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1561
1562 value_obj = v8::Integer::NewFromUnsigned(isolate, value);
Steve Block3ce2e202009-11-05 08:53:23 +00001563 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1564}
1565
1566
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001567THREADED_TEST(IsNativeError) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001568 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001569 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001570 v8::Local<Value> syntax_error = CompileRun(
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001571 "var out = 0; try { eval(\"#\"); } catch(x) { out = x; } out; ");
1572 CHECK(syntax_error->IsNativeError());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001573 v8::Local<Value> not_error = CompileRun("{a:42}");
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001574 CHECK(!not_error->IsNativeError());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001575 v8::Local<Value> not_object = CompileRun("42");
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001576 CHECK(!not_object->IsNativeError());
1577}
1578
1579
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001580THREADED_TEST(IsGeneratorFunctionOrObject) {
1581 LocalContext env;
1582 v8::HandleScope scope(env->GetIsolate());
1583
1584 CompileRun("function *gen() { yield 1; }\nfunction func() {}");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001585 v8::Local<Value> gen = CompileRun("gen");
1586 v8::Local<Value> genObj = CompileRun("gen()");
1587 v8::Local<Value> object = CompileRun("{a:42}");
1588 v8::Local<Value> func = CompileRun("func");
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001589
1590 CHECK(gen->IsGeneratorFunction());
1591 CHECK(gen->IsFunction());
1592 CHECK(!gen->IsGeneratorObject());
1593
1594 CHECK(!genObj->IsGeneratorFunction());
1595 CHECK(!genObj->IsFunction());
1596 CHECK(genObj->IsGeneratorObject());
1597
1598 CHECK(!object->IsGeneratorFunction());
1599 CHECK(!object->IsFunction());
1600 CHECK(!object->IsGeneratorObject());
1601
1602 CHECK(!func->IsGeneratorFunction());
1603 CHECK(func->IsFunction());
1604 CHECK(!func->IsGeneratorObject());
1605}
1606
1607
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001608THREADED_TEST(ArgumentsObject) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001609 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001610 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001611 v8::Local<Value> arguments_object =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001612 CompileRun("var out = 0; (function(){ out = arguments; })(1,2,3); out;");
1613 CHECK(arguments_object->IsArgumentsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001614 v8::Local<Value> array = CompileRun("[1,2,3]");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001615 CHECK(!array->IsArgumentsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001616 v8::Local<Value> object = CompileRun("{a:42}");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001617 CHECK(!object->IsArgumentsObject());
1618}
1619
1620
1621THREADED_TEST(IsMapOrSet) {
1622 LocalContext env;
1623 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001624 v8::Local<Value> map = CompileRun("new Map()");
1625 v8::Local<Value> set = CompileRun("new Set()");
1626 v8::Local<Value> weak_map = CompileRun("new WeakMap()");
1627 v8::Local<Value> weak_set = CompileRun("new WeakSet()");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001628 CHECK(map->IsMap());
1629 CHECK(set->IsSet());
1630 CHECK(weak_map->IsWeakMap());
1631 CHECK(weak_set->IsWeakSet());
1632
1633 CHECK(!map->IsSet());
1634 CHECK(!map->IsWeakMap());
1635 CHECK(!map->IsWeakSet());
1636
1637 CHECK(!set->IsMap());
1638 CHECK(!set->IsWeakMap());
1639 CHECK(!set->IsWeakSet());
1640
1641 CHECK(!weak_map->IsMap());
1642 CHECK(!weak_map->IsSet());
1643 CHECK(!weak_map->IsWeakSet());
1644
1645 CHECK(!weak_set->IsMap());
1646 CHECK(!weak_set->IsSet());
1647 CHECK(!weak_set->IsWeakMap());
1648
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001649 v8::Local<Value> object = CompileRun("{a:42}");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001650 CHECK(!object->IsMap());
1651 CHECK(!object->IsSet());
1652 CHECK(!object->IsWeakMap());
1653 CHECK(!object->IsWeakSet());
1654}
1655
1656
1657THREADED_TEST(StringObject) {
1658 LocalContext env;
1659 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001660 v8::Local<Value> boxed_string = CompileRun("new String(\"test\")");
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001661 CHECK(boxed_string->IsStringObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001662 v8::Local<Value> unboxed_string = CompileRun("\"test\"");
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001663 CHECK(!unboxed_string->IsStringObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001664 v8::Local<Value> boxed_not_string = CompileRun("new Number(42)");
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001665 CHECK(!boxed_not_string->IsStringObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001666 v8::Local<Value> not_object = CompileRun("0");
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001667 CHECK(!not_object->IsStringObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001668 v8::Local<v8::StringObject> as_boxed = boxed_string.As<v8::StringObject>();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001669 CHECK(!as_boxed.IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001670 Local<v8::String> the_string = as_boxed->ValueOf();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001671 CHECK(!the_string.IsEmpty());
1672 ExpectObject("\"test\"", the_string);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001673 v8::Local<v8::Value> new_boxed_string = v8::StringObject::New(the_string);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001674 CHECK(new_boxed_string->IsStringObject());
1675 as_boxed = new_boxed_string.As<v8::StringObject>();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001676 the_string = as_boxed->ValueOf();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001677 CHECK(!the_string.IsEmpty());
1678 ExpectObject("\"test\"", the_string);
1679}
1680
1681
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001682TEST(StringObjectDelete) {
1683 LocalContext context;
1684 v8::HandleScope scope(context->GetIsolate());
1685 v8::Local<Value> boxed_string = CompileRun("new String(\"test\")");
1686 CHECK(boxed_string->IsStringObject());
1687 v8::Local<v8::Object> str_obj = boxed_string.As<v8::Object>();
1688 CHECK(!str_obj->Delete(context.local(), 2).FromJust());
1689 CHECK(!str_obj->Delete(context.local(), v8_num(2)).FromJust());
1690}
1691
1692
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001693THREADED_TEST(NumberObject) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001694 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001695 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001696 v8::Local<Value> boxed_number = CompileRun("new Number(42)");
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001697 CHECK(boxed_number->IsNumberObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001698 v8::Local<Value> unboxed_number = CompileRun("42");
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001699 CHECK(!unboxed_number->IsNumberObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001700 v8::Local<Value> boxed_not_number = CompileRun("new Boolean(false)");
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001701 CHECK(!boxed_not_number->IsNumberObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001702 v8::Local<v8::NumberObject> as_boxed = boxed_number.As<v8::NumberObject>();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001703 CHECK(!as_boxed.IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001704 double the_number = as_boxed->ValueOf();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001705 CHECK_EQ(42.0, the_number);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001706 v8::Local<v8::Value> new_boxed_number =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001707 v8::NumberObject::New(env->GetIsolate(), 43);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001708 CHECK(new_boxed_number->IsNumberObject());
1709 as_boxed = new_boxed_number.As<v8::NumberObject>();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001710 the_number = as_boxed->ValueOf();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001711 CHECK_EQ(43.0, the_number);
1712}
1713
1714
1715THREADED_TEST(BooleanObject) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001716 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001717 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001718 v8::Local<Value> boxed_boolean = CompileRun("new Boolean(true)");
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001719 CHECK(boxed_boolean->IsBooleanObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001720 v8::Local<Value> unboxed_boolean = CompileRun("true");
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001721 CHECK(!unboxed_boolean->IsBooleanObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001722 v8::Local<Value> boxed_not_boolean = CompileRun("new Number(42)");
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001723 CHECK(!boxed_not_boolean->IsBooleanObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001724 v8::Local<v8::BooleanObject> as_boxed = boxed_boolean.As<v8::BooleanObject>();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001725 CHECK(!as_boxed.IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001726 bool the_boolean = as_boxed->ValueOf();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001727 CHECK_EQ(true, the_boolean);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001728 v8::Local<v8::Value> boxed_true =
1729 v8::BooleanObject::New(env->GetIsolate(), true);
1730 v8::Local<v8::Value> boxed_false =
1731 v8::BooleanObject::New(env->GetIsolate(), false);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001732 CHECK(boxed_true->IsBooleanObject());
1733 CHECK(boxed_false->IsBooleanObject());
1734 as_boxed = boxed_true.As<v8::BooleanObject>();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001735 CHECK_EQ(true, as_boxed->ValueOf());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001736 as_boxed = boxed_false.As<v8::BooleanObject>();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001737 CHECK_EQ(false, as_boxed->ValueOf());
1738}
1739
1740
1741THREADED_TEST(PrimitiveAndWrappedBooleans) {
1742 LocalContext env;
1743 v8::HandleScope scope(env->GetIsolate());
1744
1745 Local<Value> primitive_false = Boolean::New(env->GetIsolate(), false);
1746 CHECK(primitive_false->IsBoolean());
1747 CHECK(!primitive_false->IsBooleanObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001748 CHECK(!primitive_false->BooleanValue(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001749 CHECK(!primitive_false->IsTrue());
1750 CHECK(primitive_false->IsFalse());
1751
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001752 Local<Value> false_value = BooleanObject::New(env->GetIsolate(), false);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001753 CHECK(!false_value->IsBoolean());
1754 CHECK(false_value->IsBooleanObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001755 CHECK(false_value->BooleanValue(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001756 CHECK(!false_value->IsTrue());
1757 CHECK(!false_value->IsFalse());
1758
1759 Local<BooleanObject> false_boolean_object = false_value.As<BooleanObject>();
1760 CHECK(!false_boolean_object->IsBoolean());
1761 CHECK(false_boolean_object->IsBooleanObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001762 CHECK(false_boolean_object->BooleanValue(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001763 CHECK(!false_boolean_object->ValueOf());
1764 CHECK(!false_boolean_object->IsTrue());
1765 CHECK(!false_boolean_object->IsFalse());
1766
1767 Local<Value> primitive_true = Boolean::New(env->GetIsolate(), true);
1768 CHECK(primitive_true->IsBoolean());
1769 CHECK(!primitive_true->IsBooleanObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001770 CHECK(primitive_true->BooleanValue(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001771 CHECK(primitive_true->IsTrue());
1772 CHECK(!primitive_true->IsFalse());
1773
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001774 Local<Value> true_value = BooleanObject::New(env->GetIsolate(), true);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001775 CHECK(!true_value->IsBoolean());
1776 CHECK(true_value->IsBooleanObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001777 CHECK(true_value->BooleanValue(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001778 CHECK(!true_value->IsTrue());
1779 CHECK(!true_value->IsFalse());
1780
1781 Local<BooleanObject> true_boolean_object = true_value.As<BooleanObject>();
1782 CHECK(!true_boolean_object->IsBoolean());
1783 CHECK(true_boolean_object->IsBooleanObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001784 CHECK(true_boolean_object->BooleanValue(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001785 CHECK(true_boolean_object->ValueOf());
1786 CHECK(!true_boolean_object->IsTrue());
1787 CHECK(!true_boolean_object->IsFalse());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001788}
1789
1790
Steve Blocka7e24c12009-10-30 11:49:00 +00001791THREADED_TEST(Number) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001792 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001793 v8::HandleScope scope(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00001794 double PI = 3.1415926;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001795 Local<v8::Number> pi_obj = v8::Number::New(env->GetIsolate(), PI);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001796 CHECK_EQ(PI, pi_obj->NumberValue(env.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00001797}
1798
1799
1800THREADED_TEST(ToNumber) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001801 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001802 v8::Isolate* isolate = CcTest::isolate();
1803 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001804 Local<String> str = v8_str("3.1415926");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001805 CHECK_EQ(3.1415926, str->NumberValue(env.local()).FromJust());
1806 v8::Local<v8::Boolean> t = v8::True(isolate);
1807 CHECK_EQ(1.0, t->NumberValue(env.local()).FromJust());
1808 v8::Local<v8::Boolean> f = v8::False(isolate);
1809 CHECK_EQ(0.0, f->NumberValue(env.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00001810}
1811
1812
1813THREADED_TEST(Date) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001814 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001815 v8::HandleScope scope(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00001816 double PI = 3.1415926;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001817 Local<Value> date = v8::Date::New(env.local(), PI).ToLocalChecked();
1818 CHECK_EQ(3.0, date->NumberValue(env.local()).FromJust());
1819 CHECK(date.As<v8::Date>()
1820 ->Set(env.local(), v8_str("property"),
1821 v8::Integer::New(env->GetIsolate(), 42))
1822 .FromJust());
1823 CHECK_EQ(42, date.As<v8::Date>()
1824 ->Get(env.local(), v8_str("property"))
1825 .ToLocalChecked()
1826 ->Int32Value(env.local())
1827 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00001828}
1829
1830
1831THREADED_TEST(Boolean) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001832 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001833 v8::Isolate* isolate = env->GetIsolate();
1834 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001835 v8::Local<v8::Boolean> t = v8::True(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001836 CHECK(t->Value());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001837 v8::Local<v8::Boolean> f = v8::False(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001838 CHECK(!f->Value());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001839 v8::Local<v8::Primitive> u = v8::Undefined(isolate);
1840 CHECK(!u->BooleanValue(env.local()).FromJust());
1841 v8::Local<v8::Primitive> n = v8::Null(isolate);
1842 CHECK(!n->BooleanValue(env.local()).FromJust());
1843 v8::Local<String> str1 = v8_str("");
1844 CHECK(!str1->BooleanValue(env.local()).FromJust());
1845 v8::Local<String> str2 = v8_str("x");
1846 CHECK(str2->BooleanValue(env.local()).FromJust());
1847 CHECK(!v8::Number::New(isolate, 0)->BooleanValue(env.local()).FromJust());
1848 CHECK(v8::Number::New(isolate, -1)->BooleanValue(env.local()).FromJust());
1849 CHECK(v8::Number::New(isolate, 1)->BooleanValue(env.local()).FromJust());
1850 CHECK(v8::Number::New(isolate, 42)->BooleanValue(env.local()).FromJust());
1851 CHECK(!v8_compile("NaN")
1852 ->Run(env.local())
1853 .ToLocalChecked()
1854 ->BooleanValue(env.local())
1855 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00001856}
1857
1858
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001859static void DummyCallHandler(const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001860 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001861 args.GetReturnValue().Set(v8_num(13.4));
Steve Blocka7e24c12009-10-30 11:49:00 +00001862}
1863
1864
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001865static void GetM(Local<String> name,
1866 const v8::PropertyCallbackInfo<v8::Value>& info) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001867 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001868 info.GetReturnValue().Set(v8_num(876));
Steve Blocka7e24c12009-10-30 11:49:00 +00001869}
1870
1871
1872THREADED_TEST(GlobalPrototype) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001873 v8::Isolate* isolate = CcTest::isolate();
1874 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001875 v8::Local<v8::FunctionTemplate> func_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001876 v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001877 func_templ->PrototypeTemplate()->Set(
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001878 isolate, "dummy", v8::FunctionTemplate::New(isolate, DummyCallHandler));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001879 v8::Local<ObjectTemplate> templ = func_templ->InstanceTemplate();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001880 templ->Set(isolate, "x", v8_num(200));
Steve Blocka7e24c12009-10-30 11:49:00 +00001881 templ->SetAccessor(v8_str("m"), GetM);
1882 LocalContext env(0, templ);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001883 v8::Local<Script> script(v8_compile("dummy()"));
1884 v8::Local<Value> result(script->Run(env.local()).ToLocalChecked());
1885 CHECK_EQ(13.4, result->NumberValue(env.local()).FromJust());
1886 CHECK_EQ(200, v8_run_int32value(v8_compile("x")));
1887 CHECK_EQ(876, v8_run_int32value(v8_compile("m")));
Steve Blocka7e24c12009-10-30 11:49:00 +00001888}
1889
1890
Steve Blocka7e24c12009-10-30 11:49:00 +00001891THREADED_TEST(ObjectTemplate) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001892 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001893 v8::Isolate* isolate = CcTest::isolate();
1894 v8::HandleScope scope(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001895 Local<v8::FunctionTemplate> acc =
1896 v8::FunctionTemplate::New(isolate, Returns42);
1897 CHECK(env->Global()
1898 ->Set(env.local(), v8_str("acc"),
1899 acc->GetFunction(env.local()).ToLocalChecked())
1900 .FromJust());
1901
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001902 Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(isolate);
1903 v8::Local<v8::String> class_name = v8_str("the_class_name");
1904 fun->SetClassName(class_name);
1905 Local<ObjectTemplate> templ1 = ObjectTemplate::New(isolate, fun);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001906 templ1->Set(isolate, "x", v8_num(10));
1907 templ1->Set(isolate, "y", v8_num(13));
Ben Murdoch097c5b22016-05-18 11:27:45 +01001908 templ1->Set(v8_str("foo"), acc);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001909 Local<v8::Object> instance1 =
1910 templ1->NewInstance(env.local()).ToLocalChecked();
1911 CHECK(class_name->StrictEquals(instance1->GetConstructorName()));
1912 CHECK(env->Global()->Set(env.local(), v8_str("p"), instance1).FromJust());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001913 CHECK(CompileRun("(p.x == 10)")->BooleanValue(env.local()).FromJust());
1914 CHECK(CompileRun("(p.y == 13)")->BooleanValue(env.local()).FromJust());
1915 CHECK(CompileRun("(p.foo() == 42)")->BooleanValue(env.local()).FromJust());
1916 CHECK(CompileRun("(p.foo == acc)")->BooleanValue(env.local()).FromJust());
1917 // Ensure that foo become a data field.
1918 CompileRun("p.foo = function() {}");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001919 Local<v8::FunctionTemplate> fun2 = v8::FunctionTemplate::New(isolate);
1920 fun2->PrototypeTemplate()->Set(isolate, "nirk", v8_num(123));
1921 Local<ObjectTemplate> templ2 = fun2->InstanceTemplate();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001922 templ2->Set(isolate, "a", v8_num(12));
1923 templ2->Set(isolate, "b", templ1);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001924 templ2->Set(v8_str("bar"), acc);
1925 templ2->SetAccessorProperty(v8_str("acc"), acc);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001926 Local<v8::Object> instance2 =
1927 templ2->NewInstance(env.local()).ToLocalChecked();
1928 CHECK(env->Global()->Set(env.local(), v8_str("q"), instance2).FromJust());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001929 CHECK(CompileRun("(q.nirk == 123)")->BooleanValue(env.local()).FromJust());
1930 CHECK(CompileRun("(q.a == 12)")->BooleanValue(env.local()).FromJust());
1931 CHECK(CompileRun("(q.b.x == 10)")->BooleanValue(env.local()).FromJust());
1932 CHECK(CompileRun("(q.b.y == 13)")->BooleanValue(env.local()).FromJust());
1933 CHECK(CompileRun("(q.b.foo() == 42)")->BooleanValue(env.local()).FromJust());
1934 CHECK(CompileRun("(q.b.foo === acc)")->BooleanValue(env.local()).FromJust());
1935 CHECK(CompileRun("(q.b !== p)")->BooleanValue(env.local()).FromJust());
1936 CHECK(CompileRun("(q.acc == 42)")->BooleanValue(env.local()).FromJust());
1937 CHECK(CompileRun("(q.bar() == 42)")->BooleanValue(env.local()).FromJust());
1938 CHECK(CompileRun("(q.bar == acc)")->BooleanValue(env.local()).FromJust());
1939
1940 instance2 = templ2->NewInstance(env.local()).ToLocalChecked();
1941 CHECK(env->Global()->Set(env.local(), v8_str("q2"), instance2).FromJust());
1942 CHECK(CompileRun("(q2.nirk == 123)")->BooleanValue(env.local()).FromJust());
1943 CHECK(CompileRun("(q2.a == 12)")->BooleanValue(env.local()).FromJust());
1944 CHECK(CompileRun("(q2.b.x == 10)")->BooleanValue(env.local()).FromJust());
1945 CHECK(CompileRun("(q2.b.y == 13)")->BooleanValue(env.local()).FromJust());
1946 CHECK(CompileRun("(q2.b.foo() == 42)")->BooleanValue(env.local()).FromJust());
1947 CHECK(CompileRun("(q2.b.foo === acc)")->BooleanValue(env.local()).FromJust());
1948 CHECK(CompileRun("(q2.acc == 42)")->BooleanValue(env.local()).FromJust());
1949 CHECK(CompileRun("(q2.bar() == 42)")->BooleanValue(env.local()).FromJust());
1950 CHECK(CompileRun("(q2.bar === acc)")->BooleanValue(env.local()).FromJust());
1951
1952 CHECK(CompileRun("(q.b !== q2.b)")->BooleanValue(env.local()).FromJust());
1953 CHECK(CompileRun("q.b.x = 17; (q2.b.x == 10)")
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001954 ->BooleanValue(env.local())
1955 .FromJust());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001956 CHECK(CompileRun("desc1 = Object.getOwnPropertyDescriptor(q, 'acc');"
1957 "(desc1.get === acc)")
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001958 ->BooleanValue(env.local())
1959 .FromJust());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001960 CHECK(CompileRun("desc2 = Object.getOwnPropertyDescriptor(q2, 'acc');"
1961 "(desc2.get === acc)")
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001962 ->BooleanValue(env.local())
1963 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00001964}
1965
Ben Murdoch097c5b22016-05-18 11:27:45 +01001966THREADED_TEST(IntegerValue) {
1967 LocalContext env;
1968 v8::Isolate* isolate = CcTest::isolate();
1969 v8::HandleScope scope(isolate);
1970
1971 CHECK_EQ(0, CompileRun("undefined")->IntegerValue(env.local()).FromJust());
1972}
1973
1974static void GetNirk(Local<String> name,
1975 const v8::PropertyCallbackInfo<v8::Value>& info) {
1976 ApiTestFuzzer::Fuzz();
1977 info.GetReturnValue().Set(v8_num(900));
1978}
1979
1980static void GetRino(Local<String> name,
1981 const v8::PropertyCallbackInfo<v8::Value>& info) {
1982 ApiTestFuzzer::Fuzz();
1983 info.GetReturnValue().Set(v8_num(560));
1984}
1985
1986enum ObjectInstantiationMode {
1987 // Create object using ObjectTemplate::NewInstance.
1988 ObjectTemplate_NewInstance,
1989 // Create object using FunctionTemplate::NewInstance on constructor.
1990 Constructor_GetFunction_NewInstance,
1991 // Create object using new operator on constructor.
1992 Constructor_GetFunction_New
1993};
1994
1995// Test object instance creation using a function template with an instance
1996// template inherited from another function template with accessors and data
1997// properties in prototype template.
1998static void TestObjectTemplateInheritedWithPrototype(
1999 ObjectInstantiationMode mode) {
2000 LocalContext env;
2001 v8::Isolate* isolate = CcTest::isolate();
2002 v8::HandleScope scope(isolate);
2003
2004 Local<v8::FunctionTemplate> fun_A = v8::FunctionTemplate::New(isolate);
2005 fun_A->SetClassName(v8_str("A"));
2006 v8::Local<v8::ObjectTemplate> prototype_templ = fun_A->PrototypeTemplate();
2007 prototype_templ->Set(isolate, "a", v8_num(113));
2008 prototype_templ->SetNativeDataProperty(v8_str("nirk"), GetNirk);
2009 prototype_templ->Set(isolate, "b", v8_num(153));
2010
2011 Local<v8::FunctionTemplate> fun_B = v8::FunctionTemplate::New(isolate);
2012 v8::Local<v8::String> class_name = v8_str("B");
2013 fun_B->SetClassName(class_name);
2014 fun_B->Inherit(fun_A);
2015 prototype_templ = fun_B->PrototypeTemplate();
2016 prototype_templ->Set(isolate, "c", v8_num(713));
2017 prototype_templ->SetNativeDataProperty(v8_str("rino"), GetRino);
2018 prototype_templ->Set(isolate, "d", v8_num(753));
2019
2020 Local<ObjectTemplate> templ = fun_B->InstanceTemplate();
2021 templ->Set(isolate, "x", v8_num(10));
2022 templ->Set(isolate, "y", v8_num(13));
2023
2024 // Perform several iterations to trigger creation from cached boilerplate.
2025 for (int i = 0; i < 3; i++) {
2026 Local<v8::Object> instance;
2027 switch (mode) {
2028 case ObjectTemplate_NewInstance:
2029 instance = templ->NewInstance(env.local()).ToLocalChecked();
2030 break;
2031
2032 case Constructor_GetFunction_NewInstance: {
2033 Local<v8::Function> function_B =
2034 fun_B->GetFunction(env.local()).ToLocalChecked();
2035 instance = function_B->NewInstance(env.local()).ToLocalChecked();
2036 break;
2037 }
2038 case Constructor_GetFunction_New: {
2039 Local<v8::Function> function_B =
2040 fun_B->GetFunction(env.local()).ToLocalChecked();
2041 if (i == 0) {
2042 CHECK(env->Global()
2043 ->Set(env.local(), class_name, function_B)
2044 .FromJust());
2045 }
2046 instance =
2047 CompileRun("new B()")->ToObject(env.local()).ToLocalChecked();
2048 break;
2049 }
2050 default:
2051 UNREACHABLE();
2052 }
2053
2054 CHECK(class_name->StrictEquals(instance->GetConstructorName()));
2055 CHECK(env->Global()->Set(env.local(), v8_str("o"), instance).FromJust());
2056
2057 CHECK_EQ(10, CompileRun("o.x")->IntegerValue(env.local()).FromJust());
2058 CHECK_EQ(13, CompileRun("o.y")->IntegerValue(env.local()).FromJust());
2059
2060 CHECK_EQ(113, CompileRun("o.a")->IntegerValue(env.local()).FromJust());
2061 CHECK_EQ(900, CompileRun("o.nirk")->IntegerValue(env.local()).FromJust());
2062 CHECK_EQ(153, CompileRun("o.b")->IntegerValue(env.local()).FromJust());
2063 CHECK_EQ(713, CompileRun("o.c")->IntegerValue(env.local()).FromJust());
2064 CHECK_EQ(560, CompileRun("o.rino")->IntegerValue(env.local()).FromJust());
2065 CHECK_EQ(753, CompileRun("o.d")->IntegerValue(env.local()).FromJust());
2066 }
2067}
2068
2069THREADED_TEST(TestObjectTemplateInheritedWithAccessorsInPrototype1) {
2070 TestObjectTemplateInheritedWithPrototype(ObjectTemplate_NewInstance);
2071}
2072
2073THREADED_TEST(TestObjectTemplateInheritedWithAccessorsInPrototype2) {
2074 TestObjectTemplateInheritedWithPrototype(Constructor_GetFunction_NewInstance);
2075}
2076
2077THREADED_TEST(TestObjectTemplateInheritedWithAccessorsInPrototype3) {
2078 TestObjectTemplateInheritedWithPrototype(Constructor_GetFunction_New);
2079}
2080
2081// Test object instance creation using a function template without an instance
2082// template inherited from another function template.
2083static void TestObjectTemplateInheritedWithoutInstanceTemplate(
2084 ObjectInstantiationMode mode) {
2085 LocalContext env;
2086 v8::Isolate* isolate = CcTest::isolate();
2087 v8::HandleScope scope(isolate);
2088
2089 Local<v8::FunctionTemplate> fun_A = v8::FunctionTemplate::New(isolate);
2090 fun_A->SetClassName(v8_str("A"));
2091
2092 Local<ObjectTemplate> templ_A = fun_A->InstanceTemplate();
2093 templ_A->SetNativeDataProperty(v8_str("nirk"), GetNirk);
2094 templ_A->SetNativeDataProperty(v8_str("rino"), GetRino);
2095
2096 Local<v8::FunctionTemplate> fun_B = v8::FunctionTemplate::New(isolate);
2097 v8::Local<v8::String> class_name = v8_str("B");
2098 fun_B->SetClassName(class_name);
2099 fun_B->Inherit(fun_A);
2100
2101 // Perform several iterations to trigger creation from cached boilerplate.
2102 for (int i = 0; i < 3; i++) {
2103 Local<v8::Object> instance;
2104 switch (mode) {
2105 case Constructor_GetFunction_NewInstance: {
2106 Local<v8::Function> function_B =
2107 fun_B->GetFunction(env.local()).ToLocalChecked();
2108 instance = function_B->NewInstance(env.local()).ToLocalChecked();
2109 break;
2110 }
2111 case Constructor_GetFunction_New: {
2112 Local<v8::Function> function_B =
2113 fun_B->GetFunction(env.local()).ToLocalChecked();
2114 if (i == 0) {
2115 CHECK(env->Global()
2116 ->Set(env.local(), class_name, function_B)
2117 .FromJust());
2118 }
2119 instance =
2120 CompileRun("new B()")->ToObject(env.local()).ToLocalChecked();
2121 break;
2122 }
2123 default:
2124 UNREACHABLE();
2125 }
2126
2127 CHECK(class_name->StrictEquals(instance->GetConstructorName()));
2128 CHECK(env->Global()->Set(env.local(), v8_str("o"), instance).FromJust());
2129
2130 CHECK_EQ(900, CompileRun("o.nirk")->IntegerValue(env.local()).FromJust());
2131 CHECK_EQ(560, CompileRun("o.rino")->IntegerValue(env.local()).FromJust());
2132 }
2133}
2134
2135THREADED_TEST(TestObjectTemplateInheritedWithPrototype1) {
2136 TestObjectTemplateInheritedWithoutInstanceTemplate(
2137 Constructor_GetFunction_NewInstance);
2138}
2139
2140THREADED_TEST(TestObjectTemplateInheritedWithPrototype2) {
2141 TestObjectTemplateInheritedWithoutInstanceTemplate(
2142 Constructor_GetFunction_New);
2143}
Steve Blocka7e24c12009-10-30 11:49:00 +00002144
Ben Murdochc5610432016-08-08 18:44:38 +01002145THREADED_TEST(TestObjectTemplateClassInheritance) {
2146 LocalContext env;
2147 v8::Isolate* isolate = CcTest::isolate();
2148 v8::HandleScope scope(isolate);
2149
2150 Local<v8::FunctionTemplate> fun_A = v8::FunctionTemplate::New(isolate);
2151 fun_A->SetClassName(v8_str("A"));
2152
2153 Local<ObjectTemplate> templ_A = fun_A->InstanceTemplate();
2154 templ_A->SetNativeDataProperty(v8_str("nirk"), GetNirk);
2155 templ_A->SetNativeDataProperty(v8_str("rino"), GetRino);
2156
2157 Local<v8::FunctionTemplate> fun_B = v8::FunctionTemplate::New(isolate);
2158 v8::Local<v8::String> class_name = v8_str("B");
2159 fun_B->SetClassName(class_name);
2160 fun_B->Inherit(fun_A);
2161
2162 v8::Local<v8::String> subclass_name = v8_str("C");
2163 v8::Local<v8::Object> b_proto;
2164 v8::Local<v8::Object> c_proto;
2165 // Perform several iterations to make sure the cache doesn't break
2166 // subclassing.
2167 for (int i = 0; i < 3; i++) {
2168 Local<v8::Function> function_B =
2169 fun_B->GetFunction(env.local()).ToLocalChecked();
2170 if (i == 0) {
2171 CHECK(env->Global()->Set(env.local(), class_name, function_B).FromJust());
2172 CompileRun("class C extends B {}");
2173 b_proto =
2174 CompileRun("B.prototype")->ToObject(env.local()).ToLocalChecked();
2175 c_proto =
2176 CompileRun("C.prototype")->ToObject(env.local()).ToLocalChecked();
2177 CHECK(b_proto->Equals(env.local(), c_proto->GetPrototype()).FromJust());
2178 }
2179 Local<v8::Object> instance =
2180 CompileRun("new C()")->ToObject(env.local()).ToLocalChecked();
2181 CHECK(c_proto->Equals(env.local(), instance->GetPrototype()).FromJust());
2182
2183 CHECK(subclass_name->StrictEquals(instance->GetConstructorName()));
2184 CHECK(env->Global()->Set(env.local(), v8_str("o"), instance).FromJust());
2185
2186 CHECK_EQ(900, CompileRun("o.nirk")->IntegerValue(env.local()).FromJust());
2187 CHECK_EQ(560, CompileRun("o.rino")->IntegerValue(env.local()).FromJust());
2188 }
2189}
2190
2191static void NamedPropertyGetterWhichReturns42(
2192 Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
2193 info.GetReturnValue().Set(v8_num(42));
2194}
2195
2196THREADED_TEST(TestObjectTemplateReflectConstruct) {
2197 LocalContext env;
2198 v8::Isolate* isolate = CcTest::isolate();
2199 v8::HandleScope scope(isolate);
2200
2201 Local<v8::FunctionTemplate> fun_B = v8::FunctionTemplate::New(isolate);
2202 fun_B->InstanceTemplate()->SetHandler(
2203 v8::NamedPropertyHandlerConfiguration(NamedPropertyGetterWhichReturns42));
2204 v8::Local<v8::String> class_name = v8_str("B");
2205 fun_B->SetClassName(class_name);
2206
2207 v8::Local<v8::String> subclass_name = v8_str("C");
2208 v8::Local<v8::Object> b_proto;
2209 v8::Local<v8::Object> c_proto;
2210 // Perform several iterations to make sure the cache doesn't break
2211 // subclassing.
2212 for (int i = 0; i < 3; i++) {
2213 Local<v8::Function> function_B =
2214 fun_B->GetFunction(env.local()).ToLocalChecked();
2215 if (i == 0) {
2216 CHECK(env->Global()->Set(env.local(), class_name, function_B).FromJust());
2217 CompileRun("function C() {}");
2218 c_proto =
2219 CompileRun("C.prototype")->ToObject(env.local()).ToLocalChecked();
2220 }
2221 Local<v8::Object> instance = CompileRun("Reflect.construct(B, [], C)")
2222 ->ToObject(env.local())
2223 .ToLocalChecked();
2224 CHECK(c_proto->Equals(env.local(), instance->GetPrototype()).FromJust());
2225
2226 CHECK(subclass_name->StrictEquals(instance->GetConstructorName()));
2227 CHECK(env->Global()->Set(env.local(), v8_str("o"), instance).FromJust());
2228
2229 CHECK_EQ(42, CompileRun("o.nirk")->IntegerValue(env.local()).FromJust());
2230 CHECK_EQ(42, CompileRun("o.rino")->IntegerValue(env.local()).FromJust());
2231 }
2232}
2233
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002234static void GetFlabby(const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002235 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002236 args.GetReturnValue().Set(v8_num(17.2));
Steve Blocka7e24c12009-10-30 11:49:00 +00002237}
2238
2239
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002240static void GetKnurd(Local<String> property,
2241 const v8::PropertyCallbackInfo<v8::Value>& info) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002242 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002243 info.GetReturnValue().Set(v8_num(15.2));
Steve Blocka7e24c12009-10-30 11:49:00 +00002244}
2245
2246
2247THREADED_TEST(DescriptorInheritance) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002248 v8::Isolate* isolate = CcTest::isolate();
2249 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002250 v8::Local<v8::FunctionTemplate> super = v8::FunctionTemplate::New(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002251 super->PrototypeTemplate()->Set(isolate, "flabby",
2252 v8::FunctionTemplate::New(isolate,
2253 GetFlabby));
2254 super->PrototypeTemplate()->Set(isolate, "PI", v8_num(3.14));
Steve Blocka7e24c12009-10-30 11:49:00 +00002255
2256 super->InstanceTemplate()->SetAccessor(v8_str("knurd"), GetKnurd);
2257
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002258 v8::Local<v8::FunctionTemplate> base1 = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00002259 base1->Inherit(super);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002260 base1->PrototypeTemplate()->Set(isolate, "v1", v8_num(20.1));
Steve Blocka7e24c12009-10-30 11:49:00 +00002261
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002262 v8::Local<v8::FunctionTemplate> base2 = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00002263 base2->Inherit(super);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002264 base2->PrototypeTemplate()->Set(isolate, "v2", v8_num(10.1));
Steve Blocka7e24c12009-10-30 11:49:00 +00002265
2266 LocalContext env;
2267
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002268 CHECK(env->Global()
2269 ->Set(env.local(), v8_str("s"),
2270 super->GetFunction(env.local()).ToLocalChecked())
2271 .FromJust());
2272 CHECK(env->Global()
2273 ->Set(env.local(), v8_str("base1"),
2274 base1->GetFunction(env.local()).ToLocalChecked())
2275 .FromJust());
2276 CHECK(env->Global()
2277 ->Set(env.local(), v8_str("base2"),
2278 base2->GetFunction(env.local()).ToLocalChecked())
2279 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00002280
2281 // Checks right __proto__ chain.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002282 CHECK(CompileRun("base1.prototype.__proto__ == s.prototype")
2283 ->BooleanValue(env.local())
2284 .FromJust());
2285 CHECK(CompileRun("base2.prototype.__proto__ == s.prototype")
2286 ->BooleanValue(env.local())
2287 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00002288
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002289 CHECK(v8_compile("s.prototype.PI == 3.14")
2290 ->Run(env.local())
2291 .ToLocalChecked()
2292 ->BooleanValue(env.local())
2293 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00002294
2295 // Instance accessor should not be visible on function object or its prototype
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002296 CHECK(
2297 CompileRun("s.knurd == undefined")->BooleanValue(env.local()).FromJust());
2298 CHECK(CompileRun("s.prototype.knurd == undefined")
2299 ->BooleanValue(env.local())
2300 .FromJust());
2301 CHECK(CompileRun("base1.prototype.knurd == undefined")
2302 ->BooleanValue(env.local())
2303 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00002304
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002305 CHECK(env->Global()
2306 ->Set(env.local(), v8_str("obj"), base1->GetFunction(env.local())
2307 .ToLocalChecked()
2308 ->NewInstance(env.local())
2309 .ToLocalChecked())
2310 .FromJust());
Ben Murdoch097c5b22016-05-18 11:27:45 +01002311 CHECK_EQ(17.2,
2312 CompileRun("obj.flabby()")->NumberValue(env.local()).FromJust());
2313 CHECK(CompileRun("'flabby' in obj")->BooleanValue(env.local()).FromJust());
2314 CHECK_EQ(15.2, CompileRun("obj.knurd")->NumberValue(env.local()).FromJust());
2315 CHECK(CompileRun("'knurd' in obj")->BooleanValue(env.local()).FromJust());
2316 CHECK_EQ(20.1, CompileRun("obj.v1")->NumberValue(env.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00002317
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002318 CHECK(env->Global()
2319 ->Set(env.local(), v8_str("obj2"), base2->GetFunction(env.local())
2320 .ToLocalChecked()
2321 ->NewInstance(env.local())
2322 .ToLocalChecked())
2323 .FromJust());
Ben Murdoch097c5b22016-05-18 11:27:45 +01002324 CHECK_EQ(17.2,
2325 CompileRun("obj2.flabby()")->NumberValue(env.local()).FromJust());
2326 CHECK(CompileRun("'flabby' in obj2")->BooleanValue(env.local()).FromJust());
2327 CHECK_EQ(15.2, CompileRun("obj2.knurd")->NumberValue(env.local()).FromJust());
2328 CHECK(CompileRun("'knurd' in obj2")->BooleanValue(env.local()).FromJust());
2329 CHECK_EQ(10.1, CompileRun("obj2.v2")->NumberValue(env.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00002330
2331 // base1 and base2 cannot cross reference to each's prototype
Ben Murdoch097c5b22016-05-18 11:27:45 +01002332 CHECK(CompileRun("obj.v2")->IsUndefined());
2333 CHECK(CompileRun("obj2.v1")->IsUndefined());
2334}
2335
2336THREADED_TEST(DescriptorInheritance2) {
2337 LocalContext env;
2338 v8::Isolate* isolate = CcTest::isolate();
2339 v8::HandleScope scope(isolate);
2340 v8::Local<v8::FunctionTemplate> fun_A = v8::FunctionTemplate::New(isolate);
2341 fun_A->SetClassName(v8_str("A"));
2342 fun_A->InstanceTemplate()->SetNativeDataProperty(v8_str("knurd1"), GetKnurd);
2343 fun_A->InstanceTemplate()->SetNativeDataProperty(v8_str("nirk1"), GetNirk);
2344 fun_A->InstanceTemplate()->SetNativeDataProperty(v8_str("rino1"), GetRino);
2345
2346 v8::Local<v8::FunctionTemplate> fun_B = v8::FunctionTemplate::New(isolate);
2347 fun_B->SetClassName(v8_str("B"));
2348 fun_B->Inherit(fun_A);
2349
2350 v8::Local<v8::FunctionTemplate> fun_C = v8::FunctionTemplate::New(isolate);
2351 fun_C->SetClassName(v8_str("C"));
2352 fun_C->Inherit(fun_B);
2353 fun_C->InstanceTemplate()->SetNativeDataProperty(v8_str("knurd2"), GetKnurd);
2354 fun_C->InstanceTemplate()->SetNativeDataProperty(v8_str("nirk2"), GetNirk);
2355 fun_C->InstanceTemplate()->SetNativeDataProperty(v8_str("rino2"), GetRino);
2356
2357 v8::Local<v8::FunctionTemplate> fun_D = v8::FunctionTemplate::New(isolate);
2358 fun_D->SetClassName(v8_str("D"));
2359 fun_D->Inherit(fun_C);
2360
2361 v8::Local<v8::FunctionTemplate> fun_E = v8::FunctionTemplate::New(isolate);
2362 fun_E->SetClassName(v8_str("E"));
2363 fun_E->Inherit(fun_D);
2364 fun_E->InstanceTemplate()->SetNativeDataProperty(v8_str("knurd3"), GetKnurd);
2365 fun_E->InstanceTemplate()->SetNativeDataProperty(v8_str("nirk3"), GetNirk);
2366 fun_E->InstanceTemplate()->SetNativeDataProperty(v8_str("rino3"), GetRino);
2367
2368 v8::Local<v8::FunctionTemplate> fun_F = v8::FunctionTemplate::New(isolate);
2369 fun_F->SetClassName(v8_str("F"));
2370 fun_F->Inherit(fun_E);
2371 v8::Local<v8::ObjectTemplate> templ = fun_F->InstanceTemplate();
2372 const int kDataPropertiesNumber = 100;
2373 for (int i = 0; i < kDataPropertiesNumber; i++) {
2374 v8::Local<v8::Value> val = v8_num(i);
2375 v8::Local<v8::String> val_str = val->ToString(env.local()).ToLocalChecked();
2376 v8::Local<v8::String> name = String::Concat(v8_str("p"), val_str);
2377
2378 templ->Set(name, val);
2379 templ->Set(val_str, val);
2380 }
2381
2382 CHECK(env->Global()
2383 ->Set(env.local(), v8_str("F"),
2384 fun_F->GetFunction(env.local()).ToLocalChecked())
2385 .FromJust());
2386
2387 v8::Local<v8::Script> script = v8_compile("o = new F()");
2388
2389 for (int i = 0; i < 100; i++) {
2390 v8::HandleScope scope(isolate);
2391 script->Run(env.local()).ToLocalChecked();
2392 }
2393 v8::Local<v8::Object> object = script->Run(env.local())
2394 .ToLocalChecked()
2395 ->ToObject(env.local())
2396 .ToLocalChecked();
2397
2398 CHECK_EQ(15.2, CompileRun("o.knurd1")->NumberValue(env.local()).FromJust());
2399 CHECK_EQ(15.2, CompileRun("o.knurd2")->NumberValue(env.local()).FromJust());
2400 CHECK_EQ(15.2, CompileRun("o.knurd3")->NumberValue(env.local()).FromJust());
2401
2402 CHECK_EQ(900, CompileRun("o.nirk1")->IntegerValue(env.local()).FromJust());
2403 CHECK_EQ(900, CompileRun("o.nirk2")->IntegerValue(env.local()).FromJust());
2404 CHECK_EQ(900, CompileRun("o.nirk3")->IntegerValue(env.local()).FromJust());
2405
2406 CHECK_EQ(560, CompileRun("o.rino1")->IntegerValue(env.local()).FromJust());
2407 CHECK_EQ(560, CompileRun("o.rino2")->IntegerValue(env.local()).FromJust());
2408 CHECK_EQ(560, CompileRun("o.rino3")->IntegerValue(env.local()).FromJust());
2409
2410 for (int i = 0; i < kDataPropertiesNumber; i++) {
2411 v8::Local<v8::Value> val = v8_num(i);
2412 v8::Local<v8::String> val_str = val->ToString(env.local()).ToLocalChecked();
2413 v8::Local<v8::String> name = String::Concat(v8_str("p"), val_str);
2414
2415 CHECK_EQ(i, object->Get(env.local(), name)
2416 .ToLocalChecked()
2417 ->IntegerValue(env.local())
2418 .FromJust());
2419 CHECK_EQ(i, object->Get(env.local(), val)
2420 .ToLocalChecked()
2421 ->IntegerValue(env.local())
2422 .FromJust());
2423 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002424}
2425
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002426
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002427// Helper functions for Interceptor/Accessor interaction tests
2428
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002429void SimpleAccessorGetter(Local<String> name,
2430 const v8::PropertyCallbackInfo<v8::Value>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002431 Local<Object> self = Local<Object>::Cast(info.This());
2432 info.GetReturnValue().Set(self->Get(info.GetIsolate()->GetCurrentContext(),
2433 String::Concat(v8_str("accessor_"), name))
2434 .ToLocalChecked());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002435}
2436
2437void SimpleAccessorSetter(Local<String> name, Local<Value> value,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002438 const v8::PropertyCallbackInfo<void>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002439 Local<Object> self = Local<Object>::Cast(info.This());
2440 CHECK(self->Set(info.GetIsolate()->GetCurrentContext(),
2441 String::Concat(v8_str("accessor_"), name), value)
2442 .FromJust());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002443}
2444
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002445void SymbolAccessorGetter(Local<Name> name,
2446 const v8::PropertyCallbackInfo<v8::Value>& info) {
2447 CHECK(name->IsSymbol());
2448 Local<Symbol> sym = Local<Symbol>::Cast(name);
2449 if (sym->Name()->IsUndefined())
2450 return;
2451 SimpleAccessorGetter(Local<String>::Cast(sym->Name()), info);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002452}
2453
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002454void SymbolAccessorSetter(Local<Name> name, Local<Value> value,
2455 const v8::PropertyCallbackInfo<void>& info) {
2456 CHECK(name->IsSymbol());
2457 Local<Symbol> sym = Local<Symbol>::Cast(name);
2458 if (sym->Name()->IsUndefined())
2459 return;
2460 SimpleAccessorSetter(Local<String>::Cast(sym->Name()), value, info);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002461}
2462
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002463void SymbolAccessorGetterReturnsDefault(
2464 Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
2465 CHECK(name->IsSymbol());
2466 Local<Symbol> sym = Local<Symbol>::Cast(name);
2467 if (sym->Name()->IsUndefined()) return;
2468 info.GetReturnValue().Set(info.Data());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002469}
2470
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002471static void ThrowingSymbolAccessorGetter(
2472 Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
2473 info.GetReturnValue().Set(info.GetIsolate()->ThrowException(name));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002474}
2475
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002476
Ben Murdoch097c5b22016-05-18 11:27:45 +01002477THREADED_TEST(AccessorIsPreservedOnAttributeChange) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002478 v8::Isolate* isolate = CcTest::isolate();
2479 v8::HandleScope scope(isolate);
2480 LocalContext env;
2481 v8::Local<v8::Value> res = CompileRun("var a = []; a;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002482 i::Handle<i::JSReceiver> a(v8::Utils::OpenHandle(v8::Object::Cast(*res)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002483 CHECK(a->map()->instance_descriptors()->IsFixedArray());
2484 CHECK_GT(i::FixedArray::cast(a->map()->instance_descriptors())->length(), 0);
2485 CompileRun("Object.defineProperty(a, 'length', { writable: false });");
2486 CHECK_EQ(i::FixedArray::cast(a->map()->instance_descriptors())->length(), 0);
Ben Murdoch097c5b22016-05-18 11:27:45 +01002487 // But we should still have an AccessorInfo.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002488 i::Handle<i::String> name(v8::Utils::OpenHandle(*v8_str("length")));
2489 i::LookupIterator it(a, name, i::LookupIterator::OWN_SKIP_INTERCEPTOR);
2490 CHECK_EQ(i::LookupIterator::ACCESSOR, it.state());
Ben Murdoch097c5b22016-05-18 11:27:45 +01002491 CHECK(it.GetAccessors()->IsAccessorInfo());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002492}
2493
2494
Steve Blocka7e24c12009-10-30 11:49:00 +00002495THREADED_TEST(UndefinedIsNotEnumerable) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002496 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002497 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002498 v8::Local<Value> result = CompileRun("this.propertyIsEnumerable(undefined)");
Steve Blocka7e24c12009-10-30 11:49:00 +00002499 CHECK(result->IsFalse());
2500}
2501
2502
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002503v8::Local<Script> call_recursively_script;
2504static const int kTargetRecursionDepth = 150; // near maximum
Steve Blocka7e24c12009-10-30 11:49:00 +00002505
2506
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002507static void CallScriptRecursivelyCall(
2508 const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002509 ApiTestFuzzer::Fuzz();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002510 v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
2511 int depth = args.This()
2512 ->Get(context, v8_str("depth"))
2513 .ToLocalChecked()
2514 ->Int32Value(context)
2515 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002516 if (depth == kTargetRecursionDepth) return;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002517 CHECK(args.This()
2518 ->Set(context, v8_str("depth"),
2519 v8::Integer::New(args.GetIsolate(), depth + 1))
2520 .FromJust());
2521 args.GetReturnValue().Set(
2522 call_recursively_script->Run(context).ToLocalChecked());
Steve Blocka7e24c12009-10-30 11:49:00 +00002523}
2524
2525
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002526static void CallFunctionRecursivelyCall(
2527 const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002528 ApiTestFuzzer::Fuzz();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002529 v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
2530 int depth = args.This()
2531 ->Get(context, v8_str("depth"))
2532 .ToLocalChecked()
2533 ->Int32Value(context)
2534 .FromJust();
Steve Blocka7e24c12009-10-30 11:49:00 +00002535 if (depth == kTargetRecursionDepth) {
2536 printf("[depth = %d]\n", depth);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002537 return;
Steve Blocka7e24c12009-10-30 11:49:00 +00002538 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002539 CHECK(args.This()
2540 ->Set(context, v8_str("depth"),
2541 v8::Integer::New(args.GetIsolate(), depth + 1))
2542 .FromJust());
2543 v8::Local<Value> function =
2544 args.This()
2545 ->Get(context, v8_str("callFunctionRecursively"))
2546 .ToLocalChecked();
2547 args.GetReturnValue().Set(function.As<Function>()
2548 ->Call(context, args.This(), 0, NULL)
2549 .ToLocalChecked());
Steve Blocka7e24c12009-10-30 11:49:00 +00002550}
2551
2552
2553THREADED_TEST(DeepCrossLanguageRecursion) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002554 v8::Isolate* isolate = CcTest::isolate();
2555 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002556 v8::Local<v8::ObjectTemplate> global = ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00002557 global->Set(v8_str("callScriptRecursively"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002558 v8::FunctionTemplate::New(isolate, CallScriptRecursivelyCall));
Steve Blocka7e24c12009-10-30 11:49:00 +00002559 global->Set(v8_str("callFunctionRecursively"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002560 v8::FunctionTemplate::New(isolate, CallFunctionRecursivelyCall));
Steve Blocka7e24c12009-10-30 11:49:00 +00002561 LocalContext env(NULL, global);
2562
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002563 CHECK(env->Global()
2564 ->Set(env.local(), v8_str("depth"), v8::Integer::New(isolate, 0))
2565 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00002566 call_recursively_script = v8_compile("callScriptRecursively()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002567 call_recursively_script->Run(env.local()).ToLocalChecked();
2568 call_recursively_script = v8::Local<Script>();
Steve Blocka7e24c12009-10-30 11:49:00 +00002569
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002570 CHECK(env->Global()
2571 ->Set(env.local(), v8_str("depth"), v8::Integer::New(isolate, 0))
2572 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002573 CompileRun("callFunctionRecursively()");
Steve Blocka7e24c12009-10-30 11:49:00 +00002574}
2575
2576
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002577static void ThrowingPropertyHandlerGet(
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002578 Local<Name> key, const v8::PropertyCallbackInfo<v8::Value>& info) {
2579 // Since this interceptor is used on "with" objects, the runtime will look up
2580 // @@unscopables. Punt.
2581 if (key->IsSymbol()) return;
Steve Blocka7e24c12009-10-30 11:49:00 +00002582 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002583 info.GetReturnValue().Set(info.GetIsolate()->ThrowException(key));
Steve Blocka7e24c12009-10-30 11:49:00 +00002584}
2585
2586
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002587static void ThrowingPropertyHandlerSet(
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002588 Local<Name> key, Local<Value>,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002589 const v8::PropertyCallbackInfo<v8::Value>& info) {
2590 info.GetIsolate()->ThrowException(key);
2591 info.GetReturnValue().SetUndefined(); // not the same as empty handle
Steve Blocka7e24c12009-10-30 11:49:00 +00002592}
2593
2594
2595THREADED_TEST(CallbackExceptionRegression) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002596 v8::Isolate* isolate = CcTest::isolate();
2597 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002598 v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002599 obj->SetHandler(v8::NamedPropertyHandlerConfiguration(
2600 ThrowingPropertyHandlerGet, ThrowingPropertyHandlerSet));
Steve Blocka7e24c12009-10-30 11:49:00 +00002601 LocalContext env;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002602 CHECK(env->Global()
2603 ->Set(env.local(), v8_str("obj"),
2604 obj->NewInstance(env.local()).ToLocalChecked())
2605 .FromJust());
2606 v8::Local<Value> otto =
2607 CompileRun("try { with (obj) { otto; } } catch (e) { e; }");
2608 CHECK(v8_str("otto")->Equals(env.local(), otto).FromJust());
2609 v8::Local<Value> netto =
2610 CompileRun("try { with (obj) { netto = 4; } } catch (e) { e; }");
2611 CHECK(v8_str("netto")->Equals(env.local(), netto).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00002612}
2613
2614
Steve Blocka7e24c12009-10-30 11:49:00 +00002615THREADED_TEST(FunctionPrototype) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002616 v8::Isolate* isolate = CcTest::isolate();
2617 v8::HandleScope scope(isolate);
2618 Local<v8::FunctionTemplate> Foo = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00002619 Foo->PrototypeTemplate()->Set(v8_str("plak"), v8_num(321));
2620 LocalContext env;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002621 CHECK(env->Global()
2622 ->Set(env.local(), v8_str("Foo"),
2623 Foo->GetFunction(env.local()).ToLocalChecked())
2624 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002625 Local<Script> script = v8_compile("Foo.prototype.plak");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002626 CHECK_EQ(v8_run_int32value(script), 321);
Steve Blocka7e24c12009-10-30 11:49:00 +00002627}
2628
2629
2630THREADED_TEST(InternalFields) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002631 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002632 v8::Isolate* isolate = env->GetIsolate();
2633 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00002634
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002635 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00002636 Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
2637 instance_templ->SetInternalFieldCount(1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002638 Local<v8::Object> obj = templ->GetFunction(env.local())
2639 .ToLocalChecked()
2640 ->NewInstance(env.local())
2641 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00002642 CHECK_EQ(1, obj->InternalFieldCount());
2643 CHECK(obj->GetInternalField(0)->IsUndefined());
2644 obj->SetInternalField(0, v8_num(17));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002645 CHECK_EQ(17, obj->GetInternalField(0)->Int32Value(env.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00002646}
2647
2648
Steve Block6ded16b2010-05-10 14:33:55 +01002649THREADED_TEST(GlobalObjectInternalFields) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002650 v8::Isolate* isolate = CcTest::isolate();
2651 v8::HandleScope scope(isolate);
2652 Local<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New(isolate);
Steve Block6ded16b2010-05-10 14:33:55 +01002653 global_template->SetInternalFieldCount(1);
2654 LocalContext env(NULL, global_template);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002655 v8::Local<v8::Object> global_proxy = env->Global();
2656 v8::Local<v8::Object> global = global_proxy->GetPrototype().As<v8::Object>();
Steve Block6ded16b2010-05-10 14:33:55 +01002657 CHECK_EQ(1, global->InternalFieldCount());
2658 CHECK(global->GetInternalField(0)->IsUndefined());
2659 global->SetInternalField(0, v8_num(17));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002660 CHECK_EQ(17, global->GetInternalField(0)->Int32Value(env.local()).FromJust());
Steve Block6ded16b2010-05-10 14:33:55 +01002661}
2662
2663
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002664THREADED_TEST(GlobalObjectHasRealIndexedProperty) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002665 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002666 v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00002667
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002668 v8::Local<v8::Object> global = env->Global();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002669 CHECK(global->Set(env.local(), 0, v8_str("value")).FromJust());
2670 CHECK(global->HasRealIndexedProperty(env.local(), 0).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00002671}
2672
2673
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002674static void CheckAlignedPointerInInternalField(Local<v8::Object> obj,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002675 void* value) {
2676 CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(value) & 0x1));
2677 obj->SetAlignedPointerInInternalField(0, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002678 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002679 CHECK_EQ(value, obj->GetAlignedPointerFromInternalField(0));
2680}
Steve Block3ce2e202009-11-05 08:53:23 +00002681
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002682
2683THREADED_TEST(InternalFieldsAlignedPointers) {
2684 LocalContext env;
2685 v8::Isolate* isolate = env->GetIsolate();
2686 v8::HandleScope scope(isolate);
2687
2688 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
Steve Block3ce2e202009-11-05 08:53:23 +00002689 Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
2690 instance_templ->SetInternalFieldCount(1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002691 Local<v8::Object> obj = templ->GetFunction(env.local())
2692 .ToLocalChecked()
2693 ->NewInstance(env.local())
2694 .ToLocalChecked();
Steve Block3ce2e202009-11-05 08:53:23 +00002695 CHECK_EQ(1, obj->InternalFieldCount());
Steve Block3ce2e202009-11-05 08:53:23 +00002696
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002697 CheckAlignedPointerInInternalField(obj, NULL);
Steve Block3ce2e202009-11-05 08:53:23 +00002698
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002699 int* heap_allocated = new int[100];
2700 CheckAlignedPointerInInternalField(obj, heap_allocated);
2701 delete[] heap_allocated;
Steve Block3ce2e202009-11-05 08:53:23 +00002702
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002703 int stack_allocated[100];
2704 CheckAlignedPointerInInternalField(obj, stack_allocated);
Steve Block3ce2e202009-11-05 08:53:23 +00002705
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002706 void* huge = reinterpret_cast<void*>(~static_cast<uintptr_t>(1));
2707 CheckAlignedPointerInInternalField(obj, huge);
Steve Block3ce2e202009-11-05 08:53:23 +00002708
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002709 v8::Global<v8::Object> persistent(isolate, obj);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002710 CHECK_EQ(1, Object::InternalFieldCount(persistent));
2711 CHECK_EQ(huge, Object::GetAlignedPointerFromInternalField(persistent, 0));
2712}
Steve Block3ce2e202009-11-05 08:53:23 +00002713
Steve Block3ce2e202009-11-05 08:53:23 +00002714
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002715static void CheckAlignedPointerInEmbedderData(LocalContext* env, int index,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002716 void* value) {
2717 CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(value) & 0x1));
2718 (*env)->SetAlignedPointerInEmbedderData(index, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002719 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002720 CHECK_EQ(value, (*env)->GetAlignedPointerFromEmbedderData(index));
2721}
2722
2723
2724static void* AlignedTestPointer(int i) {
2725 return reinterpret_cast<void*>(i * 1234);
2726}
2727
2728
2729THREADED_TEST(EmbedderDataAlignedPointers) {
2730 LocalContext env;
2731 v8::HandleScope scope(env->GetIsolate());
2732
2733 CheckAlignedPointerInEmbedderData(&env, 0, NULL);
2734
2735 int* heap_allocated = new int[100];
2736 CheckAlignedPointerInEmbedderData(&env, 1, heap_allocated);
2737 delete[] heap_allocated;
2738
2739 int stack_allocated[100];
2740 CheckAlignedPointerInEmbedderData(&env, 2, stack_allocated);
2741
2742 void* huge = reinterpret_cast<void*>(~static_cast<uintptr_t>(1));
2743 CheckAlignedPointerInEmbedderData(&env, 3, huge);
2744
2745 // Test growing of the embedder data's backing store.
2746 for (int i = 0; i < 100; i++) {
2747 env->SetAlignedPointerInEmbedderData(i, AlignedTestPointer(i));
2748 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002749 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002750 for (int i = 0; i < 100; i++) {
2751 CHECK_EQ(AlignedTestPointer(i), env->GetAlignedPointerFromEmbedderData(i));
2752 }
2753}
2754
2755
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002756static void CheckEmbedderData(LocalContext* env, int index,
2757 v8::Local<Value> data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002758 (*env)->SetEmbedderData(index, data);
2759 CHECK((*env)->GetEmbedderData(index)->StrictEquals(data));
2760}
2761
2762
2763THREADED_TEST(EmbedderData) {
2764 LocalContext env;
2765 v8::Isolate* isolate = env->GetIsolate();
2766 v8::HandleScope scope(isolate);
2767
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002768 CheckEmbedderData(&env, 3, v8_str("The quick brown fox jumps"));
2769 CheckEmbedderData(&env, 2, v8_str("over the lazy dog."));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002770 CheckEmbedderData(&env, 1, v8::Number::New(isolate, 1.2345));
2771 CheckEmbedderData(&env, 0, v8::Boolean::New(isolate, true));
Steve Block3ce2e202009-11-05 08:53:23 +00002772}
2773
2774
Steve Blocka7e24c12009-10-30 11:49:00 +00002775THREADED_TEST(IdentityHash) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002776 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002777 v8::Isolate* isolate = env->GetIsolate();
2778 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00002779
2780 // Ensure that the test starts with an fresh heap to test whether the hash
2781 // code is based on the address.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002782 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002783 Local<v8::Object> obj = v8::Object::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00002784 int hash = obj->GetIdentityHash();
2785 int hash1 = obj->GetIdentityHash();
2786 CHECK_EQ(hash, hash1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002787 int hash2 = v8::Object::New(isolate)->GetIdentityHash();
Steve Blocka7e24c12009-10-30 11:49:00 +00002788 // Since the identity hash is essentially a random number two consecutive
2789 // objects should not be assigned the same hash code. If the test below fails
2790 // the random number generator should be evaluated.
2791 CHECK_NE(hash, hash2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002792 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002793 int hash3 = v8::Object::New(isolate)->GetIdentityHash();
Steve Blocka7e24c12009-10-30 11:49:00 +00002794 // Make sure that the identity hash is not based on the initial address of
2795 // the object alone. If the test below fails the random number generator
2796 // should be evaluated.
2797 CHECK_NE(hash, hash3);
2798 int hash4 = obj->GetIdentityHash();
2799 CHECK_EQ(hash, hash4);
Steve Block1e0659c2011-05-24 12:43:12 +01002800
2801 // Check identity hashes behaviour in the presence of JS accessors.
2802 // Put a getter for 'v8::IdentityHash' on the Object's prototype:
2803 {
2804 CompileRun("Object.prototype['v8::IdentityHash'] = 42;\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002805 Local<v8::Object> o1 = v8::Object::New(isolate);
2806 Local<v8::Object> o2 = v8::Object::New(isolate);
Steve Block1e0659c2011-05-24 12:43:12 +01002807 CHECK_NE(o1->GetIdentityHash(), o2->GetIdentityHash());
2808 }
2809 {
2810 CompileRun(
2811 "function cnst() { return 42; };\n"
2812 "Object.prototype.__defineGetter__('v8::IdentityHash', cnst);\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002813 Local<v8::Object> o1 = v8::Object::New(isolate);
2814 Local<v8::Object> o2 = v8::Object::New(isolate);
Steve Block1e0659c2011-05-24 12:43:12 +01002815 CHECK_NE(o1->GetIdentityHash(), o2->GetIdentityHash());
2816 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002817}
2818
2819
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002820void GlobalProxyIdentityHash(bool set_in_js) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002821 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002822 v8::Isolate* isolate = env->GetIsolate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002823 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002824 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002825 Local<Object> global_proxy = env->Global();
2826 i::Handle<i::Object> i_global_proxy = v8::Utils::OpenHandle(*global_proxy);
2827 CHECK(env->Global()
2828 ->Set(env.local(), v8_str("global"), global_proxy)
2829 .FromJust());
2830 i::Handle<i::Object> original_hash;
2831 if (set_in_js) {
2832 CompileRun("var m = new Set(); m.add(global);");
2833 original_hash = i::Handle<i::Object>(i_global_proxy->GetHash(), i_isolate);
2834 } else {
2835 original_hash = i::Handle<i::Object>(
2836 i::Object::GetOrCreateHash(i_isolate, i_global_proxy));
2837 }
2838 CHECK(original_hash->IsSmi());
2839 int32_t hash1 = i::Handle<i::Smi>::cast(original_hash)->value();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002840 // Hash should be retained after being detached.
2841 env->DetachGlobal();
2842 int hash2 = global_proxy->GetIdentityHash();
2843 CHECK_EQ(hash1, hash2);
2844 {
2845 // Re-attach global proxy to a new context, hash should stay the same.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002846 LocalContext env2(NULL, Local<ObjectTemplate>(), global_proxy);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002847 int hash3 = global_proxy->GetIdentityHash();
2848 CHECK_EQ(hash1, hash3);
2849 }
2850}
Steve Blocka7e24c12009-10-30 11:49:00 +00002851
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002852
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002853THREADED_TEST(GlobalProxyIdentityHash) {
2854 GlobalProxyIdentityHash(true);
2855 GlobalProxyIdentityHash(false);
2856}
2857
2858
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002859TEST(SymbolIdentityHash) {
2860 LocalContext env;
2861 v8::Isolate* isolate = env->GetIsolate();
2862 v8::HandleScope scope(isolate);
2863
2864 {
2865 Local<v8::Symbol> symbol = v8::Symbol::New(isolate);
2866 int hash = symbol->GetIdentityHash();
2867 int hash1 = symbol->GetIdentityHash();
2868 CHECK_EQ(hash, hash1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002869 CcTest::heap()->CollectAllGarbage();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002870 int hash3 = symbol->GetIdentityHash();
2871 CHECK_EQ(hash, hash3);
2872 }
2873
2874 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002875 v8::Local<v8::Symbol> js_symbol =
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002876 CompileRun("Symbol('foo')").As<v8::Symbol>();
2877 int hash = js_symbol->GetIdentityHash();
2878 int hash1 = js_symbol->GetIdentityHash();
2879 CHECK_EQ(hash, hash1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002880 CcTest::heap()->CollectAllGarbage();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002881 int hash3 = js_symbol->GetIdentityHash();
2882 CHECK_EQ(hash, hash3);
2883 }
2884}
2885
2886
2887TEST(StringIdentityHash) {
2888 LocalContext env;
2889 v8::Isolate* isolate = env->GetIsolate();
2890 v8::HandleScope scope(isolate);
2891
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002892 Local<v8::String> str = v8_str("str1");
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002893 int hash = str->GetIdentityHash();
2894 int hash1 = str->GetIdentityHash();
2895 CHECK_EQ(hash, hash1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002896 CcTest::heap()->CollectAllGarbage();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002897 int hash3 = str->GetIdentityHash();
2898 CHECK_EQ(hash, hash3);
2899
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002900 Local<v8::String> str2 = v8_str("str1");
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002901 int hash4 = str2->GetIdentityHash();
2902 CHECK_EQ(hash, hash4);
2903}
2904
2905
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002906THREADED_TEST(SymbolProperties) {
2907 LocalContext env;
2908 v8::Isolate* isolate = env->GetIsolate();
2909 v8::HandleScope scope(isolate);
2910
2911 v8::Local<v8::Object> obj = v8::Object::New(isolate);
2912 v8::Local<v8::Symbol> sym1 = v8::Symbol::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002913 v8::Local<v8::Symbol> sym2 = v8::Symbol::New(isolate, v8_str("my-symbol"));
2914 v8::Local<v8::Symbol> sym3 = v8::Symbol::New(isolate, v8_str("sym3"));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002915
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002916 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002917
2918 // Check basic symbol functionality.
2919 CHECK(sym1->IsSymbol());
2920 CHECK(sym2->IsSymbol());
2921 CHECK(!obj->IsSymbol());
2922
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002923 CHECK(sym1->Equals(env.local(), sym1).FromJust());
2924 CHECK(sym2->Equals(env.local(), sym2).FromJust());
2925 CHECK(!sym1->Equals(env.local(), sym2).FromJust());
2926 CHECK(!sym2->Equals(env.local(), sym1).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002927 CHECK(sym1->StrictEquals(sym1));
2928 CHECK(sym2->StrictEquals(sym2));
2929 CHECK(!sym1->StrictEquals(sym2));
2930 CHECK(!sym2->StrictEquals(sym1));
2931
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002932 CHECK(sym2->Name()->Equals(env.local(), v8_str("my-symbol")).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002933
2934 v8::Local<v8::Value> sym_val = sym2;
2935 CHECK(sym_val->IsSymbol());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002936 CHECK(sym_val->Equals(env.local(), sym2).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002937 CHECK(sym_val->StrictEquals(sym2));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002938 CHECK(v8::Symbol::Cast(*sym_val)->Equals(env.local(), sym2).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002939
2940 v8::Local<v8::Value> sym_obj = v8::SymbolObject::New(isolate, sym2);
2941 CHECK(sym_obj->IsSymbolObject());
2942 CHECK(!sym2->IsSymbolObject());
2943 CHECK(!obj->IsSymbolObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002944 CHECK(sym_obj->Equals(env.local(), sym2).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002945 CHECK(!sym_obj->StrictEquals(sym2));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002946 CHECK(v8::SymbolObject::Cast(*sym_obj)
2947 ->Equals(env.local(), sym_obj)
2948 .FromJust());
2949 CHECK(v8::SymbolObject::Cast(*sym_obj)
2950 ->ValueOf()
2951 ->Equals(env.local(), sym2)
2952 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002953
2954 // Make sure delete of a non-existent symbol property works.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002955 CHECK(obj->Delete(env.local(), sym1).FromJust());
2956 CHECK(!obj->Has(env.local(), sym1).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002957
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002958 CHECK(
2959 obj->Set(env.local(), sym1, v8::Integer::New(isolate, 1503)).FromJust());
2960 CHECK(obj->Has(env.local(), sym1).FromJust());
2961 CHECK_EQ(1503, obj->Get(env.local(), sym1)
2962 .ToLocalChecked()
2963 ->Int32Value(env.local())
2964 .FromJust());
2965 CHECK(
2966 obj->Set(env.local(), sym1, v8::Integer::New(isolate, 2002)).FromJust());
2967 CHECK(obj->Has(env.local(), sym1).FromJust());
2968 CHECK_EQ(2002, obj->Get(env.local(), sym1)
2969 .ToLocalChecked()
2970 ->Int32Value(env.local())
2971 .FromJust());
2972 CHECK_EQ(v8::None, obj->GetPropertyAttributes(env.local(), sym1).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002973
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002974 CHECK_EQ(0u,
2975 obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
2976 unsigned num_props =
2977 obj->GetPropertyNames(env.local()).ToLocalChecked()->Length();
2978 CHECK(obj->Set(env.local(), v8_str("bla"), v8::Integer::New(isolate, 20))
2979 .FromJust());
2980 CHECK_EQ(1u,
2981 obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
2982 CHECK_EQ(num_props + 1,
2983 obj->GetPropertyNames(env.local()).ToLocalChecked()->Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002984
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002985 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002986
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002987 CHECK(obj->SetAccessor(env.local(), sym3, SymbolAccessorGetter,
2988 SymbolAccessorSetter)
2989 .FromJust());
2990 CHECK(obj->Get(env.local(), sym3).ToLocalChecked()->IsUndefined());
2991 CHECK(obj->Set(env.local(), sym3, v8::Integer::New(isolate, 42)).FromJust());
2992 CHECK(obj->Get(env.local(), sym3)
2993 .ToLocalChecked()
2994 ->Equals(env.local(), v8::Integer::New(isolate, 42))
2995 .FromJust());
2996 CHECK(obj->Get(env.local(), v8_str("accessor_sym3"))
2997 .ToLocalChecked()
2998 ->Equals(env.local(), v8::Integer::New(isolate, 42))
2999 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003000
3001 // Add another property and delete it afterwards to force the object in
3002 // slow case.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003003 CHECK(
3004 obj->Set(env.local(), sym2, v8::Integer::New(isolate, 2008)).FromJust());
3005 CHECK_EQ(2002, obj->Get(env.local(), sym1)
3006 .ToLocalChecked()
3007 ->Int32Value(env.local())
3008 .FromJust());
3009 CHECK_EQ(2008, obj->Get(env.local(), sym2)
3010 .ToLocalChecked()
3011 ->Int32Value(env.local())
3012 .FromJust());
3013 CHECK_EQ(2002, obj->Get(env.local(), sym1)
3014 .ToLocalChecked()
3015 ->Int32Value(env.local())
3016 .FromJust());
3017 CHECK_EQ(2u,
3018 obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003019
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003020 CHECK(obj->Has(env.local(), sym1).FromJust());
3021 CHECK(obj->Has(env.local(), sym2).FromJust());
3022 CHECK(obj->Has(env.local(), sym3).FromJust());
3023 CHECK(obj->Has(env.local(), v8_str("accessor_sym3")).FromJust());
3024 CHECK(obj->Delete(env.local(), sym2).FromJust());
3025 CHECK(obj->Has(env.local(), sym1).FromJust());
3026 CHECK(!obj->Has(env.local(), sym2).FromJust());
3027 CHECK(obj->Has(env.local(), sym3).FromJust());
3028 CHECK(obj->Has(env.local(), v8_str("accessor_sym3")).FromJust());
3029 CHECK_EQ(2002, obj->Get(env.local(), sym1)
3030 .ToLocalChecked()
3031 ->Int32Value(env.local())
3032 .FromJust());
3033 CHECK(obj->Get(env.local(), sym3)
3034 .ToLocalChecked()
3035 ->Equals(env.local(), v8::Integer::New(isolate, 42))
3036 .FromJust());
3037 CHECK(obj->Get(env.local(), v8_str("accessor_sym3"))
3038 .ToLocalChecked()
3039 ->Equals(env.local(), v8::Integer::New(isolate, 42))
3040 .FromJust());
3041 CHECK_EQ(2u,
3042 obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003043
3044 // Symbol properties are inherited.
3045 v8::Local<v8::Object> child = v8::Object::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003046 CHECK(child->SetPrototype(env.local(), obj).FromJust());
3047 CHECK(child->Has(env.local(), sym1).FromJust());
3048 CHECK_EQ(2002, child->Get(env.local(), sym1)
3049 .ToLocalChecked()
3050 ->Int32Value(env.local())
3051 .FromJust());
3052 CHECK(obj->Get(env.local(), sym3)
3053 .ToLocalChecked()
3054 ->Equals(env.local(), v8::Integer::New(isolate, 42))
3055 .FromJust());
3056 CHECK(obj->Get(env.local(), v8_str("accessor_sym3"))
3057 .ToLocalChecked()
3058 ->Equals(env.local(), v8::Integer::New(isolate, 42))
3059 .FromJust());
3060 CHECK_EQ(0u,
3061 child->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003062}
3063
3064
3065THREADED_TEST(SymbolTemplateProperties) {
3066 LocalContext env;
3067 v8::Isolate* isolate = env->GetIsolate();
3068 v8::HandleScope scope(isolate);
3069 v8::Local<v8::FunctionTemplate> foo = v8::FunctionTemplate::New(isolate);
3070 v8::Local<v8::Name> name = v8::Symbol::New(isolate);
3071 CHECK(!name.IsEmpty());
3072 foo->PrototypeTemplate()->Set(name, v8::FunctionTemplate::New(isolate));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003073 v8::Local<v8::Object> new_instance =
3074 foo->InstanceTemplate()->NewInstance(env.local()).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003075 CHECK(!new_instance.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003076 CHECK(new_instance->Has(env.local(), name).FromJust());
3077}
3078
3079
3080THREADED_TEST(PrivatePropertiesOnProxies) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003081 LocalContext env;
3082 v8::Isolate* isolate = env->GetIsolate();
3083 v8::HandleScope scope(isolate);
3084
3085 v8::Local<v8::Object> target = CompileRun("({})").As<v8::Object>();
3086 v8::Local<v8::Object> handler = CompileRun("({})").As<v8::Object>();
3087
3088 v8::Local<v8::Proxy> proxy =
3089 v8::Proxy::New(env.local(), target, handler).ToLocalChecked();
3090
3091 v8::Local<v8::Private> priv1 = v8::Private::New(isolate);
3092 v8::Local<v8::Private> priv2 =
3093 v8::Private::New(isolate, v8_str("my-private"));
3094
3095 CcTest::heap()->CollectAllGarbage();
3096
3097 CHECK(priv2->Name()
3098 ->Equals(env.local(),
3099 v8::String::NewFromUtf8(isolate, "my-private",
3100 v8::NewStringType::kNormal)
3101 .ToLocalChecked())
3102 .FromJust());
3103
3104 // Make sure delete of a non-existent private symbol property works.
3105 proxy->DeletePrivate(env.local(), priv1).FromJust();
3106 CHECK(!proxy->HasPrivate(env.local(), priv1).FromJust());
3107
3108 CHECK(proxy->SetPrivate(env.local(), priv1, v8::Integer::New(isolate, 1503))
3109 .FromJust());
3110 CHECK(proxy->HasPrivate(env.local(), priv1).FromJust());
3111 CHECK_EQ(1503, proxy->GetPrivate(env.local(), priv1)
3112 .ToLocalChecked()
3113 ->Int32Value(env.local())
3114 .FromJust());
3115 CHECK(proxy->SetPrivate(env.local(), priv1, v8::Integer::New(isolate, 2002))
3116 .FromJust());
3117 CHECK(proxy->HasPrivate(env.local(), priv1).FromJust());
3118 CHECK_EQ(2002, proxy->GetPrivate(env.local(), priv1)
3119 .ToLocalChecked()
3120 ->Int32Value(env.local())
3121 .FromJust());
3122
3123 CHECK_EQ(0u,
3124 proxy->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
3125 unsigned num_props =
3126 proxy->GetPropertyNames(env.local()).ToLocalChecked()->Length();
3127 CHECK(proxy->Set(env.local(), v8::String::NewFromUtf8(
3128 isolate, "bla", v8::NewStringType::kNormal)
3129 .ToLocalChecked(),
3130 v8::Integer::New(isolate, 20))
3131 .FromJust());
3132 CHECK_EQ(1u,
3133 proxy->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
3134 CHECK_EQ(num_props + 1,
3135 proxy->GetPropertyNames(env.local()).ToLocalChecked()->Length());
3136
3137 CcTest::heap()->CollectAllGarbage();
3138
3139 // Add another property and delete it afterwards to force the object in
3140 // slow case.
3141 CHECK(proxy->SetPrivate(env.local(), priv2, v8::Integer::New(isolate, 2008))
3142 .FromJust());
3143 CHECK_EQ(2002, proxy->GetPrivate(env.local(), priv1)
3144 .ToLocalChecked()
3145 ->Int32Value(env.local())
3146 .FromJust());
3147 CHECK_EQ(2008, proxy->GetPrivate(env.local(), priv2)
3148 .ToLocalChecked()
3149 ->Int32Value(env.local())
3150 .FromJust());
3151 CHECK_EQ(2002, proxy->GetPrivate(env.local(), priv1)
3152 .ToLocalChecked()
3153 ->Int32Value(env.local())
3154 .FromJust());
3155 CHECK_EQ(1u,
3156 proxy->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
3157
3158 CHECK(proxy->HasPrivate(env.local(), priv1).FromJust());
3159 CHECK(proxy->HasPrivate(env.local(), priv2).FromJust());
3160 CHECK(proxy->DeletePrivate(env.local(), priv2).FromJust());
3161 CHECK(proxy->HasPrivate(env.local(), priv1).FromJust());
3162 CHECK(!proxy->HasPrivate(env.local(), priv2).FromJust());
3163 CHECK_EQ(2002, proxy->GetPrivate(env.local(), priv1)
3164 .ToLocalChecked()
3165 ->Int32Value(env.local())
3166 .FromJust());
3167 CHECK_EQ(1u,
3168 proxy->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
3169
3170 // Private properties are not inherited (for the time being).
3171 v8::Local<v8::Object> child = v8::Object::New(isolate);
3172 CHECK(child->SetPrototype(env.local(), proxy).FromJust());
3173 CHECK(!child->HasPrivate(env.local(), priv1).FromJust());
3174 CHECK_EQ(0u,
3175 child->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003176}
3177
3178
3179THREADED_TEST(PrivateProperties) {
3180 LocalContext env;
3181 v8::Isolate* isolate = env->GetIsolate();
3182 v8::HandleScope scope(isolate);
3183
3184 v8::Local<v8::Object> obj = v8::Object::New(isolate);
3185 v8::Local<v8::Private> priv1 = v8::Private::New(isolate);
3186 v8::Local<v8::Private> priv2 =
3187 v8::Private::New(isolate, v8_str("my-private"));
3188
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003189 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003190
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003191 CHECK(priv2->Name()
3192 ->Equals(env.local(),
3193 v8::String::NewFromUtf8(isolate, "my-private",
3194 v8::NewStringType::kNormal)
3195 .ToLocalChecked())
3196 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003197
3198 // Make sure delete of a non-existent private symbol property works.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003199 obj->DeletePrivate(env.local(), priv1).FromJust();
3200 CHECK(!obj->HasPrivate(env.local(), priv1).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003201
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003202 CHECK(obj->SetPrivate(env.local(), priv1, v8::Integer::New(isolate, 1503))
3203 .FromJust());
3204 CHECK(obj->HasPrivate(env.local(), priv1).FromJust());
3205 CHECK_EQ(1503, obj->GetPrivate(env.local(), priv1)
3206 .ToLocalChecked()
3207 ->Int32Value(env.local())
3208 .FromJust());
3209 CHECK(obj->SetPrivate(env.local(), priv1, v8::Integer::New(isolate, 2002))
3210 .FromJust());
3211 CHECK(obj->HasPrivate(env.local(), priv1).FromJust());
3212 CHECK_EQ(2002, obj->GetPrivate(env.local(), priv1)
3213 .ToLocalChecked()
3214 ->Int32Value(env.local())
3215 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003216
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003217 CHECK_EQ(0u,
3218 obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
3219 unsigned num_props =
3220 obj->GetPropertyNames(env.local()).ToLocalChecked()->Length();
3221 CHECK(obj->Set(env.local(), v8::String::NewFromUtf8(
3222 isolate, "bla", v8::NewStringType::kNormal)
3223 .ToLocalChecked(),
3224 v8::Integer::New(isolate, 20))
3225 .FromJust());
3226 CHECK_EQ(1u,
3227 obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
3228 CHECK_EQ(num_props + 1,
3229 obj->GetPropertyNames(env.local()).ToLocalChecked()->Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003230
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003231 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003232
3233 // Add another property and delete it afterwards to force the object in
3234 // slow case.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003235 CHECK(obj->SetPrivate(env.local(), priv2, v8::Integer::New(isolate, 2008))
3236 .FromJust());
3237 CHECK_EQ(2002, obj->GetPrivate(env.local(), priv1)
3238 .ToLocalChecked()
3239 ->Int32Value(env.local())
3240 .FromJust());
3241 CHECK_EQ(2008, obj->GetPrivate(env.local(), priv2)
3242 .ToLocalChecked()
3243 ->Int32Value(env.local())
3244 .FromJust());
3245 CHECK_EQ(2002, obj->GetPrivate(env.local(), priv1)
3246 .ToLocalChecked()
3247 ->Int32Value(env.local())
3248 .FromJust());
3249 CHECK_EQ(1u,
3250 obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003251
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003252 CHECK(obj->HasPrivate(env.local(), priv1).FromJust());
3253 CHECK(obj->HasPrivate(env.local(), priv2).FromJust());
3254 CHECK(obj->DeletePrivate(env.local(), priv2).FromJust());
3255 CHECK(obj->HasPrivate(env.local(), priv1).FromJust());
3256 CHECK(!obj->HasPrivate(env.local(), priv2).FromJust());
3257 CHECK_EQ(2002, obj->GetPrivate(env.local(), priv1)
3258 .ToLocalChecked()
3259 ->Int32Value(env.local())
3260 .FromJust());
3261 CHECK_EQ(1u,
3262 obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003263
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003264 // Private properties are not inherited (for the time being).
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003265 v8::Local<v8::Object> child = v8::Object::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003266 CHECK(child->SetPrototype(env.local(), obj).FromJust());
3267 CHECK(!child->HasPrivate(env.local(), priv1).FromJust());
3268 CHECK_EQ(0u,
3269 child->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003270}
3271
3272
3273THREADED_TEST(GlobalSymbols) {
3274 LocalContext env;
3275 v8::Isolate* isolate = env->GetIsolate();
3276 v8::HandleScope scope(isolate);
3277
3278 v8::Local<String> name = v8_str("my-symbol");
3279 v8::Local<v8::Symbol> glob = v8::Symbol::For(isolate, name);
3280 v8::Local<v8::Symbol> glob2 = v8::Symbol::For(isolate, name);
3281 CHECK(glob2->SameValue(glob));
3282
3283 v8::Local<v8::Symbol> glob_api = v8::Symbol::ForApi(isolate, name);
3284 v8::Local<v8::Symbol> glob_api2 = v8::Symbol::ForApi(isolate, name);
3285 CHECK(glob_api2->SameValue(glob_api));
3286 CHECK(!glob_api->SameValue(glob));
3287
3288 v8::Local<v8::Symbol> sym = v8::Symbol::New(isolate, name);
3289 CHECK(!sym->SameValue(glob));
3290
3291 CompileRun("var sym2 = Symbol.for('my-symbol')");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003292 v8::Local<Value> sym2 =
3293 env->Global()->Get(env.local(), v8_str("sym2")).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003294 CHECK(sym2->SameValue(glob));
3295 CHECK(!sym2->SameValue(glob_api));
3296}
3297
3298
3299static void CheckWellKnownSymbol(v8::Local<v8::Symbol>(*getter)(v8::Isolate*),
3300 const char* name) {
3301 LocalContext env;
3302 v8::Isolate* isolate = env->GetIsolate();
3303 v8::HandleScope scope(isolate);
3304
3305 v8::Local<v8::Symbol> symbol = getter(isolate);
3306 std::string script = std::string("var sym = ") + name;
3307 CompileRun(script.c_str());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003308 v8::Local<Value> value =
3309 env->Global()->Get(env.local(), v8_str("sym")).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003310
3311 CHECK(!value.IsEmpty());
3312 CHECK(!symbol.IsEmpty());
3313 CHECK(value->SameValue(symbol));
3314}
3315
3316
3317THREADED_TEST(WellKnownSymbols) {
3318 CheckWellKnownSymbol(v8::Symbol::GetIterator, "Symbol.iterator");
3319 CheckWellKnownSymbol(v8::Symbol::GetUnscopables, "Symbol.unscopables");
3320}
3321
3322
3323THREADED_TEST(GlobalPrivates) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003324 i::FLAG_allow_natives_syntax = true;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003325 LocalContext env;
3326 v8::Isolate* isolate = env->GetIsolate();
3327 v8::HandleScope scope(isolate);
3328
3329 v8::Local<String> name = v8_str("my-private");
3330 v8::Local<v8::Private> glob = v8::Private::ForApi(isolate, name);
3331 v8::Local<v8::Object> obj = v8::Object::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003332 CHECK(obj->SetPrivate(env.local(), glob, v8::Integer::New(isolate, 3))
3333 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003334
3335 v8::Local<v8::Private> glob2 = v8::Private::ForApi(isolate, name);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003336 CHECK(obj->HasPrivate(env.local(), glob2).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003337
3338 v8::Local<v8::Private> priv = v8::Private::New(isolate, name);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003339 CHECK(!obj->HasPrivate(env.local(), priv).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003340
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003341 CompileRun("var intern = %CreatePrivateSymbol('my-private')");
3342 v8::Local<Value> intern =
3343 env->Global()->Get(env.local(), v8_str("intern")).ToLocalChecked();
3344 CHECK(!obj->Has(env.local(), intern).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003345}
3346
3347
3348class ScopedArrayBufferContents {
3349 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003350 explicit ScopedArrayBufferContents(const v8::ArrayBuffer::Contents& contents)
3351 : contents_(contents) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003352 ~ScopedArrayBufferContents() { free(contents_.Data()); }
3353 void* Data() const { return contents_.Data(); }
3354 size_t ByteLength() const { return contents_.ByteLength(); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003355
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003356 private:
3357 const v8::ArrayBuffer::Contents contents_;
3358};
3359
3360template <typename T>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003361static void CheckInternalFieldsAreZero(v8::Local<T> value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003362 CHECK_EQ(T::kInternalFieldCount, value->InternalFieldCount());
3363 for (int i = 0; i < value->InternalFieldCount(); i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003364 CHECK_EQ(0, value->GetInternalField(i)
3365 ->Int32Value(CcTest::isolate()->GetCurrentContext())
3366 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003367 }
3368}
3369
3370
3371THREADED_TEST(ArrayBuffer_ApiInternalToExternal) {
3372 LocalContext env;
3373 v8::Isolate* isolate = env->GetIsolate();
3374 v8::HandleScope handle_scope(isolate);
3375
3376 Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, 1024);
3377 CheckInternalFieldsAreZero(ab);
3378 CHECK_EQ(1024, static_cast<int>(ab->ByteLength()));
3379 CHECK(!ab->IsExternal());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003380 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003381
3382 ScopedArrayBufferContents ab_contents(ab->Externalize());
3383 CHECK(ab->IsExternal());
3384
3385 CHECK_EQ(1024, static_cast<int>(ab_contents.ByteLength()));
3386 uint8_t* data = static_cast<uint8_t*>(ab_contents.Data());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003387 CHECK(data != NULL);
3388 CHECK(env->Global()->Set(env.local(), v8_str("ab"), ab).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003389
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003390 v8::Local<v8::Value> result = CompileRun("ab.byteLength");
3391 CHECK_EQ(1024, result->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003392
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003393 result = CompileRun(
3394 "var u8 = new Uint8Array(ab);"
3395 "u8[0] = 0xFF;"
3396 "u8[1] = 0xAA;"
3397 "u8.length");
3398 CHECK_EQ(1024, result->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003399 CHECK_EQ(0xFF, data[0]);
3400 CHECK_EQ(0xAA, data[1]);
3401 data[0] = 0xCC;
3402 data[1] = 0x11;
3403 result = CompileRun("u8[0] + u8[1]");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003404 CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003405}
3406
3407
3408THREADED_TEST(ArrayBuffer_JSInternalToExternal) {
3409 LocalContext env;
3410 v8::Isolate* isolate = env->GetIsolate();
3411 v8::HandleScope handle_scope(isolate);
3412
3413
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003414 v8::Local<v8::Value> result = CompileRun(
3415 "var ab1 = new ArrayBuffer(2);"
3416 "var u8_a = new Uint8Array(ab1);"
3417 "u8_a[0] = 0xAA;"
3418 "u8_a[1] = 0xFF; u8_a.buffer");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003419 Local<v8::ArrayBuffer> ab1 = Local<v8::ArrayBuffer>::Cast(result);
3420 CheckInternalFieldsAreZero(ab1);
3421 CHECK_EQ(2, static_cast<int>(ab1->ByteLength()));
3422 CHECK(!ab1->IsExternal());
3423 ScopedArrayBufferContents ab1_contents(ab1->Externalize());
3424 CHECK(ab1->IsExternal());
3425
3426 result = CompileRun("ab1.byteLength");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003427 CHECK_EQ(2, result->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003428 result = CompileRun("u8_a[0]");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003429 CHECK_EQ(0xAA, result->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003430 result = CompileRun("u8_a[1]");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003431 CHECK_EQ(0xFF, result->Int32Value(env.local()).FromJust());
3432 result = CompileRun(
3433 "var u8_b = new Uint8Array(ab1);"
3434 "u8_b[0] = 0xBB;"
3435 "u8_a[0]");
3436 CHECK_EQ(0xBB, result->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003437 result = CompileRun("u8_b[1]");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003438 CHECK_EQ(0xFF, result->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003439
3440 CHECK_EQ(2, static_cast<int>(ab1_contents.ByteLength()));
3441 uint8_t* ab1_data = static_cast<uint8_t*>(ab1_contents.Data());
3442 CHECK_EQ(0xBB, ab1_data[0]);
3443 CHECK_EQ(0xFF, ab1_data[1]);
3444 ab1_data[0] = 0xCC;
3445 ab1_data[1] = 0x11;
3446 result = CompileRun("u8_a[0] + u8_a[1]");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003447 CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003448}
3449
3450
3451THREADED_TEST(ArrayBuffer_External) {
3452 LocalContext env;
3453 v8::Isolate* isolate = env->GetIsolate();
3454 v8::HandleScope handle_scope(isolate);
3455
3456 i::ScopedVector<uint8_t> my_data(100);
3457 memset(my_data.start(), 0, 100);
3458 Local<v8::ArrayBuffer> ab3 =
3459 v8::ArrayBuffer::New(isolate, my_data.start(), 100);
3460 CheckInternalFieldsAreZero(ab3);
3461 CHECK_EQ(100, static_cast<int>(ab3->ByteLength()));
3462 CHECK(ab3->IsExternal());
3463
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003464 CHECK(env->Global()->Set(env.local(), v8_str("ab3"), ab3).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003465
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003466 v8::Local<v8::Value> result = CompileRun("ab3.byteLength");
3467 CHECK_EQ(100, result->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003468
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003469 result = CompileRun(
3470 "var u8_b = new Uint8Array(ab3);"
3471 "u8_b[0] = 0xBB;"
3472 "u8_b[1] = 0xCC;"
3473 "u8_b.length");
3474 CHECK_EQ(100, result->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003475 CHECK_EQ(0xBB, my_data[0]);
3476 CHECK_EQ(0xCC, my_data[1]);
3477 my_data[0] = 0xCC;
3478 my_data[1] = 0x11;
3479 result = CompileRun("u8_b[0] + u8_b[1]");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003480 CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003481}
3482
3483
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003484THREADED_TEST(ArrayBuffer_DisableNeuter) {
3485 LocalContext env;
3486 v8::Isolate* isolate = env->GetIsolate();
3487 v8::HandleScope handle_scope(isolate);
3488
3489 i::ScopedVector<uint8_t> my_data(100);
3490 memset(my_data.start(), 0, 100);
3491 Local<v8::ArrayBuffer> ab =
3492 v8::ArrayBuffer::New(isolate, my_data.start(), 100);
3493 CHECK(ab->IsNeuterable());
3494
3495 i::Handle<i::JSArrayBuffer> buf = v8::Utils::OpenHandle(*ab);
3496 buf->set_is_neuterable(false);
3497
3498 CHECK(!ab->IsNeuterable());
3499}
3500
3501
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003502static void CheckDataViewIsNeutered(v8::Local<v8::DataView> dv) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003503 CHECK_EQ(0, static_cast<int>(dv->ByteLength()));
3504 CHECK_EQ(0, static_cast<int>(dv->ByteOffset()));
3505}
3506
3507
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003508static void CheckIsNeutered(v8::Local<v8::TypedArray> ta) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003509 CHECK_EQ(0, static_cast<int>(ta->ByteLength()));
3510 CHECK_EQ(0, static_cast<int>(ta->Length()));
3511 CHECK_EQ(0, static_cast<int>(ta->ByteOffset()));
3512}
3513
3514
3515static void CheckIsTypedArrayVarNeutered(const char* name) {
3516 i::ScopedVector<char> source(1024);
3517 i::SNPrintF(source,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003518 "%s.byteLength == 0 && %s.byteOffset == 0 && %s.length == 0",
3519 name, name, name);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003520 CHECK(CompileRun(source.start())->IsTrue());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003521 v8::Local<v8::TypedArray> ta =
3522 v8::Local<v8::TypedArray>::Cast(CompileRun(name));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003523 CheckIsNeutered(ta);
3524}
3525
3526
3527template <typename TypedArray, int kElementSize>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003528static Local<TypedArray> CreateAndCheck(Local<v8::ArrayBuffer> ab,
3529 int byteOffset, int length) {
3530 v8::Local<TypedArray> ta = TypedArray::New(ab, byteOffset, length);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003531 CheckInternalFieldsAreZero<v8::ArrayBufferView>(ta);
3532 CHECK_EQ(byteOffset, static_cast<int>(ta->ByteOffset()));
3533 CHECK_EQ(length, static_cast<int>(ta->Length()));
3534 CHECK_EQ(length * kElementSize, static_cast<int>(ta->ByteLength()));
3535 return ta;
3536}
3537
3538
3539THREADED_TEST(ArrayBuffer_NeuteringApi) {
3540 LocalContext env;
3541 v8::Isolate* isolate = env->GetIsolate();
3542 v8::HandleScope handle_scope(isolate);
3543
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003544 v8::Local<v8::ArrayBuffer> buffer = v8::ArrayBuffer::New(isolate, 1024);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003545
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003546 v8::Local<v8::Uint8Array> u8a =
3547 CreateAndCheck<v8::Uint8Array, 1>(buffer, 1, 1023);
3548 v8::Local<v8::Uint8ClampedArray> u8c =
3549 CreateAndCheck<v8::Uint8ClampedArray, 1>(buffer, 1, 1023);
3550 v8::Local<v8::Int8Array> i8a =
3551 CreateAndCheck<v8::Int8Array, 1>(buffer, 1, 1023);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003552
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003553 v8::Local<v8::Uint16Array> u16a =
3554 CreateAndCheck<v8::Uint16Array, 2>(buffer, 2, 511);
3555 v8::Local<v8::Int16Array> i16a =
3556 CreateAndCheck<v8::Int16Array, 2>(buffer, 2, 511);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003557
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003558 v8::Local<v8::Uint32Array> u32a =
3559 CreateAndCheck<v8::Uint32Array, 4>(buffer, 4, 255);
3560 v8::Local<v8::Int32Array> i32a =
3561 CreateAndCheck<v8::Int32Array, 4>(buffer, 4, 255);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003562
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003563 v8::Local<v8::Float32Array> f32a =
3564 CreateAndCheck<v8::Float32Array, 4>(buffer, 4, 255);
3565 v8::Local<v8::Float64Array> f64a =
3566 CreateAndCheck<v8::Float64Array, 8>(buffer, 8, 127);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003567
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003568 v8::Local<v8::DataView> dv = v8::DataView::New(buffer, 1, 1023);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003569 CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
3570 CHECK_EQ(1, static_cast<int>(dv->ByteOffset()));
3571 CHECK_EQ(1023, static_cast<int>(dv->ByteLength()));
3572
3573 ScopedArrayBufferContents contents(buffer->Externalize());
3574 buffer->Neuter();
3575 CHECK_EQ(0, static_cast<int>(buffer->ByteLength()));
3576 CheckIsNeutered(u8a);
3577 CheckIsNeutered(u8c);
3578 CheckIsNeutered(i8a);
3579 CheckIsNeutered(u16a);
3580 CheckIsNeutered(i16a);
3581 CheckIsNeutered(u32a);
3582 CheckIsNeutered(i32a);
3583 CheckIsNeutered(f32a);
3584 CheckIsNeutered(f64a);
3585 CheckDataViewIsNeutered(dv);
3586}
3587
3588
3589THREADED_TEST(ArrayBuffer_NeuteringScript) {
3590 LocalContext env;
3591 v8::Isolate* isolate = env->GetIsolate();
3592 v8::HandleScope handle_scope(isolate);
3593
3594 CompileRun(
3595 "var ab = new ArrayBuffer(1024);"
3596 "var u8a = new Uint8Array(ab, 1, 1023);"
3597 "var u8c = new Uint8ClampedArray(ab, 1, 1023);"
3598 "var i8a = new Int8Array(ab, 1, 1023);"
3599 "var u16a = new Uint16Array(ab, 2, 511);"
3600 "var i16a = new Int16Array(ab, 2, 511);"
3601 "var u32a = new Uint32Array(ab, 4, 255);"
3602 "var i32a = new Int32Array(ab, 4, 255);"
3603 "var f32a = new Float32Array(ab, 4, 255);"
3604 "var f64a = new Float64Array(ab, 8, 127);"
3605 "var dv = new DataView(ab, 1, 1023);");
3606
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003607 v8::Local<v8::ArrayBuffer> ab =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003608 Local<v8::ArrayBuffer>::Cast(CompileRun("ab"));
3609
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003610 v8::Local<v8::DataView> dv = v8::Local<v8::DataView>::Cast(CompileRun("dv"));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003611
3612 ScopedArrayBufferContents contents(ab->Externalize());
3613 ab->Neuter();
3614 CHECK_EQ(0, static_cast<int>(ab->ByteLength()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003615 CHECK_EQ(0, v8_run_int32value(v8_compile("ab.byteLength")));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003616
3617 CheckIsTypedArrayVarNeutered("u8a");
3618 CheckIsTypedArrayVarNeutered("u8c");
3619 CheckIsTypedArrayVarNeutered("i8a");
3620 CheckIsTypedArrayVarNeutered("u16a");
3621 CheckIsTypedArrayVarNeutered("i16a");
3622 CheckIsTypedArrayVarNeutered("u32a");
3623 CheckIsTypedArrayVarNeutered("i32a");
3624 CheckIsTypedArrayVarNeutered("f32a");
3625 CheckIsTypedArrayVarNeutered("f64a");
3626
3627 CHECK(CompileRun("dv.byteLength == 0 && dv.byteOffset == 0")->IsTrue());
3628 CheckDataViewIsNeutered(dv);
3629}
3630
3631
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003632class ScopedSharedArrayBufferContents {
3633 public:
3634 explicit ScopedSharedArrayBufferContents(
3635 const v8::SharedArrayBuffer::Contents& contents)
3636 : contents_(contents) {}
3637 ~ScopedSharedArrayBufferContents() { free(contents_.Data()); }
3638 void* Data() const { return contents_.Data(); }
3639 size_t ByteLength() const { return contents_.ByteLength(); }
3640
3641 private:
3642 const v8::SharedArrayBuffer::Contents contents_;
3643};
3644
3645
3646THREADED_TEST(SharedArrayBuffer_ApiInternalToExternal) {
3647 i::FLAG_harmony_sharedarraybuffer = true;
3648 LocalContext env;
3649 v8::Isolate* isolate = env->GetIsolate();
3650 v8::HandleScope handle_scope(isolate);
3651
3652 Local<v8::SharedArrayBuffer> ab = v8::SharedArrayBuffer::New(isolate, 1024);
3653 CheckInternalFieldsAreZero(ab);
3654 CHECK_EQ(1024, static_cast<int>(ab->ByteLength()));
3655 CHECK(!ab->IsExternal());
3656 CcTest::heap()->CollectAllGarbage();
3657
3658 ScopedSharedArrayBufferContents ab_contents(ab->Externalize());
3659 CHECK(ab->IsExternal());
3660
3661 CHECK_EQ(1024, static_cast<int>(ab_contents.ByteLength()));
3662 uint8_t* data = static_cast<uint8_t*>(ab_contents.Data());
3663 CHECK(data != NULL);
3664 CHECK(env->Global()->Set(env.local(), v8_str("ab"), ab).FromJust());
3665
3666 v8::Local<v8::Value> result = CompileRun("ab.byteLength");
3667 CHECK_EQ(1024, result->Int32Value(env.local()).FromJust());
3668
3669 result = CompileRun(
3670 "var u8 = new Uint8Array(ab);"
3671 "u8[0] = 0xFF;"
3672 "u8[1] = 0xAA;"
3673 "u8.length");
3674 CHECK_EQ(1024, result->Int32Value(env.local()).FromJust());
3675 CHECK_EQ(0xFF, data[0]);
3676 CHECK_EQ(0xAA, data[1]);
3677 data[0] = 0xCC;
3678 data[1] = 0x11;
3679 result = CompileRun("u8[0] + u8[1]");
3680 CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
3681}
3682
3683
3684THREADED_TEST(SharedArrayBuffer_JSInternalToExternal) {
3685 i::FLAG_harmony_sharedarraybuffer = true;
3686 LocalContext env;
3687 v8::Isolate* isolate = env->GetIsolate();
3688 v8::HandleScope handle_scope(isolate);
3689
3690
3691 v8::Local<v8::Value> result = CompileRun(
3692 "var ab1 = new SharedArrayBuffer(2);"
3693 "var u8_a = new Uint8Array(ab1);"
3694 "u8_a[0] = 0xAA;"
3695 "u8_a[1] = 0xFF; u8_a.buffer");
3696 Local<v8::SharedArrayBuffer> ab1 = Local<v8::SharedArrayBuffer>::Cast(result);
3697 CheckInternalFieldsAreZero(ab1);
3698 CHECK_EQ(2, static_cast<int>(ab1->ByteLength()));
3699 CHECK(!ab1->IsExternal());
3700 ScopedSharedArrayBufferContents ab1_contents(ab1->Externalize());
3701 CHECK(ab1->IsExternal());
3702
3703 result = CompileRun("ab1.byteLength");
3704 CHECK_EQ(2, result->Int32Value(env.local()).FromJust());
3705 result = CompileRun("u8_a[0]");
3706 CHECK_EQ(0xAA, result->Int32Value(env.local()).FromJust());
3707 result = CompileRun("u8_a[1]");
3708 CHECK_EQ(0xFF, result->Int32Value(env.local()).FromJust());
3709 result = CompileRun(
3710 "var u8_b = new Uint8Array(ab1);"
3711 "u8_b[0] = 0xBB;"
3712 "u8_a[0]");
3713 CHECK_EQ(0xBB, result->Int32Value(env.local()).FromJust());
3714 result = CompileRun("u8_b[1]");
3715 CHECK_EQ(0xFF, result->Int32Value(env.local()).FromJust());
3716
3717 CHECK_EQ(2, static_cast<int>(ab1_contents.ByteLength()));
3718 uint8_t* ab1_data = static_cast<uint8_t*>(ab1_contents.Data());
3719 CHECK_EQ(0xBB, ab1_data[0]);
3720 CHECK_EQ(0xFF, ab1_data[1]);
3721 ab1_data[0] = 0xCC;
3722 ab1_data[1] = 0x11;
3723 result = CompileRun("u8_a[0] + u8_a[1]");
3724 CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
3725}
3726
3727
3728THREADED_TEST(SharedArrayBuffer_External) {
3729 i::FLAG_harmony_sharedarraybuffer = true;
3730 LocalContext env;
3731 v8::Isolate* isolate = env->GetIsolate();
3732 v8::HandleScope handle_scope(isolate);
3733
3734 i::ScopedVector<uint8_t> my_data(100);
3735 memset(my_data.start(), 0, 100);
3736 Local<v8::SharedArrayBuffer> ab3 =
3737 v8::SharedArrayBuffer::New(isolate, my_data.start(), 100);
3738 CheckInternalFieldsAreZero(ab3);
3739 CHECK_EQ(100, static_cast<int>(ab3->ByteLength()));
3740 CHECK(ab3->IsExternal());
3741
3742 CHECK(env->Global()->Set(env.local(), v8_str("ab3"), ab3).FromJust());
3743
3744 v8::Local<v8::Value> result = CompileRun("ab3.byteLength");
3745 CHECK_EQ(100, result->Int32Value(env.local()).FromJust());
3746
3747 result = CompileRun(
3748 "var u8_b = new Uint8Array(ab3);"
3749 "u8_b[0] = 0xBB;"
3750 "u8_b[1] = 0xCC;"
3751 "u8_b.length");
3752 CHECK_EQ(100, result->Int32Value(env.local()).FromJust());
3753 CHECK_EQ(0xBB, my_data[0]);
3754 CHECK_EQ(0xCC, my_data[1]);
3755 my_data[0] = 0xCC;
3756 my_data[1] = 0x11;
3757 result = CompileRun("u8_b[0] + u8_b[1]");
3758 CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
3759}
3760
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003761
3762THREADED_TEST(HiddenProperties) {
3763 LocalContext env;
3764 v8::Isolate* isolate = env->GetIsolate();
3765 v8::HandleScope scope(isolate);
3766
3767 v8::Local<v8::Object> obj = v8::Object::New(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003768 v8::Local<v8::Private> key =
3769 v8::Private::ForApi(isolate, v8_str("api-test::hidden-key"));
Steve Blocka7e24c12009-10-30 11:49:00 +00003770 v8::Local<v8::String> empty = v8_str("");
3771 v8::Local<v8::String> prop_name = v8_str("prop_name");
3772
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003773 CcTest::heap()->CollectAllGarbage();
Steve Blocka7e24c12009-10-30 11:49:00 +00003774
3775 // Make sure delete of a non-existent hidden value works
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003776 obj->DeletePrivate(env.local(), key).FromJust();
Steve Blocka7e24c12009-10-30 11:49:00 +00003777
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003778 CHECK(obj->SetPrivate(env.local(), key, v8::Integer::New(isolate, 1503))
3779 .FromJust());
3780 CHECK_EQ(1503, obj->GetPrivate(env.local(), key)
3781 .ToLocalChecked()
3782 ->Int32Value(env.local())
3783 .FromJust());
3784 CHECK(obj->SetPrivate(env.local(), key, v8::Integer::New(isolate, 2002))
3785 .FromJust());
3786 CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
3787 .ToLocalChecked()
3788 ->Int32Value(env.local())
3789 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00003790
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003791 CcTest::heap()->CollectAllGarbage();
Steve Blocka7e24c12009-10-30 11:49:00 +00003792
3793 // Make sure we do not find the hidden property.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003794 CHECK(!obj->Has(env.local(), empty).FromJust());
3795 CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
3796 .ToLocalChecked()
3797 ->Int32Value(env.local())
3798 .FromJust());
3799 CHECK(obj->Get(env.local(), empty).ToLocalChecked()->IsUndefined());
3800 CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
3801 .ToLocalChecked()
3802 ->Int32Value(env.local())
3803 .FromJust());
3804 CHECK(
3805 obj->Set(env.local(), empty, v8::Integer::New(isolate, 2003)).FromJust());
3806 CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
3807 .ToLocalChecked()
3808 ->Int32Value(env.local())
3809 .FromJust());
3810 CHECK_EQ(2003, obj->Get(env.local(), empty)
3811 .ToLocalChecked()
3812 ->Int32Value(env.local())
3813 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00003814
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003815 CcTest::heap()->CollectAllGarbage();
Steve Blocka7e24c12009-10-30 11:49:00 +00003816
3817 // Add another property and delete it afterwards to force the object in
3818 // slow case.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003819 CHECK(obj->Set(env.local(), prop_name, v8::Integer::New(isolate, 2008))
3820 .FromJust());
3821 CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
3822 .ToLocalChecked()
3823 ->Int32Value(env.local())
3824 .FromJust());
3825 CHECK_EQ(2008, obj->Get(env.local(), prop_name)
3826 .ToLocalChecked()
3827 ->Int32Value(env.local())
3828 .FromJust());
3829 CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
3830 .ToLocalChecked()
3831 ->Int32Value(env.local())
3832 .FromJust());
3833 CHECK(obj->Delete(env.local(), prop_name).FromJust());
3834 CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
3835 .ToLocalChecked()
3836 ->Int32Value(env.local())
3837 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00003838
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003839 CcTest::heap()->CollectAllGarbage();
Steve Blocka7e24c12009-10-30 11:49:00 +00003840
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003841 CHECK(obj->SetPrivate(env.local(), key, v8::Integer::New(isolate, 2002))
3842 .FromJust());
3843 CHECK(obj->DeletePrivate(env.local(), key).FromJust());
3844 CHECK(!obj->HasPrivate(env.local(), key).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00003845}
3846
3847
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003848THREADED_TEST(Regress97784) {
3849 // Regression test for crbug.com/97784
3850 // Messing with the Object.prototype should not have effect on
3851 // hidden properties.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003852 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003853 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003854
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003855 v8::Local<v8::Object> obj = v8::Object::New(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003856 v8::Local<v8::Private> key =
3857 v8::Private::New(env->GetIsolate(), v8_str("hidden"));
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003858
3859 CompileRun(
3860 "set_called = false;"
3861 "Object.defineProperty("
3862 " Object.prototype,"
3863 " 'hidden',"
3864 " {get: function() { return 45; },"
3865 " set: function() { set_called = true; }})");
3866
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003867 CHECK(!obj->HasPrivate(env.local(), key).FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003868 // Make sure that the getter and setter from Object.prototype is not invoked.
3869 // If it did we would have full access to the hidden properties in
3870 // the accessor.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003871 CHECK(
3872 obj->SetPrivate(env.local(), key, v8::Integer::New(env->GetIsolate(), 42))
3873 .FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003874 ExpectFalse("set_called");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003875 CHECK_EQ(42, obj->GetPrivate(env.local(), key)
3876 .ToLocalChecked()
3877 ->Int32Value(env.local())
3878 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00003879}
3880
3881
3882THREADED_TEST(External) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003883 v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00003884 int x = 3;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003885 Local<v8::External> ext = v8::External::New(CcTest::isolate(), &x);
Steve Blocka7e24c12009-10-30 11:49:00 +00003886 LocalContext env;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003887 CHECK(env->Global()->Set(env.local(), v8_str("ext"), ext).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003888 Local<Value> reext_obj = CompileRun("this.ext");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003889 v8::Local<v8::External> reext = reext_obj.As<v8::External>();
Steve Blocka7e24c12009-10-30 11:49:00 +00003890 int* ptr = static_cast<int*>(reext->Value());
3891 CHECK_EQ(x, 3);
3892 *ptr = 10;
3893 CHECK_EQ(x, 10);
3894
3895 // Make sure unaligned pointers are wrapped properly.
3896 char* data = i::StrDup("0123456789");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003897 Local<v8::Value> zero = v8::External::New(CcTest::isolate(), &data[0]);
3898 Local<v8::Value> one = v8::External::New(CcTest::isolate(), &data[1]);
3899 Local<v8::Value> two = v8::External::New(CcTest::isolate(), &data[2]);
3900 Local<v8::Value> three = v8::External::New(CcTest::isolate(), &data[3]);
Steve Blocka7e24c12009-10-30 11:49:00 +00003901
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003902 char* char_ptr = reinterpret_cast<char*>(v8::External::Cast(*zero)->Value());
Steve Blocka7e24c12009-10-30 11:49:00 +00003903 CHECK_EQ('0', *char_ptr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003904 char_ptr = reinterpret_cast<char*>(v8::External::Cast(*one)->Value());
Steve Blocka7e24c12009-10-30 11:49:00 +00003905 CHECK_EQ('1', *char_ptr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003906 char_ptr = reinterpret_cast<char*>(v8::External::Cast(*two)->Value());
Steve Blocka7e24c12009-10-30 11:49:00 +00003907 CHECK_EQ('2', *char_ptr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003908 char_ptr = reinterpret_cast<char*>(v8::External::Cast(*three)->Value());
Steve Blocka7e24c12009-10-30 11:49:00 +00003909 CHECK_EQ('3', *char_ptr);
3910 i::DeleteArray(data);
3911}
3912
3913
3914THREADED_TEST(GlobalHandle) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003915 v8::Isolate* isolate = CcTest::isolate();
Steve Blocka7e24c12009-10-30 11:49:00 +00003916 v8::Persistent<String> global;
3917 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003918 v8::HandleScope scope(isolate);
3919 global.Reset(isolate, v8_str("str"));
Steve Blocka7e24c12009-10-30 11:49:00 +00003920 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003921 {
3922 v8::HandleScope scope(isolate);
3923 CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
3924 }
3925 global.Reset();
3926 {
3927 v8::HandleScope scope(isolate);
3928 global.Reset(isolate, v8_str("str"));
3929 }
3930 {
3931 v8::HandleScope scope(isolate);
3932 CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
3933 }
3934 global.Reset();
3935}
3936
3937
3938THREADED_TEST(ResettingGlobalHandle) {
3939 v8::Isolate* isolate = CcTest::isolate();
3940 v8::Persistent<String> global;
3941 {
3942 v8::HandleScope scope(isolate);
3943 global.Reset(isolate, v8_str("str"));
3944 }
3945 v8::internal::GlobalHandles* global_handles =
3946 reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
3947 int initial_handle_count = global_handles->global_handles_count();
3948 {
3949 v8::HandleScope scope(isolate);
3950 CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
3951 }
3952 {
3953 v8::HandleScope scope(isolate);
3954 global.Reset(isolate, v8_str("longer"));
3955 }
3956 CHECK_EQ(global_handles->global_handles_count(), initial_handle_count);
3957 {
3958 v8::HandleScope scope(isolate);
3959 CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 6);
3960 }
3961 global.Reset();
3962 CHECK_EQ(global_handles->global_handles_count(), initial_handle_count - 1);
3963}
3964
3965
3966THREADED_TEST(ResettingGlobalHandleToEmpty) {
3967 v8::Isolate* isolate = CcTest::isolate();
3968 v8::Persistent<String> global;
3969 {
3970 v8::HandleScope scope(isolate);
3971 global.Reset(isolate, v8_str("str"));
3972 }
3973 v8::internal::GlobalHandles* global_handles =
3974 reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
3975 int initial_handle_count = global_handles->global_handles_count();
3976 {
3977 v8::HandleScope scope(isolate);
3978 CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
3979 }
3980 {
3981 v8::HandleScope scope(isolate);
3982 Local<String> empty;
3983 global.Reset(isolate, empty);
3984 }
3985 CHECK(global.IsEmpty());
3986 CHECK_EQ(global_handles->global_handles_count(), initial_handle_count - 1);
3987}
3988
3989
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003990template <class T>
3991static v8::Global<T> PassUnique(v8::Global<T> unique) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003992 return unique.Pass();
3993}
3994
3995
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003996template <class T>
3997static v8::Global<T> ReturnUnique(v8::Isolate* isolate,
3998 const v8::Persistent<T>& global) {
3999 v8::Global<String> unique(isolate, global);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004000 return unique.Pass();
4001}
4002
4003
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004004THREADED_TEST(Global) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004005 v8::Isolate* isolate = CcTest::isolate();
4006 v8::Persistent<String> global;
4007 {
4008 v8::HandleScope scope(isolate);
4009 global.Reset(isolate, v8_str("str"));
4010 }
4011 v8::internal::GlobalHandles* global_handles =
4012 reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
4013 int initial_handle_count = global_handles->global_handles_count();
4014 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004015 v8::Global<String> unique(isolate, global);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004016 CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
4017 // Test assignment via Pass
4018 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004019 v8::Global<String> copy = unique.Pass();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004020 CHECK(unique.IsEmpty());
4021 CHECK(copy == global);
4022 CHECK_EQ(initial_handle_count + 1,
4023 global_handles->global_handles_count());
4024 unique = copy.Pass();
4025 }
4026 // Test ctor via Pass
4027 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004028 v8::Global<String> copy(unique.Pass());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004029 CHECK(unique.IsEmpty());
4030 CHECK(copy == global);
4031 CHECK_EQ(initial_handle_count + 1,
4032 global_handles->global_handles_count());
4033 unique = copy.Pass();
4034 }
4035 // Test pass through function call
4036 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004037 v8::Global<String> copy = PassUnique(unique.Pass());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004038 CHECK(unique.IsEmpty());
4039 CHECK(copy == global);
4040 CHECK_EQ(initial_handle_count + 1,
4041 global_handles->global_handles_count());
4042 unique = copy.Pass();
4043 }
4044 CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
4045 }
4046 // Test pass from function call
4047 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004048 v8::Global<String> unique = ReturnUnique(isolate, global);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004049 CHECK(unique == global);
4050 CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
4051 }
4052 CHECK_EQ(initial_handle_count, global_handles->global_handles_count());
4053 global.Reset();
4054}
4055
4056
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004057namespace {
4058
4059class TwoPassCallbackData;
4060void FirstPassCallback(const v8::WeakCallbackInfo<TwoPassCallbackData>& data);
4061void SecondPassCallback(const v8::WeakCallbackInfo<TwoPassCallbackData>& data);
4062
4063
4064class TwoPassCallbackData {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004065 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004066 TwoPassCallbackData(v8::Isolate* isolate, int* instance_counter)
4067 : first_pass_called_(false),
4068 second_pass_called_(false),
4069 trigger_gc_(false),
4070 instance_counter_(instance_counter) {
4071 HandleScope scope(isolate);
4072 i::ScopedVector<char> buffer(40);
4073 i::SNPrintF(buffer, "%p", static_cast<void*>(this));
4074 auto string =
4075 v8::String::NewFromUtf8(isolate, buffer.start(),
4076 v8::NewStringType::kNormal).ToLocalChecked();
4077 cell_.Reset(isolate, string);
4078 (*instance_counter_)++;
4079 }
4080
4081 ~TwoPassCallbackData() {
4082 CHECK(first_pass_called_);
4083 CHECK(second_pass_called_);
4084 CHECK(cell_.IsEmpty());
4085 (*instance_counter_)--;
4086 }
4087
4088 void FirstPass() {
4089 CHECK(!first_pass_called_);
4090 CHECK(!second_pass_called_);
4091 CHECK(!cell_.IsEmpty());
4092 cell_.Reset();
4093 first_pass_called_ = true;
4094 }
4095
4096 void SecondPass() {
4097 CHECK(first_pass_called_);
4098 CHECK(!second_pass_called_);
4099 CHECK(cell_.IsEmpty());
4100 second_pass_called_ = true;
4101 delete this;
4102 }
4103
4104 void SetWeak() {
4105 cell_.SetWeak(this, FirstPassCallback, v8::WeakCallbackType::kParameter);
4106 }
4107
4108 void MarkTriggerGc() { trigger_gc_ = true; }
4109 bool trigger_gc() { return trigger_gc_; }
4110
4111 int* instance_counter() { return instance_counter_; }
4112
4113 private:
4114 bool first_pass_called_;
4115 bool second_pass_called_;
4116 bool trigger_gc_;
4117 v8::Global<v8::String> cell_;
4118 int* instance_counter_;
4119};
4120
4121
4122void SecondPassCallback(const v8::WeakCallbackInfo<TwoPassCallbackData>& data) {
4123 ApiTestFuzzer::Fuzz();
4124 bool trigger_gc = data.GetParameter()->trigger_gc();
4125 int* instance_counter = data.GetParameter()->instance_counter();
4126 data.GetParameter()->SecondPass();
4127 if (!trigger_gc) return;
4128 auto data_2 = new TwoPassCallbackData(data.GetIsolate(), instance_counter);
4129 data_2->SetWeak();
4130 CcTest::heap()->CollectAllGarbage();
4131}
4132
4133
4134void FirstPassCallback(const v8::WeakCallbackInfo<TwoPassCallbackData>& data) {
4135 data.GetParameter()->FirstPass();
4136 data.SetSecondPassCallback(SecondPassCallback);
4137}
4138
4139} // namespace
4140
4141
4142TEST(TwoPassPhantomCallbacks) {
4143 auto isolate = CcTest::isolate();
4144 const size_t kLength = 20;
4145 int instance_counter = 0;
4146 for (size_t i = 0; i < kLength; ++i) {
4147 auto data = new TwoPassCallbackData(isolate, &instance_counter);
4148 data->SetWeak();
4149 }
4150 CHECK_EQ(static_cast<int>(kLength), instance_counter);
4151 CcTest::heap()->CollectAllGarbage();
4152 EmptyMessageQueues(isolate);
4153 CHECK_EQ(0, instance_counter);
4154}
4155
4156
4157TEST(TwoPassPhantomCallbacksNestedGc) {
4158 auto isolate = CcTest::isolate();
4159 const size_t kLength = 20;
4160 TwoPassCallbackData* array[kLength];
4161 int instance_counter = 0;
4162 for (size_t i = 0; i < kLength; ++i) {
4163 array[i] = new TwoPassCallbackData(isolate, &instance_counter);
4164 array[i]->SetWeak();
4165 }
4166 array[5]->MarkTriggerGc();
4167 array[10]->MarkTriggerGc();
4168 array[15]->MarkTriggerGc();
4169 CHECK_EQ(static_cast<int>(kLength), instance_counter);
4170 CcTest::heap()->CollectAllGarbage();
4171 EmptyMessageQueues(isolate);
4172 CHECK_EQ(0, instance_counter);
4173}
4174
4175
4176namespace {
4177
4178void* IntKeyToVoidPointer(int key) { return reinterpret_cast<void*>(key << 1); }
4179
4180
4181Local<v8::Object> NewObjectForIntKey(
4182 v8::Isolate* isolate, const v8::Global<v8::ObjectTemplate>& templ,
4183 int key) {
4184 auto local = Local<v8::ObjectTemplate>::New(isolate, templ);
4185 auto obj = local->NewInstance(isolate->GetCurrentContext()).ToLocalChecked();
4186 obj->SetAlignedPointerInInternalField(0, IntKeyToVoidPointer(key));
4187 return obj;
4188}
4189
4190
4191template <typename K, typename V>
4192class PhantomStdMapTraits : public v8::StdMapTraits<K, V> {
4193 public:
4194 typedef typename v8::GlobalValueMap<K, V, PhantomStdMapTraits<K, V>> MapType;
4195 static const v8::PersistentContainerCallbackType kCallbackType =
4196 v8::kWeakWithInternalFields;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004197 struct WeakCallbackDataType {
4198 MapType* map;
4199 K key;
4200 };
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004201 static WeakCallbackDataType* WeakCallbackParameter(MapType* map, const K& key,
4202 Local<V> value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004203 WeakCallbackDataType* data = new WeakCallbackDataType;
4204 data->map = map;
4205 data->key = key;
4206 return data;
4207 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004208 static MapType* MapFromWeakCallbackInfo(
4209 const v8::WeakCallbackInfo<WeakCallbackDataType>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004210 return data.GetParameter()->map;
4211 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004212 static K KeyFromWeakCallbackInfo(
4213 const v8::WeakCallbackInfo<WeakCallbackDataType>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004214 return data.GetParameter()->key;
4215 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004216 static void DisposeCallbackData(WeakCallbackDataType* data) { delete data; }
4217 static void Dispose(v8::Isolate* isolate, v8::Global<V> value, K key) {
4218 CHECK_EQ(IntKeyToVoidPointer(key),
4219 v8::Object::GetAlignedPointerFromInternalField(value, 0));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004220 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004221 static void OnWeakCallback(
4222 const v8::WeakCallbackInfo<WeakCallbackDataType>&) {}
4223 static void DisposeWeak(
4224 const v8::WeakCallbackInfo<WeakCallbackDataType>& info) {
4225 K key = KeyFromWeakCallbackInfo(info);
4226 CHECK_EQ(IntKeyToVoidPointer(key), info.GetInternalField(0));
4227 DisposeCallbackData(info.GetParameter());
4228 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004229};
4230
4231
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004232template <typename Map>
4233void TestGlobalValueMap() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004234 LocalContext env;
4235 v8::Isolate* isolate = env->GetIsolate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004236 v8::Global<ObjectTemplate> templ;
4237 {
4238 HandleScope scope(isolate);
4239 auto t = ObjectTemplate::New(isolate);
4240 t->SetInternalFieldCount(1);
4241 templ.Reset(isolate, t);
4242 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004243 Map map(isolate);
4244 v8::internal::GlobalHandles* global_handles =
4245 reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
4246 int initial_handle_count = global_handles->global_handles_count();
4247 CHECK_EQ(0, static_cast<int>(map.Size()));
4248 {
4249 HandleScope scope(isolate);
4250 Local<v8::Object> obj = map.Get(7);
4251 CHECK(obj.IsEmpty());
4252 Local<v8::Object> expected = v8::Object::New(isolate);
4253 map.Set(7, expected);
4254 CHECK_EQ(1, static_cast<int>(map.Size()));
4255 obj = map.Get(7);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004256 CHECK(expected->Equals(env.local(), obj).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004257 {
4258 typename Map::PersistentValueReference ref = map.GetReference(7);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004259 CHECK(expected->Equals(env.local(), ref.NewLocal(isolate)).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004260 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004261 v8::Global<v8::Object> removed = map.Remove(7);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004262 CHECK_EQ(0, static_cast<int>(map.Size()));
4263 CHECK(expected == removed);
4264 removed = map.Remove(7);
4265 CHECK(removed.IsEmpty());
4266 map.Set(8, expected);
4267 CHECK_EQ(1, static_cast<int>(map.Size()));
4268 map.Set(8, expected);
4269 CHECK_EQ(1, static_cast<int>(map.Size()));
4270 {
4271 typename Map::PersistentValueReference ref;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004272 Local<v8::Object> expected2 = NewObjectForIntKey(isolate, templ, 8);
4273 removed = map.Set(8, v8::Global<v8::Object>(isolate, expected2), &ref);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004274 CHECK_EQ(1, static_cast<int>(map.Size()));
4275 CHECK(expected == removed);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004276 CHECK(expected2->Equals(env.local(), ref.NewLocal(isolate)).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004277 }
4278 }
4279 CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
4280 if (map.IsWeak()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004281 CcTest::i_isolate()->heap()->CollectAllGarbage(
4282 i::Heap::kAbortIncrementalMarkingMask);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004283 } else {
4284 map.Clear();
4285 }
4286 CHECK_EQ(0, static_cast<int>(map.Size()));
4287 CHECK_EQ(initial_handle_count, global_handles->global_handles_count());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004288 {
4289 HandleScope scope(isolate);
4290 Local<v8::Object> value = NewObjectForIntKey(isolate, templ, 9);
4291 map.Set(9, value);
4292 map.Clear();
4293 }
4294 CHECK_EQ(0, static_cast<int>(map.Size()));
4295 CHECK_EQ(initial_handle_count, global_handles->global_handles_count());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004296}
4297
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004298} // namespace
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004299
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004300
4301TEST(GlobalValueMap) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004302 // Default case, w/o weak callbacks:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004303 TestGlobalValueMap<v8::StdGlobalValueMap<int, v8::Object>>();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004304
4305 // Custom traits with weak callbacks:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004306 typedef v8::GlobalValueMap<int, v8::Object,
4307 PhantomStdMapTraits<int, v8::Object>> WeakMap;
4308 TestGlobalValueMap<WeakMap>();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004309}
4310
4311
4312TEST(PersistentValueVector) {
4313 LocalContext env;
4314 v8::Isolate* isolate = env->GetIsolate();
4315 v8::internal::GlobalHandles* global_handles =
4316 reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
4317 int handle_count = global_handles->global_handles_count();
4318 HandleScope scope(isolate);
4319
4320 v8::PersistentValueVector<v8::Object> vector(isolate);
4321
4322 Local<v8::Object> obj1 = v8::Object::New(isolate);
4323 Local<v8::Object> obj2 = v8::Object::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004324 v8::Global<v8::Object> obj3(isolate, v8::Object::New(isolate));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004325
4326 CHECK(vector.IsEmpty());
4327 CHECK_EQ(0, static_cast<int>(vector.Size()));
4328
4329 vector.ReserveCapacity(3);
4330 CHECK(vector.IsEmpty());
4331
4332 vector.Append(obj1);
4333 vector.Append(obj2);
4334 vector.Append(obj1);
4335 vector.Append(obj3.Pass());
4336 vector.Append(obj1);
4337
4338 CHECK(!vector.IsEmpty());
4339 CHECK_EQ(5, static_cast<int>(vector.Size()));
4340 CHECK(obj3.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004341 CHECK(obj1->Equals(env.local(), vector.Get(0)).FromJust());
4342 CHECK(obj1->Equals(env.local(), vector.Get(2)).FromJust());
4343 CHECK(obj1->Equals(env.local(), vector.Get(4)).FromJust());
4344 CHECK(obj2->Equals(env.local(), vector.Get(1)).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004345
4346 CHECK_EQ(5 + handle_count, global_handles->global_handles_count());
4347
4348 vector.Clear();
4349 CHECK(vector.IsEmpty());
4350 CHECK_EQ(0, static_cast<int>(vector.Size()));
4351 CHECK_EQ(handle_count, global_handles->global_handles_count());
4352}
4353
4354
4355THREADED_TEST(GlobalHandleUpcast) {
4356 v8::Isolate* isolate = CcTest::isolate();
4357 v8::HandleScope scope(isolate);
4358 v8::Local<String> local = v8::Local<String>::New(isolate, v8_str("str"));
4359 v8::Persistent<String> global_string(isolate, local);
4360 v8::Persistent<Value>& global_value =
4361 v8::Persistent<Value>::Cast(global_string);
4362 CHECK(v8::Local<v8::Value>::New(isolate, global_value)->IsString());
4363 CHECK(global_string == v8::Persistent<String>::Cast(global_value));
4364 global_string.Reset();
4365}
4366
4367
4368THREADED_TEST(HandleEquality) {
4369 v8::Isolate* isolate = CcTest::isolate();
4370 v8::Persistent<String> global1;
4371 v8::Persistent<String> global2;
4372 {
4373 v8::HandleScope scope(isolate);
4374 global1.Reset(isolate, v8_str("str"));
4375 global2.Reset(isolate, v8_str("str2"));
4376 }
4377 CHECK_EQ(global1 == global1, true);
4378 CHECK_EQ(global1 != global1, false);
4379 {
4380 v8::HandleScope scope(isolate);
4381 Local<String> local1 = Local<String>::New(isolate, global1);
4382 Local<String> local2 = Local<String>::New(isolate, global2);
4383
4384 CHECK_EQ(global1 == local1, true);
4385 CHECK_EQ(global1 != local1, false);
4386 CHECK_EQ(local1 == global1, true);
4387 CHECK_EQ(local1 != global1, false);
4388
4389 CHECK_EQ(global1 == local2, false);
4390 CHECK_EQ(global1 != local2, true);
4391 CHECK_EQ(local2 == global1, false);
4392 CHECK_EQ(local2 != global1, true);
4393
4394 CHECK_EQ(local1 == local2, false);
4395 CHECK_EQ(local1 != local2, true);
4396
4397 Local<String> anotherLocal1 = Local<String>::New(isolate, global1);
4398 CHECK_EQ(local1 == anotherLocal1, true);
4399 CHECK_EQ(local1 != anotherLocal1, false);
4400 }
4401 global1.Reset();
4402 global2.Reset();
4403}
4404
4405
4406THREADED_TEST(LocalHandle) {
4407 v8::HandleScope scope(CcTest::isolate());
4408 v8::Local<String> local =
4409 v8::Local<String>::New(CcTest::isolate(), v8_str("str"));
4410 CHECK_EQ(local->Length(), 3);
Steve Blocka7e24c12009-10-30 11:49:00 +00004411}
4412
4413
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004414class WeakCallCounter {
4415 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004416 explicit WeakCallCounter(int id) : id_(id), number_of_weak_calls_(0) {}
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004417 int id() { return id_; }
4418 void increment() { number_of_weak_calls_++; }
4419 int NumberOfWeakCalls() { return number_of_weak_calls_; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004420
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004421 private:
4422 int id_;
4423 int number_of_weak_calls_;
4424};
4425
4426
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004427template <typename T>
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004428struct WeakCallCounterAndPersistent {
4429 explicit WeakCallCounterAndPersistent(WeakCallCounter* counter)
4430 : counter(counter) {}
4431 WeakCallCounter* counter;
4432 v8::Persistent<T> handle;
4433};
4434
4435
4436template <typename T>
4437static void WeakPointerCallback(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004438 const v8::WeakCallbackInfo<WeakCallCounterAndPersistent<T>>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004439 CHECK_EQ(1234, data.GetParameter()->counter->id());
4440 data.GetParameter()->counter->increment();
4441 data.GetParameter()->handle.Reset();
4442}
4443
4444
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004445template <typename T>
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004446static UniqueId MakeUniqueId(const Persistent<T>& p) {
4447 return UniqueId(reinterpret_cast<uintptr_t>(*v8::Utils::OpenPersistent(p)));
Steve Block44f0eee2011-05-26 01:26:41 +01004448}
4449
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004450
Steve Block44f0eee2011-05-26 01:26:41 +01004451THREADED_TEST(ApiObjectGroups) {
Steve Block44f0eee2011-05-26 01:26:41 +01004452 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004453 v8::Isolate* iso = env->GetIsolate();
4454 HandleScope scope(iso);
Steve Block44f0eee2011-05-26 01:26:41 +01004455
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004456 WeakCallCounter counter(1234);
4457
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004458 WeakCallCounterAndPersistent<Value> g1s1(&counter);
4459 WeakCallCounterAndPersistent<Value> g1s2(&counter);
4460 WeakCallCounterAndPersistent<Value> g1c1(&counter);
4461 WeakCallCounterAndPersistent<Value> g2s1(&counter);
4462 WeakCallCounterAndPersistent<Value> g2s2(&counter);
4463 WeakCallCounterAndPersistent<Value> g2c1(&counter);
Steve Block44f0eee2011-05-26 01:26:41 +01004464
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004465 {
4466 HandleScope scope(iso);
4467 g1s1.handle.Reset(iso, Object::New(iso));
4468 g1s2.handle.Reset(iso, Object::New(iso));
4469 g1c1.handle.Reset(iso, Object::New(iso));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004470 g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback,
4471 v8::WeakCallbackType::kParameter);
4472 g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback,
4473 v8::WeakCallbackType::kParameter);
4474 g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback,
4475 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004476
4477 g2s1.handle.Reset(iso, Object::New(iso));
4478 g2s2.handle.Reset(iso, Object::New(iso));
4479 g2c1.handle.Reset(iso, Object::New(iso));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004480 g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback,
4481 v8::WeakCallbackType::kParameter);
4482 g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback,
4483 v8::WeakCallbackType::kParameter);
4484 g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback,
4485 v8::WeakCallbackType::kParameter);
Steve Block44f0eee2011-05-26 01:26:41 +01004486 }
4487
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004488 WeakCallCounterAndPersistent<Value> root(&counter);
4489 root.handle.Reset(iso, g1s1.handle); // make a root.
Steve Block44f0eee2011-05-26 01:26:41 +01004490
4491 // Connect group 1 and 2, make a cycle.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004492 {
4493 HandleScope scope(iso);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004494 CHECK(Local<Object>::New(iso, g1s2.handle.As<Object>())
4495 ->Set(env.local(), 0, Local<Value>::New(iso, g2s2.handle))
4496 .FromJust());
4497 CHECK(Local<Object>::New(iso, g2s1.handle.As<Object>())
4498 ->Set(env.local(), 0, Local<Value>::New(iso, g1s1.handle))
4499 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004500 }
Steve Block44f0eee2011-05-26 01:26:41 +01004501
4502 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004503 UniqueId id1 = MakeUniqueId(g1s1.handle);
4504 UniqueId id2 = MakeUniqueId(g2s2.handle);
4505 iso->SetObjectGroupId(g1s1.handle, id1);
4506 iso->SetObjectGroupId(g1s2.handle, id1);
4507 iso->SetReferenceFromGroup(id1, g1c1.handle);
4508 iso->SetObjectGroupId(g2s1.handle, id2);
4509 iso->SetObjectGroupId(g2s2.handle, id2);
4510 iso->SetReferenceFromGroup(id2, g2c1.handle);
Steve Block44f0eee2011-05-26 01:26:41 +01004511 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004512 // Do a single full GC, ensure incremental marking is stopped.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004513 v8::internal::Heap* heap =
4514 reinterpret_cast<v8::internal::Isolate*>(iso)->heap();
4515 heap->CollectAllGarbage();
Steve Block44f0eee2011-05-26 01:26:41 +01004516
4517 // All object should be alive.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004518 CHECK_EQ(0, counter.NumberOfWeakCalls());
Steve Block44f0eee2011-05-26 01:26:41 +01004519
4520 // Weaken the root.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004521 root.handle.SetWeak(&root, &WeakPointerCallback,
4522 v8::WeakCallbackType::kParameter);
Steve Block44f0eee2011-05-26 01:26:41 +01004523 // But make children strong roots---all the objects (except for children)
4524 // should be collectable now.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004525 g1c1.handle.ClearWeak();
4526 g2c1.handle.ClearWeak();
Steve Block44f0eee2011-05-26 01:26:41 +01004527
4528 // Groups are deleted, rebuild groups.
4529 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004530 UniqueId id1 = MakeUniqueId(g1s1.handle);
4531 UniqueId id2 = MakeUniqueId(g2s2.handle);
4532 iso->SetObjectGroupId(g1s1.handle, id1);
4533 iso->SetObjectGroupId(g1s2.handle, id1);
4534 iso->SetReferenceFromGroup(id1, g1c1.handle);
4535 iso->SetObjectGroupId(g2s1.handle, id2);
4536 iso->SetObjectGroupId(g2s2.handle, id2);
4537 iso->SetReferenceFromGroup(id2, g2c1.handle);
Steve Block44f0eee2011-05-26 01:26:41 +01004538 }
4539
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004540 heap->CollectAllGarbage();
Steve Block44f0eee2011-05-26 01:26:41 +01004541
4542 // All objects should be gone. 5 global handles in total.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004543 CHECK_EQ(5, counter.NumberOfWeakCalls());
Steve Block44f0eee2011-05-26 01:26:41 +01004544
4545 // And now make children weak again and collect them.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004546 g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback,
4547 v8::WeakCallbackType::kParameter);
4548 g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback,
4549 v8::WeakCallbackType::kParameter);
Steve Block44f0eee2011-05-26 01:26:41 +01004550
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004551 heap->CollectAllGarbage();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004552 CHECK_EQ(7, counter.NumberOfWeakCalls());
Steve Block44f0eee2011-05-26 01:26:41 +01004553}
4554
4555
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004556THREADED_TEST(ApiObjectGroupsForSubtypes) {
Steve Block44f0eee2011-05-26 01:26:41 +01004557 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004558 v8::Isolate* iso = env->GetIsolate();
4559 HandleScope scope(iso);
Steve Block44f0eee2011-05-26 01:26:41 +01004560
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004561 WeakCallCounter counter(1234);
Steve Block44f0eee2011-05-26 01:26:41 +01004562
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004563 WeakCallCounterAndPersistent<Object> g1s1(&counter);
4564 WeakCallCounterAndPersistent<String> g1s2(&counter);
4565 WeakCallCounterAndPersistent<String> g1c1(&counter);
4566 WeakCallCounterAndPersistent<Object> g2s1(&counter);
4567 WeakCallCounterAndPersistent<String> g2s2(&counter);
4568 WeakCallCounterAndPersistent<String> g2c1(&counter);
Steve Block44f0eee2011-05-26 01:26:41 +01004569
4570 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004571 HandleScope scope(iso);
4572 g1s1.handle.Reset(iso, Object::New(iso));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004573 g1s2.handle.Reset(iso, v8_str("foo1"));
4574 g1c1.handle.Reset(iso, v8_str("foo2"));
4575 g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback,
4576 v8::WeakCallbackType::kParameter);
4577 g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback,
4578 v8::WeakCallbackType::kParameter);
4579 g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback,
4580 v8::WeakCallbackType::kParameter);
Steve Block44f0eee2011-05-26 01:26:41 +01004581
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004582 g2s1.handle.Reset(iso, Object::New(iso));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004583 g2s2.handle.Reset(iso, v8_str("foo3"));
4584 g2c1.handle.Reset(iso, v8_str("foo4"));
4585 g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback,
4586 v8::WeakCallbackType::kParameter);
4587 g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback,
4588 v8::WeakCallbackType::kParameter);
4589 g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback,
4590 v8::WeakCallbackType::kParameter);
Steve Block44f0eee2011-05-26 01:26:41 +01004591 }
4592
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004593 WeakCallCounterAndPersistent<Value> root(&counter);
4594 root.handle.Reset(iso, g1s1.handle); // make a root.
Steve Block44f0eee2011-05-26 01:26:41 +01004595
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004596 // Connect group 1 and 2, make a cycle.
Steve Block44f0eee2011-05-26 01:26:41 +01004597 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004598 HandleScope scope(iso);
4599 CHECK(Local<Object>::New(iso, g1s1.handle)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004600 ->Set(env.local(), 0, Local<Object>::New(iso, g2s1.handle))
4601 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004602 CHECK(Local<Object>::New(iso, g2s1.handle)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004603 ->Set(env.local(), 0, Local<Object>::New(iso, g1s1.handle))
4604 .FromJust());
Steve Block44f0eee2011-05-26 01:26:41 +01004605 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004606
4607 {
4608 UniqueId id1 = MakeUniqueId(g1s1.handle);
4609 UniqueId id2 = MakeUniqueId(g2s2.handle);
4610 iso->SetObjectGroupId(g1s1.handle, id1);
4611 iso->SetObjectGroupId(g1s2.handle, id1);
4612 iso->SetReference(g1s1.handle, g1c1.handle);
4613 iso->SetObjectGroupId(g2s1.handle, id2);
4614 iso->SetObjectGroupId(g2s2.handle, id2);
4615 iso->SetReferenceFromGroup(id2, g2c1.handle);
4616 }
4617 // Do a single full GC, ensure incremental marking is stopped.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004618 v8::internal::Heap* heap =
4619 reinterpret_cast<v8::internal::Isolate*>(iso)->heap();
4620 heap->CollectAllGarbage();
Steve Block44f0eee2011-05-26 01:26:41 +01004621
4622 // All object should be alive.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004623 CHECK_EQ(0, counter.NumberOfWeakCalls());
Steve Block44f0eee2011-05-26 01:26:41 +01004624
4625 // Weaken the root.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004626 root.handle.SetWeak(&root, &WeakPointerCallback,
4627 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004628 // But make children strong roots---all the objects (except for children)
4629 // should be collectable now.
4630 g1c1.handle.ClearWeak();
4631 g2c1.handle.ClearWeak();
Steve Block44f0eee2011-05-26 01:26:41 +01004632
4633 // Groups are deleted, rebuild groups.
4634 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004635 UniqueId id1 = MakeUniqueId(g1s1.handle);
4636 UniqueId id2 = MakeUniqueId(g2s2.handle);
4637 iso->SetObjectGroupId(g1s1.handle, id1);
4638 iso->SetObjectGroupId(g1s2.handle, id1);
4639 iso->SetReference(g1s1.handle, g1c1.handle);
4640 iso->SetObjectGroupId(g2s1.handle, id2);
4641 iso->SetObjectGroupId(g2s2.handle, id2);
4642 iso->SetReferenceFromGroup(id2, g2c1.handle);
Steve Block44f0eee2011-05-26 01:26:41 +01004643 }
4644
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004645 heap->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004646
4647 // All objects should be gone. 5 global handles in total.
4648 CHECK_EQ(5, counter.NumberOfWeakCalls());
4649
4650 // And now make children weak again and collect them.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004651 g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback,
4652 v8::WeakCallbackType::kParameter);
4653 g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback,
4654 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004655
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004656 heap->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004657 CHECK_EQ(7, counter.NumberOfWeakCalls());
4658}
4659
4660
4661THREADED_TEST(ApiObjectGroupsCycle) {
4662 LocalContext env;
4663 v8::Isolate* iso = env->GetIsolate();
4664 HandleScope scope(iso);
4665
4666 WeakCallCounter counter(1234);
4667
4668 WeakCallCounterAndPersistent<Value> g1s1(&counter);
4669 WeakCallCounterAndPersistent<Value> g1s2(&counter);
4670 WeakCallCounterAndPersistent<Value> g2s1(&counter);
4671 WeakCallCounterAndPersistent<Value> g2s2(&counter);
4672 WeakCallCounterAndPersistent<Value> g3s1(&counter);
4673 WeakCallCounterAndPersistent<Value> g3s2(&counter);
4674 WeakCallCounterAndPersistent<Value> g4s1(&counter);
4675 WeakCallCounterAndPersistent<Value> g4s2(&counter);
4676
4677 {
4678 HandleScope scope(iso);
4679 g1s1.handle.Reset(iso, Object::New(iso));
4680 g1s2.handle.Reset(iso, Object::New(iso));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004681 g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback,
4682 v8::WeakCallbackType::kParameter);
4683 g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback,
4684 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004685 CHECK(g1s1.handle.IsWeak());
4686 CHECK(g1s2.handle.IsWeak());
4687
4688 g2s1.handle.Reset(iso, Object::New(iso));
4689 g2s2.handle.Reset(iso, Object::New(iso));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004690 g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback,
4691 v8::WeakCallbackType::kParameter);
4692 g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback,
4693 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004694 CHECK(g2s1.handle.IsWeak());
4695 CHECK(g2s2.handle.IsWeak());
4696
4697 g3s1.handle.Reset(iso, Object::New(iso));
4698 g3s2.handle.Reset(iso, Object::New(iso));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004699 g3s1.handle.SetWeak(&g3s1, &WeakPointerCallback,
4700 v8::WeakCallbackType::kParameter);
4701 g3s2.handle.SetWeak(&g3s2, &WeakPointerCallback,
4702 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004703 CHECK(g3s1.handle.IsWeak());
4704 CHECK(g3s2.handle.IsWeak());
4705
4706 g4s1.handle.Reset(iso, Object::New(iso));
4707 g4s2.handle.Reset(iso, Object::New(iso));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004708 g4s1.handle.SetWeak(&g4s1, &WeakPointerCallback,
4709 v8::WeakCallbackType::kParameter);
4710 g4s2.handle.SetWeak(&g4s2, &WeakPointerCallback,
4711 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004712 CHECK(g4s1.handle.IsWeak());
4713 CHECK(g4s2.handle.IsWeak());
4714 }
4715
4716 WeakCallCounterAndPersistent<Value> root(&counter);
4717 root.handle.Reset(iso, g1s1.handle); // make a root.
4718
4719 // Connect groups. We're building the following cycle:
4720 // G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other
4721 // groups.
4722 {
4723 UniqueId id1 = MakeUniqueId(g1s1.handle);
4724 UniqueId id2 = MakeUniqueId(g2s1.handle);
4725 UniqueId id3 = MakeUniqueId(g3s1.handle);
4726 UniqueId id4 = MakeUniqueId(g4s1.handle);
4727 iso->SetObjectGroupId(g1s1.handle, id1);
4728 iso->SetObjectGroupId(g1s2.handle, id1);
4729 iso->SetReferenceFromGroup(id1, g2s1.handle);
4730 iso->SetObjectGroupId(g2s1.handle, id2);
4731 iso->SetObjectGroupId(g2s2.handle, id2);
4732 iso->SetReferenceFromGroup(id2, g3s1.handle);
4733 iso->SetObjectGroupId(g3s1.handle, id3);
4734 iso->SetObjectGroupId(g3s2.handle, id3);
4735 iso->SetReferenceFromGroup(id3, g4s1.handle);
4736 iso->SetObjectGroupId(g4s1.handle, id4);
4737 iso->SetObjectGroupId(g4s2.handle, id4);
4738 iso->SetReferenceFromGroup(id4, g1s1.handle);
4739 }
4740 // Do a single full GC
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004741 v8::internal::Heap* heap =
4742 reinterpret_cast<v8::internal::Isolate*>(iso)->heap();
4743 heap->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004744
4745 // All object should be alive.
4746 CHECK_EQ(0, counter.NumberOfWeakCalls());
4747
4748 // Weaken the root.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004749 root.handle.SetWeak(&root, &WeakPointerCallback,
4750 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004751
4752 // Groups are deleted, rebuild groups.
4753 {
4754 UniqueId id1 = MakeUniqueId(g1s1.handle);
4755 UniqueId id2 = MakeUniqueId(g2s1.handle);
4756 UniqueId id3 = MakeUniqueId(g3s1.handle);
4757 UniqueId id4 = MakeUniqueId(g4s1.handle);
4758 iso->SetObjectGroupId(g1s1.handle, id1);
4759 iso->SetObjectGroupId(g1s2.handle, id1);
4760 iso->SetReferenceFromGroup(id1, g2s1.handle);
4761 iso->SetObjectGroupId(g2s1.handle, id2);
4762 iso->SetObjectGroupId(g2s2.handle, id2);
4763 iso->SetReferenceFromGroup(id2, g3s1.handle);
4764 iso->SetObjectGroupId(g3s1.handle, id3);
4765 iso->SetObjectGroupId(g3s2.handle, id3);
4766 iso->SetReferenceFromGroup(id3, g4s1.handle);
4767 iso->SetObjectGroupId(g4s1.handle, id4);
4768 iso->SetObjectGroupId(g4s2.handle, id4);
4769 iso->SetReferenceFromGroup(id4, g1s1.handle);
4770 }
4771
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004772 heap->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004773
4774 // All objects should be gone. 9 global handles in total.
4775 CHECK_EQ(9, counter.NumberOfWeakCalls());
4776}
4777
4778
Steve Blocka7e24c12009-10-30 11:49:00 +00004779THREADED_TEST(ScriptException) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004780 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004781 v8::HandleScope scope(env->GetIsolate());
4782 Local<Script> script = v8_compile("throw 'panama!';");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004783 v8::TryCatch try_catch(env->GetIsolate());
4784 v8::MaybeLocal<Value> result = script->Run(env.local());
Steve Blocka7e24c12009-10-30 11:49:00 +00004785 CHECK(result.IsEmpty());
4786 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004787 String::Utf8Value exception_value(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004788 CHECK_EQ(0, strcmp(*exception_value, "panama!"));
Steve Blocka7e24c12009-10-30 11:49:00 +00004789}
4790
4791
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004792TEST(TryCatchCustomException) {
4793 LocalContext env;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004794 v8::Isolate* isolate = env->GetIsolate();
4795 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004796 v8::TryCatch try_catch(isolate);
4797 CompileRun(
4798 "function CustomError() { this.a = 'b'; }"
4799 "(function f() { throw new CustomError(); })();");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004800 CHECK(try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004801 CHECK(try_catch.Exception()
4802 ->ToObject(env.local())
4803 .ToLocalChecked()
4804 ->Get(env.local(), v8_str("a"))
4805 .ToLocalChecked()
4806 ->Equals(env.local(), v8_str("b"))
4807 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004808}
4809
4810
Steve Blocka7e24c12009-10-30 11:49:00 +00004811bool message_received;
4812
4813
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004814static void check_message_0(v8::Local<v8::Message> message,
4815 v8::Local<Value> data) {
4816 CHECK_EQ(5.76, data->NumberValue(CcTest::isolate()->GetCurrentContext())
4817 .FromJust());
4818 CHECK_EQ(6.75, message->GetScriptOrigin()
4819 .ResourceName()
4820 ->NumberValue(CcTest::isolate()->GetCurrentContext())
4821 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004822 CHECK(!message->IsSharedCrossOrigin());
Steve Blocka7e24c12009-10-30 11:49:00 +00004823 message_received = true;
4824}
4825
4826
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004827THREADED_TEST(MessageHandler0) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004828 message_received = false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004829 v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00004830 CHECK(!message_received);
Steve Blocka7e24c12009-10-30 11:49:00 +00004831 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004832 CcTest::isolate()->AddMessageListener(check_message_0, v8_num(5.76));
4833 v8::Local<v8::Script> script = CompileWithOrigin("throw 'error'", "6.75");
4834 CHECK(script->Run(context.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00004835 CHECK(message_received);
4836 // clear out the message listener
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004837 CcTest::isolate()->RemoveMessageListeners(check_message_0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004838}
4839
4840
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004841static void check_message_1(v8::Local<v8::Message> message,
4842 v8::Local<Value> data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004843 CHECK(data->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004844 CHECK_EQ(1337,
4845 data->Int32Value(CcTest::isolate()->GetCurrentContext()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004846 CHECK(!message->IsSharedCrossOrigin());
4847 message_received = true;
4848}
4849
4850
4851TEST(MessageHandler1) {
4852 message_received = false;
4853 v8::HandleScope scope(CcTest::isolate());
4854 CHECK(!message_received);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004855 CcTest::isolate()->AddMessageListener(check_message_1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004856 LocalContext context;
4857 CompileRun("throw 1337;");
4858 CHECK(message_received);
4859 // clear out the message listener
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004860 CcTest::isolate()->RemoveMessageListeners(check_message_1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004861}
4862
4863
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004864static void check_message_2(v8::Local<v8::Message> message,
4865 v8::Local<Value> data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004866 LocalContext context;
4867 CHECK(data->IsObject());
4868 v8::Local<v8::Value> hidden_property =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004869 v8::Object::Cast(*data)
4870 ->GetPrivate(
4871 context.local(),
4872 v8::Private::ForApi(CcTest::isolate(), v8_str("hidden key")))
4873 .ToLocalChecked();
4874 CHECK(v8_str("hidden value")
4875 ->Equals(context.local(), hidden_property)
4876 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004877 CHECK(!message->IsSharedCrossOrigin());
4878 message_received = true;
4879}
4880
4881
4882TEST(MessageHandler2) {
4883 message_received = false;
4884 v8::HandleScope scope(CcTest::isolate());
4885 CHECK(!message_received);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004886 CcTest::isolate()->AddMessageListener(check_message_2);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004887 LocalContext context;
4888 v8::Local<v8::Value> error = v8::Exception::Error(v8_str("custom error"));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004889 v8::Object::Cast(*error)
4890 ->SetPrivate(context.local(),
4891 v8::Private::ForApi(CcTest::isolate(), v8_str("hidden key")),
4892 v8_str("hidden value"))
4893 .FromJust();
4894 CHECK(context->Global()
4895 ->Set(context.local(), v8_str("error"), error)
4896 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004897 CompileRun("throw error;");
4898 CHECK(message_received);
4899 // clear out the message listener
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004900 CcTest::isolate()->RemoveMessageListeners(check_message_2);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004901}
4902
4903
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004904static void check_message_3(v8::Local<v8::Message> message,
4905 v8::Local<Value> data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004906 CHECK(message->IsSharedCrossOrigin());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004907 CHECK(message->GetScriptOrigin().Options().IsSharedCrossOrigin());
4908 CHECK(message->GetScriptOrigin().Options().IsEmbedderDebugScript());
4909 CHECK(message->GetScriptOrigin().Options().IsOpaque());
4910 CHECK_EQ(6.75, message->GetScriptOrigin()
4911 .ResourceName()
4912 ->NumberValue(CcTest::isolate()->GetCurrentContext())
4913 .FromJust());
4914 CHECK_EQ(7.40, message->GetScriptOrigin()
4915 .SourceMapUrl()
4916 ->NumberValue(CcTest::isolate()->GetCurrentContext())
4917 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004918 message_received = true;
4919}
4920
4921
4922TEST(MessageHandler3) {
4923 message_received = false;
4924 v8::Isolate* isolate = CcTest::isolate();
4925 v8::HandleScope scope(isolate);
4926 CHECK(!message_received);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004927 isolate->AddMessageListener(check_message_3);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004928 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004929 v8::ScriptOrigin origin = v8::ScriptOrigin(
4930 v8_str("6.75"), v8::Integer::New(isolate, 1),
4931 v8::Integer::New(isolate, 2), v8::True(isolate), Local<v8::Integer>(),
4932 v8::True(isolate), v8_str("7.40"), v8::True(isolate));
4933 v8::Local<v8::Script> script =
4934 Script::Compile(context.local(), v8_str("throw 'error'"), &origin)
4935 .ToLocalChecked();
4936 CHECK(script->Run(context.local()).IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004937 CHECK(message_received);
4938 // clear out the message listener
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004939 isolate->RemoveMessageListeners(check_message_3);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004940}
4941
4942
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004943static void check_message_4(v8::Local<v8::Message> message,
4944 v8::Local<Value> data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004945 CHECK(!message->IsSharedCrossOrigin());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004946 CHECK_EQ(6.75, message->GetScriptOrigin()
4947 .ResourceName()
4948 ->NumberValue(CcTest::isolate()->GetCurrentContext())
4949 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004950 message_received = true;
4951}
4952
4953
4954TEST(MessageHandler4) {
4955 message_received = false;
4956 v8::Isolate* isolate = CcTest::isolate();
4957 v8::HandleScope scope(isolate);
4958 CHECK(!message_received);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004959 isolate->AddMessageListener(check_message_4);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004960 LocalContext context;
4961 v8::ScriptOrigin origin =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004962 v8::ScriptOrigin(v8_str("6.75"), v8::Integer::New(isolate, 1),
4963 v8::Integer::New(isolate, 2), v8::False(isolate));
4964 v8::Local<v8::Script> script =
4965 Script::Compile(context.local(), v8_str("throw 'error'"), &origin)
4966 .ToLocalChecked();
4967 CHECK(script->Run(context.local()).IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004968 CHECK(message_received);
4969 // clear out the message listener
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004970 isolate->RemoveMessageListeners(check_message_4);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004971}
4972
4973
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004974static void check_message_5a(v8::Local<v8::Message> message,
4975 v8::Local<Value> data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004976 CHECK(message->IsSharedCrossOrigin());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004977 CHECK_EQ(6.75, message->GetScriptOrigin()
4978 .ResourceName()
4979 ->NumberValue(CcTest::isolate()->GetCurrentContext())
4980 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004981 message_received = true;
4982}
4983
4984
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004985static void check_message_5b(v8::Local<v8::Message> message,
4986 v8::Local<Value> data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004987 CHECK(!message->IsSharedCrossOrigin());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004988 CHECK_EQ(6.75, message->GetScriptOrigin()
4989 .ResourceName()
4990 ->NumberValue(CcTest::isolate()->GetCurrentContext())
4991 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004992 message_received = true;
4993}
4994
4995
4996TEST(MessageHandler5) {
4997 message_received = false;
4998 v8::Isolate* isolate = CcTest::isolate();
4999 v8::HandleScope scope(isolate);
5000 CHECK(!message_received);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005001 isolate->AddMessageListener(check_message_5a);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005002 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005003 v8::ScriptOrigin origin1 =
5004 v8::ScriptOrigin(v8_str("6.75"), v8::Integer::New(isolate, 1),
5005 v8::Integer::New(isolate, 2), v8::True(isolate));
5006 v8::Local<v8::Script> script =
5007 Script::Compile(context.local(), v8_str("throw 'error'"), &origin1)
5008 .ToLocalChecked();
5009 CHECK(script->Run(context.local()).IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005010 CHECK(message_received);
5011 // clear out the message listener
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005012 isolate->RemoveMessageListeners(check_message_5a);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005013
5014 message_received = false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005015 isolate->AddMessageListener(check_message_5b);
5016 v8::ScriptOrigin origin2 =
5017 v8::ScriptOrigin(v8_str("6.75"), v8::Integer::New(isolate, 1),
5018 v8::Integer::New(isolate, 2), v8::False(isolate));
5019 script = Script::Compile(context.local(), v8_str("throw 'error'"), &origin2)
5020 .ToLocalChecked();
5021 CHECK(script->Run(context.local()).IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005022 CHECK(message_received);
5023 // clear out the message listener
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005024 isolate->RemoveMessageListeners(check_message_5b);
5025}
5026
5027
5028TEST(NativeWeakMap) {
5029 v8::Isolate* isolate = CcTest::isolate();
5030 HandleScope scope(isolate);
5031 Local<v8::NativeWeakMap> weak_map(v8::NativeWeakMap::New(isolate));
5032 CHECK(!weak_map.IsEmpty());
5033
5034 LocalContext env;
5035 Local<Object> value = v8::Object::New(isolate);
5036
5037 Local<Object> local1 = v8::Object::New(isolate);
5038 CHECK(!weak_map->Has(local1));
5039 CHECK(weak_map->Get(local1)->IsUndefined());
5040 weak_map->Set(local1, value);
5041 CHECK(weak_map->Has(local1));
5042 CHECK(value->Equals(env.local(), weak_map->Get(local1)).FromJust());
5043
5044 WeakCallCounter counter(1234);
5045 WeakCallCounterAndPersistent<Value> o1(&counter);
5046 WeakCallCounterAndPersistent<Value> o2(&counter);
5047 WeakCallCounterAndPersistent<Value> s1(&counter);
5048 {
5049 HandleScope scope(isolate);
5050 Local<v8::Object> obj1 = v8::Object::New(isolate);
5051 Local<v8::Object> obj2 = v8::Object::New(isolate);
5052 Local<v8::Symbol> sym1 = v8::Symbol::New(isolate);
5053
5054 weak_map->Set(obj1, value);
5055 weak_map->Set(obj2, value);
5056 weak_map->Set(sym1, value);
5057
5058 o1.handle.Reset(isolate, obj1);
5059 o2.handle.Reset(isolate, obj2);
5060 s1.handle.Reset(isolate, sym1);
5061
5062 CHECK(weak_map->Has(local1));
5063 CHECK(weak_map->Has(obj1));
5064 CHECK(weak_map->Has(obj2));
5065 CHECK(weak_map->Has(sym1));
5066
5067 CHECK(value->Equals(env.local(), weak_map->Get(local1)).FromJust());
5068 CHECK(value->Equals(env.local(), weak_map->Get(obj1)).FromJust());
5069 CHECK(value->Equals(env.local(), weak_map->Get(obj2)).FromJust());
5070 CHECK(value->Equals(env.local(), weak_map->Get(sym1)).FromJust());
5071 }
5072 CcTest::heap()->CollectAllGarbage();
5073 {
5074 HandleScope scope(isolate);
5075 CHECK(value->Equals(env.local(), weak_map->Get(local1)).FromJust());
5076 CHECK(value->Equals(env.local(),
5077 weak_map->Get(Local<Value>::New(isolate, o1.handle)))
5078 .FromJust());
5079 CHECK(value->Equals(env.local(),
5080 weak_map->Get(Local<Value>::New(isolate, o2.handle)))
5081 .FromJust());
5082 CHECK(value->Equals(env.local(),
5083 weak_map->Get(Local<Value>::New(isolate, s1.handle)))
5084 .FromJust());
5085 }
5086
5087 o1.handle.SetWeak(&o1, &WeakPointerCallback,
5088 v8::WeakCallbackType::kParameter);
5089 o2.handle.SetWeak(&o2, &WeakPointerCallback,
5090 v8::WeakCallbackType::kParameter);
5091 s1.handle.SetWeak(&s1, &WeakPointerCallback,
5092 v8::WeakCallbackType::kParameter);
5093
5094 CcTest::heap()->CollectAllGarbage();
5095 CHECK_EQ(3, counter.NumberOfWeakCalls());
5096
5097 CHECK(o1.handle.IsEmpty());
5098 CHECK(o2.handle.IsEmpty());
5099 CHECK(s1.handle.IsEmpty());
5100
5101 CHECK(value->Equals(env.local(), weak_map->Get(local1)).FromJust());
5102 CHECK(weak_map->Delete(local1));
5103 CHECK(!weak_map->Has(local1));
5104 CHECK(weak_map->Get(local1)->IsUndefined());
Steve Blocka7e24c12009-10-30 11:49:00 +00005105}
5106
5107
5108THREADED_TEST(GetSetProperty) {
Steve Blocka7e24c12009-10-30 11:49:00 +00005109 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005110 v8::Isolate* isolate = context->GetIsolate();
5111 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005112 CHECK(context->Global()
5113 ->Set(context.local(), v8_str("foo"), v8_num(14))
5114 .FromJust());
5115 CHECK(context->Global()
5116 ->Set(context.local(), v8_str("12"), v8_num(92))
5117 .FromJust());
5118 CHECK(context->Global()
5119 ->Set(context.local(), v8::Integer::New(isolate, 16), v8_num(32))
5120 .FromJust());
5121 CHECK(context->Global()
5122 ->Set(context.local(), v8_num(13), v8_num(56))
5123 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005124 Local<Value> foo = CompileRun("this.foo");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005125 CHECK_EQ(14, foo->Int32Value(context.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005126 Local<Value> twelve = CompileRun("this[12]");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005127 CHECK_EQ(92, twelve->Int32Value(context.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005128 Local<Value> sixteen = CompileRun("this[16]");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005129 CHECK_EQ(32, sixteen->Int32Value(context.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005130 Local<Value> thirteen = CompileRun("this[13]");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005131 CHECK_EQ(56, thirteen->Int32Value(context.local()).FromJust());
5132 CHECK_EQ(92, context->Global()
5133 ->Get(context.local(), v8::Integer::New(isolate, 12))
5134 .ToLocalChecked()
5135 ->Int32Value(context.local())
5136 .FromJust());
5137 CHECK_EQ(92, context->Global()
5138 ->Get(context.local(), v8_str("12"))
5139 .ToLocalChecked()
5140 ->Int32Value(context.local())
5141 .FromJust());
5142 CHECK_EQ(92, context->Global()
5143 ->Get(context.local(), v8_num(12))
5144 .ToLocalChecked()
5145 ->Int32Value(context.local())
5146 .FromJust());
5147 CHECK_EQ(32, context->Global()
5148 ->Get(context.local(), v8::Integer::New(isolate, 16))
5149 .ToLocalChecked()
5150 ->Int32Value(context.local())
5151 .FromJust());
5152 CHECK_EQ(32, context->Global()
5153 ->Get(context.local(), v8_str("16"))
5154 .ToLocalChecked()
5155 ->Int32Value(context.local())
5156 .FromJust());
5157 CHECK_EQ(32, context->Global()
5158 ->Get(context.local(), v8_num(16))
5159 .ToLocalChecked()
5160 ->Int32Value(context.local())
5161 .FromJust());
5162 CHECK_EQ(56, context->Global()
5163 ->Get(context.local(), v8::Integer::New(isolate, 13))
5164 .ToLocalChecked()
5165 ->Int32Value(context.local())
5166 .FromJust());
5167 CHECK_EQ(56, context->Global()
5168 ->Get(context.local(), v8_str("13"))
5169 .ToLocalChecked()
5170 ->Int32Value(context.local())
5171 .FromJust());
5172 CHECK_EQ(56, context->Global()
5173 ->Get(context.local(), v8_num(13))
5174 .ToLocalChecked()
5175 ->Int32Value(context.local())
5176 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005177}
5178
5179
5180THREADED_TEST(PropertyAttributes) {
Steve Blocka7e24c12009-10-30 11:49:00 +00005181 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005182 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005183 // none
5184 Local<String> prop = v8_str("none");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005185 CHECK(context->Global()->Set(context.local(), prop, v8_num(7)).FromJust());
5186 CHECK_EQ(v8::None, context->Global()
5187 ->GetPropertyAttributes(context.local(), prop)
5188 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005189 // read-only
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005190 prop = v8_str("read_only");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005191 context->Global()
5192 ->DefineOwnProperty(context.local(), prop, v8_num(7), v8::ReadOnly)
5193 .FromJust();
5194 CHECK_EQ(7, context->Global()
5195 ->Get(context.local(), prop)
5196 .ToLocalChecked()
5197 ->Int32Value(context.local())
5198 .FromJust());
5199 CHECK_EQ(v8::ReadOnly, context->Global()
5200 ->GetPropertyAttributes(context.local(), prop)
5201 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005202 CompileRun("read_only = 9");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005203 CHECK_EQ(7, context->Global()
5204 ->Get(context.local(), prop)
5205 .ToLocalChecked()
5206 ->Int32Value(context.local())
5207 .FromJust());
5208 CHECK(context->Global()->Set(context.local(), prop, v8_num(10)).FromJust());
5209 CHECK_EQ(7, context->Global()
5210 ->Get(context.local(), prop)
5211 .ToLocalChecked()
5212 ->Int32Value(context.local())
5213 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005214 // dont-delete
5215 prop = v8_str("dont_delete");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005216 context->Global()
5217 ->DefineOwnProperty(context.local(), prop, v8_num(13), v8::DontDelete)
5218 .FromJust();
5219 CHECK_EQ(13, context->Global()
5220 ->Get(context.local(), prop)
5221 .ToLocalChecked()
5222 ->Int32Value(context.local())
5223 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005224 CompileRun("delete dont_delete");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005225 CHECK_EQ(13, context->Global()
5226 ->Get(context.local(), prop)
5227 .ToLocalChecked()
5228 ->Int32Value(context.local())
5229 .FromJust());
5230 CHECK_EQ(v8::DontDelete, context->Global()
5231 ->GetPropertyAttributes(context.local(), prop)
5232 .FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005233 // dont-enum
5234 prop = v8_str("dont_enum");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005235 context->Global()
5236 ->DefineOwnProperty(context.local(), prop, v8_num(28), v8::DontEnum)
5237 .FromJust();
5238 CHECK_EQ(v8::DontEnum, context->Global()
5239 ->GetPropertyAttributes(context.local(), prop)
5240 .FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005241 // absent
5242 prop = v8_str("absent");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005243 CHECK_EQ(v8::None, context->Global()
5244 ->GetPropertyAttributes(context.local(), prop)
5245 .FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005246 Local<Value> fake_prop = v8_num(1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005247 CHECK_EQ(v8::None, context->Global()
5248 ->GetPropertyAttributes(context.local(), fake_prop)
5249 .FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005250 // exception
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005251 TryCatch try_catch(context->GetIsolate());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005252 Local<Value> exception =
5253 CompileRun("({ toString: function() { throw 'exception';} })");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005254 CHECK(context->Global()
5255 ->GetPropertyAttributes(context.local(), exception)
5256 .IsNothing());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005257 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005258 String::Utf8Value exception_value(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005259 CHECK_EQ(0, strcmp("exception", *exception_value));
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005260 try_catch.Reset();
Steve Blocka7e24c12009-10-30 11:49:00 +00005261}
5262
5263
5264THREADED_TEST(Array) {
Steve Blocka7e24c12009-10-30 11:49:00 +00005265 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005266 v8::HandleScope scope(context->GetIsolate());
5267 Local<v8::Array> array = v8::Array::New(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005268 CHECK_EQ(0u, array->Length());
5269 CHECK(array->Get(context.local(), 0).ToLocalChecked()->IsUndefined());
5270 CHECK(!array->Has(context.local(), 0).FromJust());
5271 CHECK(array->Get(context.local(), 100).ToLocalChecked()->IsUndefined());
5272 CHECK(!array->Has(context.local(), 100).FromJust());
5273 CHECK(array->Set(context.local(), 2, v8_num(7)).FromJust());
5274 CHECK_EQ(3u, array->Length());
5275 CHECK(!array->Has(context.local(), 0).FromJust());
5276 CHECK(!array->Has(context.local(), 1).FromJust());
5277 CHECK(array->Has(context.local(), 2).FromJust());
5278 CHECK_EQ(7, array->Get(context.local(), 2)
5279 .ToLocalChecked()
5280 ->Int32Value(context.local())
5281 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005282 Local<Value> obj = CompileRun("[1, 2, 3]");
Steve Block6ded16b2010-05-10 14:33:55 +01005283 Local<v8::Array> arr = obj.As<v8::Array>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005284 CHECK_EQ(3u, arr->Length());
5285 CHECK_EQ(1, arr->Get(context.local(), 0)
5286 .ToLocalChecked()
5287 ->Int32Value(context.local())
5288 .FromJust());
5289 CHECK_EQ(2, arr->Get(context.local(), 1)
5290 .ToLocalChecked()
5291 ->Int32Value(context.local())
5292 .FromJust());
5293 CHECK_EQ(3, arr->Get(context.local(), 2)
5294 .ToLocalChecked()
5295 ->Int32Value(context.local())
5296 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005297 array = v8::Array::New(context->GetIsolate(), 27);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005298 CHECK_EQ(27u, array->Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005299 array = v8::Array::New(context->GetIsolate(), -27);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005300 CHECK_EQ(0u, array->Length());
Steve Blocka7e24c12009-10-30 11:49:00 +00005301}
5302
5303
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005304void HandleF(const v8::FunctionCallbackInfo<v8::Value>& args) {
5305 v8::EscapableHandleScope scope(args.GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00005306 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005307 Local<v8::Array> result = v8::Array::New(args.GetIsolate(), args.Length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005308 for (int i = 0; i < args.Length(); i++) {
5309 CHECK(result->Set(CcTest::isolate()->GetCurrentContext(), i, args[i])
5310 .FromJust());
5311 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005312 args.GetReturnValue().Set(scope.Escape(result));
Steve Blocka7e24c12009-10-30 11:49:00 +00005313}
5314
5315
5316THREADED_TEST(Vector) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005317 v8::Isolate* isolate = CcTest::isolate();
5318 v8::HandleScope scope(isolate);
5319 Local<ObjectTemplate> global = ObjectTemplate::New(isolate);
5320 global->Set(v8_str("f"), v8::FunctionTemplate::New(isolate, HandleF));
Steve Blocka7e24c12009-10-30 11:49:00 +00005321 LocalContext context(0, global);
5322
5323 const char* fun = "f()";
Steve Block6ded16b2010-05-10 14:33:55 +01005324 Local<v8::Array> a0 = CompileRun(fun).As<v8::Array>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005325 CHECK_EQ(0u, a0->Length());
Steve Blocka7e24c12009-10-30 11:49:00 +00005326
5327 const char* fun2 = "f(11)";
Steve Block6ded16b2010-05-10 14:33:55 +01005328 Local<v8::Array> a1 = CompileRun(fun2).As<v8::Array>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005329 CHECK_EQ(1u, a1->Length());
5330 CHECK_EQ(11, a1->Get(context.local(), 0)
5331 .ToLocalChecked()
5332 ->Int32Value(context.local())
5333 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005334
5335 const char* fun3 = "f(12, 13)";
Steve Block6ded16b2010-05-10 14:33:55 +01005336 Local<v8::Array> a2 = CompileRun(fun3).As<v8::Array>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005337 CHECK_EQ(2u, a2->Length());
5338 CHECK_EQ(12, a2->Get(context.local(), 0)
5339 .ToLocalChecked()
5340 ->Int32Value(context.local())
5341 .FromJust());
5342 CHECK_EQ(13, a2->Get(context.local(), 1)
5343 .ToLocalChecked()
5344 ->Int32Value(context.local())
5345 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005346
5347 const char* fun4 = "f(14, 15, 16)";
Steve Block6ded16b2010-05-10 14:33:55 +01005348 Local<v8::Array> a3 = CompileRun(fun4).As<v8::Array>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005349 CHECK_EQ(3u, a3->Length());
5350 CHECK_EQ(14, a3->Get(context.local(), 0)
5351 .ToLocalChecked()
5352 ->Int32Value(context.local())
5353 .FromJust());
5354 CHECK_EQ(15, a3->Get(context.local(), 1)
5355 .ToLocalChecked()
5356 ->Int32Value(context.local())
5357 .FromJust());
5358 CHECK_EQ(16, a3->Get(context.local(), 2)
5359 .ToLocalChecked()
5360 ->Int32Value(context.local())
5361 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005362
5363 const char* fun5 = "f(17, 18, 19, 20)";
Steve Block6ded16b2010-05-10 14:33:55 +01005364 Local<v8::Array> a4 = CompileRun(fun5).As<v8::Array>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005365 CHECK_EQ(4u, a4->Length());
5366 CHECK_EQ(17, a4->Get(context.local(), 0)
5367 .ToLocalChecked()
5368 ->Int32Value(context.local())
5369 .FromJust());
5370 CHECK_EQ(18, a4->Get(context.local(), 1)
5371 .ToLocalChecked()
5372 ->Int32Value(context.local())
5373 .FromJust());
5374 CHECK_EQ(19, a4->Get(context.local(), 2)
5375 .ToLocalChecked()
5376 ->Int32Value(context.local())
5377 .FromJust());
5378 CHECK_EQ(20, a4->Get(context.local(), 3)
5379 .ToLocalChecked()
5380 ->Int32Value(context.local())
5381 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005382}
5383
5384
5385THREADED_TEST(FunctionCall) {
Steve Blocka7e24c12009-10-30 11:49:00 +00005386 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005387 v8::Isolate* isolate = context->GetIsolate();
5388 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00005389 CompileRun(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005390 "function Foo() {"
5391 " var result = [];"
5392 " for (var i = 0; i < arguments.length; i++) {"
5393 " result.push(arguments[i]);"
5394 " }"
5395 " return result;"
5396 "}"
5397 "function ReturnThisSloppy() {"
5398 " return this;"
5399 "}"
5400 "function ReturnThisStrict() {"
5401 " 'use strict';"
5402 " return this;"
5403 "}");
5404 Local<Function> Foo = Local<Function>::Cast(
5405 context->Global()->Get(context.local(), v8_str("Foo")).ToLocalChecked());
5406 Local<Function> ReturnThisSloppy = Local<Function>::Cast(
5407 context->Global()
5408 ->Get(context.local(), v8_str("ReturnThisSloppy"))
5409 .ToLocalChecked());
5410 Local<Function> ReturnThisStrict = Local<Function>::Cast(
5411 context->Global()
5412 ->Get(context.local(), v8_str("ReturnThisStrict"))
5413 .ToLocalChecked());
Steve Blocka7e24c12009-10-30 11:49:00 +00005414
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005415 v8::Local<Value>* args0 = NULL;
5416 Local<v8::Array> a0 = Local<v8::Array>::Cast(
5417 Foo->Call(context.local(), Foo, 0, args0).ToLocalChecked());
5418 CHECK_EQ(0u, a0->Length());
Steve Blocka7e24c12009-10-30 11:49:00 +00005419
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005420 v8::Local<Value> args1[] = {v8_num(1.1)};
5421 Local<v8::Array> a1 = Local<v8::Array>::Cast(
5422 Foo->Call(context.local(), Foo, 1, args1).ToLocalChecked());
5423 CHECK_EQ(1u, a1->Length());
5424 CHECK_EQ(1.1, a1->Get(context.local(), v8::Integer::New(isolate, 0))
5425 .ToLocalChecked()
5426 ->NumberValue(context.local())
5427 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005428
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005429 v8::Local<Value> args2[] = {v8_num(2.2), v8_num(3.3)};
5430 Local<v8::Array> a2 = Local<v8::Array>::Cast(
5431 Foo->Call(context.local(), Foo, 2, args2).ToLocalChecked());
5432 CHECK_EQ(2u, a2->Length());
5433 CHECK_EQ(2.2, a2->Get(context.local(), v8::Integer::New(isolate, 0))
5434 .ToLocalChecked()
5435 ->NumberValue(context.local())
5436 .FromJust());
5437 CHECK_EQ(3.3, a2->Get(context.local(), v8::Integer::New(isolate, 1))
5438 .ToLocalChecked()
5439 ->NumberValue(context.local())
5440 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005441
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005442 v8::Local<Value> args3[] = {v8_num(4.4), v8_num(5.5), v8_num(6.6)};
5443 Local<v8::Array> a3 = Local<v8::Array>::Cast(
5444 Foo->Call(context.local(), Foo, 3, args3).ToLocalChecked());
5445 CHECK_EQ(3u, a3->Length());
5446 CHECK_EQ(4.4, a3->Get(context.local(), v8::Integer::New(isolate, 0))
5447 .ToLocalChecked()
5448 ->NumberValue(context.local())
5449 .FromJust());
5450 CHECK_EQ(5.5, a3->Get(context.local(), v8::Integer::New(isolate, 1))
5451 .ToLocalChecked()
5452 ->NumberValue(context.local())
5453 .FromJust());
5454 CHECK_EQ(6.6, a3->Get(context.local(), v8::Integer::New(isolate, 2))
5455 .ToLocalChecked()
5456 ->NumberValue(context.local())
5457 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005458
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005459 v8::Local<Value> args4[] = {v8_num(7.7), v8_num(8.8), v8_num(9.9),
5460 v8_num(10.11)};
5461 Local<v8::Array> a4 = Local<v8::Array>::Cast(
5462 Foo->Call(context.local(), Foo, 4, args4).ToLocalChecked());
5463 CHECK_EQ(4u, a4->Length());
5464 CHECK_EQ(7.7, a4->Get(context.local(), v8::Integer::New(isolate, 0))
5465 .ToLocalChecked()
5466 ->NumberValue(context.local())
5467 .FromJust());
5468 CHECK_EQ(8.8, a4->Get(context.local(), v8::Integer::New(isolate, 1))
5469 .ToLocalChecked()
5470 ->NumberValue(context.local())
5471 .FromJust());
5472 CHECK_EQ(9.9, a4->Get(context.local(), v8::Integer::New(isolate, 2))
5473 .ToLocalChecked()
5474 ->NumberValue(context.local())
5475 .FromJust());
5476 CHECK_EQ(10.11, a4->Get(context.local(), v8::Integer::New(isolate, 3))
5477 .ToLocalChecked()
5478 ->NumberValue(context.local())
5479 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005480
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005481 Local<v8::Value> r1 =
5482 ReturnThisSloppy->Call(context.local(), v8::Undefined(isolate), 0, NULL)
5483 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005484 CHECK(r1->StrictEquals(context->Global()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005485 Local<v8::Value> r2 =
5486 ReturnThisSloppy->Call(context.local(), v8::Null(isolate), 0, NULL)
5487 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005488 CHECK(r2->StrictEquals(context->Global()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005489 Local<v8::Value> r3 =
5490 ReturnThisSloppy->Call(context.local(), v8_num(42), 0, NULL)
5491 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005492 CHECK(r3->IsNumberObject());
5493 CHECK_EQ(42.0, r3.As<v8::NumberObject>()->ValueOf());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005494 Local<v8::Value> r4 =
5495 ReturnThisSloppy->Call(context.local(), v8_str("hello"), 0, NULL)
5496 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005497 CHECK(r4->IsStringObject());
5498 CHECK(r4.As<v8::StringObject>()->ValueOf()->StrictEquals(v8_str("hello")));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005499 Local<v8::Value> r5 =
5500 ReturnThisSloppy->Call(context.local(), v8::True(isolate), 0, NULL)
5501 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005502 CHECK(r5->IsBooleanObject());
5503 CHECK(r5.As<v8::BooleanObject>()->ValueOf());
Steve Blocka7e24c12009-10-30 11:49:00 +00005504
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005505 Local<v8::Value> r6 =
5506 ReturnThisStrict->Call(context.local(), v8::Undefined(isolate), 0, NULL)
5507 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005508 CHECK(r6->IsUndefined());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005509 Local<v8::Value> r7 =
5510 ReturnThisStrict->Call(context.local(), v8::Null(isolate), 0, NULL)
5511 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005512 CHECK(r7->IsNull());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005513 Local<v8::Value> r8 =
5514 ReturnThisStrict->Call(context.local(), v8_num(42), 0, NULL)
5515 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005516 CHECK(r8->StrictEquals(v8_num(42)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005517 Local<v8::Value> r9 =
5518 ReturnThisStrict->Call(context.local(), v8_str("hello"), 0, NULL)
5519 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005520 CHECK(r9->StrictEquals(v8_str("hello")));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005521 Local<v8::Value> r10 =
5522 ReturnThisStrict->Call(context.local(), v8::True(isolate), 0, NULL)
5523 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005524 CHECK(r10->StrictEquals(v8::True(isolate)));
Steve Blocka7e24c12009-10-30 11:49:00 +00005525}
5526
5527
5528THREADED_TEST(ConstructCall) {
Steve Blocka7e24c12009-10-30 11:49:00 +00005529 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005530 v8::Isolate* isolate = context->GetIsolate();
5531 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00005532 CompileRun(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005533 "function Foo() {"
5534 " var result = [];"
5535 " for (var i = 0; i < arguments.length; i++) {"
5536 " result.push(arguments[i]);"
5537 " }"
5538 " return result;"
5539 "}");
5540 Local<Function> Foo = Local<Function>::Cast(
5541 context->Global()->Get(context.local(), v8_str("Foo")).ToLocalChecked());
Steve Blocka7e24c12009-10-30 11:49:00 +00005542
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005543 v8::Local<Value>* args0 = NULL;
5544 Local<v8::Array> a0 = Local<v8::Array>::Cast(
5545 Foo->NewInstance(context.local(), 0, args0).ToLocalChecked());
5546 CHECK_EQ(0u, a0->Length());
Steve Blocka7e24c12009-10-30 11:49:00 +00005547
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005548 v8::Local<Value> args1[] = {v8_num(1.1)};
5549 Local<v8::Array> a1 = Local<v8::Array>::Cast(
5550 Foo->NewInstance(context.local(), 1, args1).ToLocalChecked());
5551 CHECK_EQ(1u, a1->Length());
5552 CHECK_EQ(1.1, a1->Get(context.local(), v8::Integer::New(isolate, 0))
5553 .ToLocalChecked()
5554 ->NumberValue(context.local())
5555 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005556
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005557 v8::Local<Value> args2[] = {v8_num(2.2), v8_num(3.3)};
5558 Local<v8::Array> a2 = Local<v8::Array>::Cast(
5559 Foo->NewInstance(context.local(), 2, args2).ToLocalChecked());
5560 CHECK_EQ(2u, a2->Length());
5561 CHECK_EQ(2.2, a2->Get(context.local(), v8::Integer::New(isolate, 0))
5562 .ToLocalChecked()
5563 ->NumberValue(context.local())
5564 .FromJust());
5565 CHECK_EQ(3.3, a2->Get(context.local(), v8::Integer::New(isolate, 1))
5566 .ToLocalChecked()
5567 ->NumberValue(context.local())
5568 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005569
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005570 v8::Local<Value> args3[] = {v8_num(4.4), v8_num(5.5), v8_num(6.6)};
5571 Local<v8::Array> a3 = Local<v8::Array>::Cast(
5572 Foo->NewInstance(context.local(), 3, args3).ToLocalChecked());
5573 CHECK_EQ(3u, a3->Length());
5574 CHECK_EQ(4.4, a3->Get(context.local(), v8::Integer::New(isolate, 0))
5575 .ToLocalChecked()
5576 ->NumberValue(context.local())
5577 .FromJust());
5578 CHECK_EQ(5.5, a3->Get(context.local(), v8::Integer::New(isolate, 1))
5579 .ToLocalChecked()
5580 ->NumberValue(context.local())
5581 .FromJust());
5582 CHECK_EQ(6.6, a3->Get(context.local(), v8::Integer::New(isolate, 2))
5583 .ToLocalChecked()
5584 ->NumberValue(context.local())
5585 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005586
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005587 v8::Local<Value> args4[] = {v8_num(7.7), v8_num(8.8), v8_num(9.9),
5588 v8_num(10.11)};
5589 Local<v8::Array> a4 = Local<v8::Array>::Cast(
5590 Foo->NewInstance(context.local(), 4, args4).ToLocalChecked());
5591 CHECK_EQ(4u, a4->Length());
5592 CHECK_EQ(7.7, a4->Get(context.local(), v8::Integer::New(isolate, 0))
5593 .ToLocalChecked()
5594 ->NumberValue(context.local())
5595 .FromJust());
5596 CHECK_EQ(8.8, a4->Get(context.local(), v8::Integer::New(isolate, 1))
5597 .ToLocalChecked()
5598 ->NumberValue(context.local())
5599 .FromJust());
5600 CHECK_EQ(9.9, a4->Get(context.local(), v8::Integer::New(isolate, 2))
5601 .ToLocalChecked()
5602 ->NumberValue(context.local())
5603 .FromJust());
5604 CHECK_EQ(10.11, a4->Get(context.local(), v8::Integer::New(isolate, 3))
5605 .ToLocalChecked()
5606 ->NumberValue(context.local())
5607 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005608}
5609
5610
Steve Block6ded16b2010-05-10 14:33:55 +01005611THREADED_TEST(ConversionNumber) {
Steve Block6ded16b2010-05-10 14:33:55 +01005612 LocalContext env;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005613 v8::Isolate* isolate = env->GetIsolate();
5614 v8::HandleScope scope(isolate);
Steve Block6ded16b2010-05-10 14:33:55 +01005615 // Very large number.
5616 CompileRun("var obj = Math.pow(2,32) * 1237;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005617 Local<Value> obj =
5618 env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
5619 CHECK_EQ(5312874545152.0,
5620 obj->ToNumber(env.local()).ToLocalChecked()->Value());
5621 CHECK_EQ(0, obj->ToInt32(env.local()).ToLocalChecked()->Value());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005622 CHECK(0u ==
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005623 obj->ToUint32(env.local())
5624 .ToLocalChecked()
5625 ->Value()); // NOLINT - no CHECK_EQ for unsigned.
Steve Block6ded16b2010-05-10 14:33:55 +01005626 // Large number.
5627 CompileRun("var obj = -1234567890123;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005628 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
5629 CHECK_EQ(-1234567890123.0,
5630 obj->ToNumber(env.local()).ToLocalChecked()->Value());
5631 CHECK_EQ(-1912276171, obj->ToInt32(env.local()).ToLocalChecked()->Value());
5632 CHECK(2382691125u ==
5633 obj->ToUint32(env.local()).ToLocalChecked()->Value()); // NOLINT
Steve Block6ded16b2010-05-10 14:33:55 +01005634 // Small positive integer.
5635 CompileRun("var obj = 42;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005636 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
5637 CHECK_EQ(42.0, obj->ToNumber(env.local()).ToLocalChecked()->Value());
5638 CHECK_EQ(42, obj->ToInt32(env.local()).ToLocalChecked()->Value());
5639 CHECK(42u == obj->ToUint32(env.local()).ToLocalChecked()->Value()); // NOLINT
Steve Block6ded16b2010-05-10 14:33:55 +01005640 // Negative integer.
5641 CompileRun("var obj = -37;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005642 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
5643 CHECK_EQ(-37.0, obj->ToNumber(env.local()).ToLocalChecked()->Value());
5644 CHECK_EQ(-37, obj->ToInt32(env.local()).ToLocalChecked()->Value());
5645 CHECK(4294967259u ==
5646 obj->ToUint32(env.local()).ToLocalChecked()->Value()); // NOLINT
Steve Block6ded16b2010-05-10 14:33:55 +01005647 // Positive non-int32 integer.
5648 CompileRun("var obj = 0x81234567;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005649 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
5650 CHECK_EQ(2166572391.0, obj->ToNumber(env.local()).ToLocalChecked()->Value());
5651 CHECK_EQ(-2128394905, obj->ToInt32(env.local()).ToLocalChecked()->Value());
5652 CHECK(2166572391u ==
5653 obj->ToUint32(env.local()).ToLocalChecked()->Value()); // NOLINT
Steve Block6ded16b2010-05-10 14:33:55 +01005654 // Fraction.
5655 CompileRun("var obj = 42.3;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005656 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
5657 CHECK_EQ(42.3, obj->ToNumber(env.local()).ToLocalChecked()->Value());
5658 CHECK_EQ(42, obj->ToInt32(env.local()).ToLocalChecked()->Value());
5659 CHECK(42u == obj->ToUint32(env.local()).ToLocalChecked()->Value()); // NOLINT
Steve Block6ded16b2010-05-10 14:33:55 +01005660 // Large negative fraction.
5661 CompileRun("var obj = -5726623061.75;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005662 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
5663 CHECK_EQ(-5726623061.75,
5664 obj->ToNumber(env.local()).ToLocalChecked()->Value());
5665 CHECK_EQ(-1431655765, obj->ToInt32(env.local()).ToLocalChecked()->Value());
5666 CHECK(2863311531u ==
5667 obj->ToUint32(env.local()).ToLocalChecked()->Value()); // NOLINT
Steve Block6ded16b2010-05-10 14:33:55 +01005668}
5669
5670
5671THREADED_TEST(isNumberType) {
Steve Block6ded16b2010-05-10 14:33:55 +01005672 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005673 v8::HandleScope scope(env->GetIsolate());
Steve Block6ded16b2010-05-10 14:33:55 +01005674 // Very large number.
5675 CompileRun("var obj = Math.pow(2,32) * 1237;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005676 Local<Value> obj =
5677 env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
Steve Block6ded16b2010-05-10 14:33:55 +01005678 CHECK(!obj->IsInt32());
5679 CHECK(!obj->IsUint32());
5680 // Large negative number.
5681 CompileRun("var obj = -1234567890123;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005682 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
Steve Block6ded16b2010-05-10 14:33:55 +01005683 CHECK(!obj->IsInt32());
5684 CHECK(!obj->IsUint32());
5685 // Small positive integer.
5686 CompileRun("var obj = 42;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005687 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
Steve Block6ded16b2010-05-10 14:33:55 +01005688 CHECK(obj->IsInt32());
5689 CHECK(obj->IsUint32());
5690 // Negative integer.
5691 CompileRun("var obj = -37;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005692 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
Steve Block6ded16b2010-05-10 14:33:55 +01005693 CHECK(obj->IsInt32());
5694 CHECK(!obj->IsUint32());
5695 // Positive non-int32 integer.
5696 CompileRun("var obj = 0x81234567;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005697 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
Steve Block6ded16b2010-05-10 14:33:55 +01005698 CHECK(!obj->IsInt32());
5699 CHECK(obj->IsUint32());
5700 // Fraction.
5701 CompileRun("var obj = 42.3;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005702 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
Steve Block6ded16b2010-05-10 14:33:55 +01005703 CHECK(!obj->IsInt32());
5704 CHECK(!obj->IsUint32());
5705 // Large negative fraction.
5706 CompileRun("var obj = -5726623061.75;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005707 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
Steve Block6ded16b2010-05-10 14:33:55 +01005708 CHECK(!obj->IsInt32());
5709 CHECK(!obj->IsUint32());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005710 // Positive zero
5711 CompileRun("var obj = 0.0;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005712 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005713 CHECK(obj->IsInt32());
5714 CHECK(obj->IsUint32());
5715 // Positive zero
5716 CompileRun("var obj = -0.0;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005717 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005718 CHECK(!obj->IsInt32());
5719 CHECK(!obj->IsUint32());
Steve Block6ded16b2010-05-10 14:33:55 +01005720}
5721
5722
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005723static void CheckUncle(v8::TryCatch* try_catch) {
5724 CHECK(try_catch->HasCaught());
5725 String::Utf8Value str_value(try_catch->Exception());
5726 CHECK_EQ(0, strcmp(*str_value, "uncle?"));
5727 try_catch->Reset();
5728}
5729
5730
Steve Blocka7e24c12009-10-30 11:49:00 +00005731THREADED_TEST(ConversionException) {
Steve Blocka7e24c12009-10-30 11:49:00 +00005732 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005733 v8::Isolate* isolate = env->GetIsolate();
5734 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00005735 CompileRun(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005736 "function TestClass() { };"
5737 "TestClass.prototype.toString = function () { throw 'uncle?'; };"
5738 "var obj = new TestClass();");
5739 Local<Value> obj =
5740 env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00005741
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005742 v8::TryCatch try_catch(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00005743
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005744 CHECK(obj->ToString(env.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00005745 CheckUncle(&try_catch);
5746
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005747 CHECK(obj->ToNumber(env.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00005748 CheckUncle(&try_catch);
5749
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005750 CHECK(obj->ToInteger(env.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00005751 CheckUncle(&try_catch);
5752
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005753 CHECK(obj->ToUint32(env.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00005754 CheckUncle(&try_catch);
5755
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005756 CHECK(obj->ToInt32(env.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00005757 CheckUncle(&try_catch);
5758
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005759 CHECK(v8::Undefined(isolate)->ToObject(env.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00005760 CHECK(try_catch.HasCaught());
5761 try_catch.Reset();
5762
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005763 CHECK(obj->Int32Value(env.local()).IsNothing());
Steve Blocka7e24c12009-10-30 11:49:00 +00005764 CheckUncle(&try_catch);
5765
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005766 CHECK(obj->Uint32Value(env.local()).IsNothing());
Steve Blocka7e24c12009-10-30 11:49:00 +00005767 CheckUncle(&try_catch);
5768
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005769 CHECK(obj->NumberValue(env.local()).IsNothing());
Steve Blocka7e24c12009-10-30 11:49:00 +00005770 CheckUncle(&try_catch);
5771
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005772 CHECK(obj->IntegerValue(env.local()).IsNothing());
Steve Blocka7e24c12009-10-30 11:49:00 +00005773 CheckUncle(&try_catch);
5774}
5775
5776
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005777void ThrowFromC(const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +00005778 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005779 args.GetIsolate()->ThrowException(v8_str("konto"));
Steve Blocka7e24c12009-10-30 11:49:00 +00005780}
5781
5782
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005783void CCatcher(const v8::FunctionCallbackInfo<v8::Value>& args) {
5784 if (args.Length() < 1) {
5785 args.GetReturnValue().Set(false);
5786 return;
5787 }
5788 v8::HandleScope scope(args.GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005789 v8::TryCatch try_catch(args.GetIsolate());
5790 Local<Value> result =
5791 CompileRun(args[0]
5792 ->ToString(args.GetIsolate()->GetCurrentContext())
5793 .ToLocalChecked());
Steve Blocka7e24c12009-10-30 11:49:00 +00005794 CHECK(!try_catch.HasCaught() || result.IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005795 args.GetReturnValue().Set(try_catch.HasCaught());
Steve Blocka7e24c12009-10-30 11:49:00 +00005796}
5797
5798
5799THREADED_TEST(APICatch) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005800 v8::Isolate* isolate = CcTest::isolate();
5801 v8::HandleScope scope(isolate);
5802 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00005803 templ->Set(v8_str("ThrowFromC"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005804 v8::FunctionTemplate::New(isolate, ThrowFromC));
Steve Blocka7e24c12009-10-30 11:49:00 +00005805 LocalContext context(0, templ);
5806 CompileRun(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005807 "var thrown = false;"
5808 "try {"
5809 " ThrowFromC();"
5810 "} catch (e) {"
5811 " thrown = true;"
5812 "}");
5813 Local<Value> thrown = context->Global()
5814 ->Get(context.local(), v8_str("thrown"))
5815 .ToLocalChecked();
5816 CHECK(thrown->BooleanValue(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005817}
5818
5819
5820THREADED_TEST(APIThrowTryCatch) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005821 v8::Isolate* isolate = CcTest::isolate();
5822 v8::HandleScope scope(isolate);
5823 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00005824 templ->Set(v8_str("ThrowFromC"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005825 v8::FunctionTemplate::New(isolate, ThrowFromC));
Steve Blocka7e24c12009-10-30 11:49:00 +00005826 LocalContext context(0, templ);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005827 v8::TryCatch try_catch(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00005828 CompileRun("ThrowFromC();");
5829 CHECK(try_catch.HasCaught());
5830}
5831
5832
5833// Test that a try-finally block doesn't shadow a try-catch block
5834// when setting up an external handler.
5835//
5836// BUG(271): Some of the exception propagation does not work on the
5837// ARM simulator because the simulator separates the C++ stack and the
5838// JS stack. This test therefore fails on the simulator. The test is
5839// not threaded to allow the threading tests to run on the simulator.
5840TEST(TryCatchInTryFinally) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005841 v8::Isolate* isolate = CcTest::isolate();
5842 v8::HandleScope scope(isolate);
5843 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005844 templ->Set(v8_str("CCatcher"), v8::FunctionTemplate::New(isolate, CCatcher));
Steve Blocka7e24c12009-10-30 11:49:00 +00005845 LocalContext context(0, templ);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005846 Local<Value> result = CompileRun(
5847 "try {"
5848 " try {"
5849 " CCatcher('throw 7;');"
5850 " } finally {"
5851 " }"
5852 "} catch (e) {"
5853 "}");
Steve Blocka7e24c12009-10-30 11:49:00 +00005854 CHECK(result->IsTrue());
5855}
5856
5857
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005858static void check_custom_error_tostring(v8::Local<v8::Message> message,
5859 v8::Local<v8::Value> data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005860 const char* uncaught_error = "Uncaught MyError toString";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005861 CHECK(message->Get()
5862 ->Equals(CcTest::isolate()->GetCurrentContext(),
5863 v8_str(uncaught_error))
5864 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005865}
5866
5867
5868TEST(CustomErrorToString) {
5869 LocalContext context;
5870 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005871 context->GetIsolate()->AddMessageListener(check_custom_error_tostring);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005872 CompileRun(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005873 "function MyError(name, message) { "
5874 " this.name = name; "
5875 " this.message = message; "
5876 "} "
5877 "MyError.prototype = Object.create(Error.prototype); "
5878 "MyError.prototype.toString = function() { "
5879 " return 'MyError toString'; "
5880 "}; "
5881 "throw new MyError('my name', 'my message'); ");
5882 context->GetIsolate()->RemoveMessageListeners(check_custom_error_tostring);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005883}
5884
5885
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005886static void check_custom_error_message(v8::Local<v8::Message> message,
5887 v8::Local<v8::Value> data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005888 const char* uncaught_error = "Uncaught MyError: my message";
5889 printf("%s\n", *v8::String::Utf8Value(message->Get()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005890 CHECK(message->Get()
5891 ->Equals(CcTest::isolate()->GetCurrentContext(),
5892 v8_str(uncaught_error))
5893 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005894}
5895
5896
5897TEST(CustomErrorMessage) {
5898 LocalContext context;
5899 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005900 context->GetIsolate()->AddMessageListener(check_custom_error_message);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005901
5902 // Handlebars.
5903 CompileRun(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005904 "function MyError(msg) { "
5905 " this.name = 'MyError'; "
5906 " this.message = msg; "
5907 "} "
5908 "MyError.prototype = new Error(); "
5909 "throw new MyError('my message'); ");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005910
5911 // Closure.
5912 CompileRun(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005913 "function MyError(msg) { "
5914 " this.name = 'MyError'; "
5915 " this.message = msg; "
5916 "} "
5917 "inherits = function(childCtor, parentCtor) { "
5918 " function tempCtor() {}; "
5919 " tempCtor.prototype = parentCtor.prototype; "
5920 " childCtor.superClass_ = parentCtor.prototype; "
5921 " childCtor.prototype = new tempCtor(); "
5922 " childCtor.prototype.constructor = childCtor; "
5923 "}; "
5924 "inherits(MyError, Error); "
5925 "throw new MyError('my message'); ");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005926
5927 // Object.create.
5928 CompileRun(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005929 "function MyError(msg) { "
5930 " this.name = 'MyError'; "
5931 " this.message = msg; "
5932 "} "
5933 "MyError.prototype = Object.create(Error.prototype); "
5934 "throw new MyError('my message'); ");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005935
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005936 context->GetIsolate()->RemoveMessageListeners(check_custom_error_message);
Ben Murdochb8e0da22011-05-16 14:20:40 +01005937}
5938
5939
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005940static void check_custom_rethrowing_message(v8::Local<v8::Message> message,
5941 v8::Local<v8::Value> data) {
5942 const char* uncaught_error = "Uncaught exception";
5943 CHECK(message->Get()
5944 ->Equals(CcTest::isolate()->GetCurrentContext(),
5945 v8_str(uncaught_error))
5946 .FromJust());
5947}
5948
5949
5950TEST(CustomErrorRethrowsOnToString) {
5951 LocalContext context;
5952 v8::HandleScope scope(context->GetIsolate());
5953 context->GetIsolate()->AddMessageListener(check_custom_rethrowing_message);
5954
5955 CompileRun(
5956 "var e = { toString: function() { throw e; } };"
5957 "try { throw e; } finally {}");
5958
5959 context->GetIsolate()->RemoveMessageListeners(
5960 check_custom_rethrowing_message);
5961}
5962
5963
5964static void receive_message(v8::Local<v8::Message> message,
5965 v8::Local<v8::Value> data) {
Steve Blocka7e24c12009-10-30 11:49:00 +00005966 message->Get();
5967 message_received = true;
5968}
5969
5970
5971TEST(APIThrowMessage) {
5972 message_received = false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005973 v8::Isolate* isolate = CcTest::isolate();
5974 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005975 isolate->AddMessageListener(receive_message);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005976 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00005977 templ->Set(v8_str("ThrowFromC"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005978 v8::FunctionTemplate::New(isolate, ThrowFromC));
Steve Blocka7e24c12009-10-30 11:49:00 +00005979 LocalContext context(0, templ);
5980 CompileRun("ThrowFromC();");
5981 CHECK(message_received);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005982 isolate->RemoveMessageListeners(receive_message);
Steve Blocka7e24c12009-10-30 11:49:00 +00005983}
5984
5985
5986TEST(APIThrowMessageAndVerboseTryCatch) {
5987 message_received = false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005988 v8::Isolate* isolate = CcTest::isolate();
5989 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005990 isolate->AddMessageListener(receive_message);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005991 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00005992 templ->Set(v8_str("ThrowFromC"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005993 v8::FunctionTemplate::New(isolate, ThrowFromC));
Steve Blocka7e24c12009-10-30 11:49:00 +00005994 LocalContext context(0, templ);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005995 v8::TryCatch try_catch(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00005996 try_catch.SetVerbose(true);
5997 Local<Value> result = CompileRun("ThrowFromC();");
5998 CHECK(try_catch.HasCaught());
5999 CHECK(result.IsEmpty());
6000 CHECK(message_received);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006001 isolate->RemoveMessageListeners(receive_message);
Steve Blocka7e24c12009-10-30 11:49:00 +00006002}
6003
6004
Ben Murdoch8b112d22011-06-08 16:22:53 +01006005TEST(APIStackOverflowAndVerboseTryCatch) {
6006 message_received = false;
Ben Murdoch8b112d22011-06-08 16:22:53 +01006007 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006008 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006009 context->GetIsolate()->AddMessageListener(receive_message);
6010 v8::TryCatch try_catch(context->GetIsolate());
Ben Murdoch8b112d22011-06-08 16:22:53 +01006011 try_catch.SetVerbose(true);
6012 Local<Value> result = CompileRun("function foo() { foo(); } foo();");
6013 CHECK(try_catch.HasCaught());
6014 CHECK(result.IsEmpty());
6015 CHECK(message_received);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006016 context->GetIsolate()->RemoveMessageListeners(receive_message);
Ben Murdoch8b112d22011-06-08 16:22:53 +01006017}
6018
6019
Steve Blocka7e24c12009-10-30 11:49:00 +00006020THREADED_TEST(ExternalScriptException) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006021 v8::Isolate* isolate = CcTest::isolate();
6022 v8::HandleScope scope(isolate);
6023 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00006024 templ->Set(v8_str("ThrowFromC"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006025 v8::FunctionTemplate::New(isolate, ThrowFromC));
Steve Blocka7e24c12009-10-30 11:49:00 +00006026 LocalContext context(0, templ);
6027
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006028 v8::TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006029 Local<Value> result = CompileRun("ThrowFromC(); throw 'panama';");
Steve Blocka7e24c12009-10-30 11:49:00 +00006030 CHECK(result.IsEmpty());
6031 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006032 String::Utf8Value exception_value(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006033 CHECK_EQ(0, strcmp("konto", *exception_value));
Steve Blocka7e24c12009-10-30 11:49:00 +00006034}
6035
6036
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006037void CThrowCountDown(const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +00006038 ApiTestFuzzer::Fuzz();
6039 CHECK_EQ(4, args.Length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006040 v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
6041 int count = args[0]->Int32Value(context).FromJust();
6042 int cInterval = args[2]->Int32Value(context).FromJust();
Steve Blocka7e24c12009-10-30 11:49:00 +00006043 if (count == 0) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006044 args.GetIsolate()->ThrowException(v8_str("FromC"));
6045 return;
Steve Blocka7e24c12009-10-30 11:49:00 +00006046 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006047 Local<v8::Object> global = context->Global();
6048 Local<Value> fun =
6049 global->Get(context, v8_str("JSThrowCountDown")).ToLocalChecked();
6050 v8::Local<Value> argv[] = {v8_num(count - 1), args[1], args[2], args[3]};
Steve Blocka7e24c12009-10-30 11:49:00 +00006051 if (count % cInterval == 0) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006052 v8::TryCatch try_catch(args.GetIsolate());
6053 Local<Value> result = fun.As<Function>()
6054 ->Call(context, global, 4, argv)
6055 .FromMaybe(Local<Value>());
6056 int expected = args[3]->Int32Value(context).FromJust();
Steve Blocka7e24c12009-10-30 11:49:00 +00006057 if (try_catch.HasCaught()) {
6058 CHECK_EQ(expected, count);
6059 CHECK(result.IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006060 CHECK(!CcTest::i_isolate()->has_scheduled_exception());
Steve Blocka7e24c12009-10-30 11:49:00 +00006061 } else {
6062 CHECK_NE(expected, count);
6063 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006064 args.GetReturnValue().Set(result);
6065 return;
Steve Blocka7e24c12009-10-30 11:49:00 +00006066 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006067 args.GetReturnValue().Set(fun.As<Function>()
6068 ->Call(context, global, 4, argv)
6069 .FromMaybe(v8::Local<v8::Value>()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006070 return;
Steve Blocka7e24c12009-10-30 11:49:00 +00006071 }
6072 }
6073}
6074
6075
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006076void JSCheck(const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +00006077 ApiTestFuzzer::Fuzz();
6078 CHECK_EQ(3, args.Length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006079 v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
6080 bool equality = args[0]->BooleanValue(context).FromJust();
6081 int count = args[1]->Int32Value(context).FromJust();
6082 int expected = args[2]->Int32Value(context).FromJust();
Steve Blocka7e24c12009-10-30 11:49:00 +00006083 if (equality) {
6084 CHECK_EQ(count, expected);
6085 } else {
6086 CHECK_NE(count, expected);
6087 }
Steve Blocka7e24c12009-10-30 11:49:00 +00006088}
6089
6090
6091THREADED_TEST(EvalInTryFinally) {
Steve Blocka7e24c12009-10-30 11:49:00 +00006092 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006093 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006094 v8::TryCatch try_catch(context->GetIsolate());
6095 CompileRun(
6096 "(function() {"
6097 " try {"
6098 " eval('asldkf (*&^&*^');"
6099 " } finally {"
6100 " return;"
6101 " }"
6102 "})()");
Steve Blocka7e24c12009-10-30 11:49:00 +00006103 CHECK(!try_catch.HasCaught());
6104}
6105
6106
6107// This test works by making a stack of alternating JavaScript and C
6108// activations. These activations set up exception handlers with regular
6109// intervals, one interval for C activations and another for JavaScript
6110// activations. When enough activations have been created an exception is
6111// thrown and we check that the right activation catches the exception and that
6112// no other activations do. The right activation is always the topmost one with
6113// a handler, regardless of whether it is in JavaScript or C.
6114//
6115// The notation used to describe a test case looks like this:
6116//
6117// *JS[4] *C[3] @JS[2] C[1] JS[0]
6118//
6119// Each entry is an activation, either JS or C. The index is the count at that
6120// level. Stars identify activations with exception handlers, the @ identifies
6121// the exception handler that should catch the exception.
6122//
6123// BUG(271): Some of the exception propagation does not work on the
6124// ARM simulator because the simulator separates the C++ stack and the
6125// JS stack. This test therefore fails on the simulator. The test is
6126// not threaded to allow the threading tests to run on the simulator.
6127TEST(ExceptionOrder) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006128 v8::Isolate* isolate = CcTest::isolate();
6129 v8::HandleScope scope(isolate);
6130 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6131 templ->Set(v8_str("check"), v8::FunctionTemplate::New(isolate, JSCheck));
Steve Blocka7e24c12009-10-30 11:49:00 +00006132 templ->Set(v8_str("CThrowCountDown"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006133 v8::FunctionTemplate::New(isolate, CThrowCountDown));
Steve Blocka7e24c12009-10-30 11:49:00 +00006134 LocalContext context(0, templ);
6135 CompileRun(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006136 "function JSThrowCountDown(count, jsInterval, cInterval, expected) {"
6137 " if (count == 0) throw 'FromJS';"
6138 " if (count % jsInterval == 0) {"
6139 " try {"
6140 " var value = CThrowCountDown(count - 1,"
6141 " jsInterval,"
6142 " cInterval,"
6143 " expected);"
6144 " check(false, count, expected);"
6145 " return value;"
6146 " } catch (e) {"
6147 " check(true, count, expected);"
6148 " }"
6149 " } else {"
6150 " return CThrowCountDown(count - 1, jsInterval, cInterval, expected);"
6151 " }"
6152 "}");
6153 Local<Function> fun = Local<Function>::Cast(
6154 context->Global()
6155 ->Get(context.local(), v8_str("JSThrowCountDown"))
6156 .ToLocalChecked());
Steve Blocka7e24c12009-10-30 11:49:00 +00006157
6158 const int argc = 4;
6159 // count jsInterval cInterval expected
6160
6161 // *JS[4] *C[3] @JS[2] C[1] JS[0]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006162 v8::Local<Value> a0[argc] = {v8_num(4), v8_num(2), v8_num(3), v8_num(2)};
6163 fun->Call(context.local(), fun, argc, a0).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00006164
6165 // JS[5] *C[4] JS[3] @C[2] JS[1] C[0]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006166 v8::Local<Value> a1[argc] = {v8_num(5), v8_num(6), v8_num(1), v8_num(2)};
6167 fun->Call(context.local(), fun, argc, a1).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00006168
6169 // JS[6] @C[5] JS[4] C[3] JS[2] C[1] JS[0]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006170 v8::Local<Value> a2[argc] = {v8_num(6), v8_num(7), v8_num(5), v8_num(5)};
6171 fun->Call(context.local(), fun, argc, a2).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00006172
6173 // @JS[6] C[5] JS[4] C[3] JS[2] C[1] JS[0]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006174 v8::Local<Value> a3[argc] = {v8_num(6), v8_num(6), v8_num(7), v8_num(6)};
6175 fun->Call(context.local(), fun, argc, a3).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00006176
6177 // JS[6] *C[5] @JS[4] C[3] JS[2] C[1] JS[0]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006178 v8::Local<Value> a4[argc] = {v8_num(6), v8_num(4), v8_num(5), v8_num(4)};
6179 fun->Call(context.local(), fun, argc, a4).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00006180
6181 // JS[6] C[5] *JS[4] @C[3] JS[2] C[1] JS[0]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006182 v8::Local<Value> a5[argc] = {v8_num(6), v8_num(4), v8_num(3), v8_num(3)};
6183 fun->Call(context.local(), fun, argc, a5).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00006184}
6185
6186
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006187void ThrowValue(const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +00006188 ApiTestFuzzer::Fuzz();
6189 CHECK_EQ(1, args.Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006190 args.GetIsolate()->ThrowException(args[0]);
Steve Blocka7e24c12009-10-30 11:49:00 +00006191}
6192
6193
6194THREADED_TEST(ThrowValues) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006195 v8::Isolate* isolate = CcTest::isolate();
6196 v8::HandleScope scope(isolate);
6197 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6198 templ->Set(v8_str("Throw"), v8::FunctionTemplate::New(isolate, ThrowValue));
Steve Blocka7e24c12009-10-30 11:49:00 +00006199 LocalContext context(0, templ);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006200 v8::Local<v8::Array> result = v8::Local<v8::Array>::Cast(
6201 CompileRun("function Run(obj) {"
6202 " try {"
6203 " Throw(obj);"
6204 " } catch (e) {"
6205 " return e;"
6206 " }"
6207 " return 'no exception';"
6208 "}"
6209 "[Run('str'), Run(1), Run(0), Run(null), Run(void 0)];"));
6210 CHECK_EQ(5u, result->Length());
6211 CHECK(result->Get(context.local(), v8::Integer::New(isolate, 0))
6212 .ToLocalChecked()
6213 ->IsString());
6214 CHECK(result->Get(context.local(), v8::Integer::New(isolate, 1))
6215 .ToLocalChecked()
6216 ->IsNumber());
6217 CHECK_EQ(1, result->Get(context.local(), v8::Integer::New(isolate, 1))
6218 .ToLocalChecked()
6219 ->Int32Value(context.local())
6220 .FromJust());
6221 CHECK(result->Get(context.local(), v8::Integer::New(isolate, 2))
6222 .ToLocalChecked()
6223 ->IsNumber());
6224 CHECK_EQ(0, result->Get(context.local(), v8::Integer::New(isolate, 2))
6225 .ToLocalChecked()
6226 ->Int32Value(context.local())
6227 .FromJust());
6228 CHECK(result->Get(context.local(), v8::Integer::New(isolate, 3))
6229 .ToLocalChecked()
6230 ->IsNull());
6231 CHECK(result->Get(context.local(), v8::Integer::New(isolate, 4))
6232 .ToLocalChecked()
6233 ->IsUndefined());
Steve Blocka7e24c12009-10-30 11:49:00 +00006234}
6235
6236
6237THREADED_TEST(CatchZero) {
Steve Blocka7e24c12009-10-30 11:49:00 +00006238 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006239 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006240 v8::TryCatch try_catch(context->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00006241 CHECK(!try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006242 CompileRun("throw 10");
Steve Blocka7e24c12009-10-30 11:49:00 +00006243 CHECK(try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006244 CHECK_EQ(10, try_catch.Exception()->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00006245 try_catch.Reset();
6246 CHECK(!try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006247 CompileRun("throw 0");
Steve Blocka7e24c12009-10-30 11:49:00 +00006248 CHECK(try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006249 CHECK_EQ(0, try_catch.Exception()->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00006250}
6251
6252
6253THREADED_TEST(CatchExceptionFromWith) {
Steve Blocka7e24c12009-10-30 11:49:00 +00006254 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006255 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006256 v8::TryCatch try_catch(context->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00006257 CHECK(!try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006258 CompileRun("var o = {}; with (o) { throw 42; }");
Steve Blocka7e24c12009-10-30 11:49:00 +00006259 CHECK(try_catch.HasCaught());
6260}
6261
6262
Ben Murdoche0cee9b2011-05-25 10:26:03 +01006263THREADED_TEST(TryCatchAndFinallyHidingException) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01006264 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006265 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006266 v8::TryCatch try_catch(context->GetIsolate());
Ben Murdoche0cee9b2011-05-25 10:26:03 +01006267 CHECK(!try_catch.HasCaught());
6268 CompileRun("function f(k) { try { this[k]; } finally { return 0; } };");
6269 CompileRun("f({toString: function() { throw 42; }});");
6270 CHECK(!try_catch.HasCaught());
6271}
6272
6273
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006274void WithTryCatch(const v8::FunctionCallbackInfo<v8::Value>& args) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006275 v8::TryCatch try_catch(args.GetIsolate());
Ben Murdoche0cee9b2011-05-25 10:26:03 +01006276}
6277
6278
6279THREADED_TEST(TryCatchAndFinally) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01006280 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006281 v8::Isolate* isolate = context->GetIsolate();
6282 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006283 CHECK(context->Global()
6284 ->Set(context.local(), v8_str("native_with_try_catch"),
6285 v8::FunctionTemplate::New(isolate, WithTryCatch)
6286 ->GetFunction(context.local())
6287 .ToLocalChecked())
6288 .FromJust());
6289 v8::TryCatch try_catch(isolate);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01006290 CHECK(!try_catch.HasCaught());
6291 CompileRun(
6292 "try {\n"
6293 " throw new Error('a');\n"
6294 "} finally {\n"
6295 " native_with_try_catch();\n"
6296 "}\n");
6297 CHECK(try_catch.HasCaught());
6298}
6299
6300
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006301static void TryCatchNested1Helper(int depth) {
6302 if (depth > 0) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006303 v8::TryCatch try_catch(CcTest::isolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006304 try_catch.SetVerbose(true);
6305 TryCatchNested1Helper(depth - 1);
6306 CHECK(try_catch.HasCaught());
6307 try_catch.ReThrow();
6308 } else {
6309 CcTest::isolate()->ThrowException(v8_str("E1"));
6310 }
6311}
6312
6313
6314static void TryCatchNested2Helper(int depth) {
6315 if (depth > 0) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006316 v8::TryCatch try_catch(CcTest::isolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006317 try_catch.SetVerbose(true);
6318 TryCatchNested2Helper(depth - 1);
6319 CHECK(try_catch.HasCaught());
6320 try_catch.ReThrow();
6321 } else {
6322 CompileRun("throw 'E2';");
6323 }
6324}
6325
6326
6327TEST(TryCatchNested) {
6328 v8::V8::Initialize();
Steve Blocka7e24c12009-10-30 11:49:00 +00006329 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006330 v8::HandleScope scope(context->GetIsolate());
6331
6332 {
6333 // Test nested try-catch with a native throw in the end.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006334 v8::TryCatch try_catch(context->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006335 TryCatchNested1Helper(5);
6336 CHECK(try_catch.HasCaught());
6337 CHECK_EQ(0, strcmp(*v8::String::Utf8Value(try_catch.Exception()), "E1"));
6338 }
6339
6340 {
6341 // Test nested try-catch with a JavaScript throw in the end.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006342 v8::TryCatch try_catch(context->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006343 TryCatchNested2Helper(5);
6344 CHECK(try_catch.HasCaught());
6345 CHECK_EQ(0, strcmp(*v8::String::Utf8Value(try_catch.Exception()), "E2"));
6346 }
6347}
6348
6349
6350void TryCatchMixedNestingCheck(v8::TryCatch* try_catch) {
6351 CHECK(try_catch->HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006352 Local<Message> message = try_catch->Message();
6353 Local<Value> resource = message->GetScriptOrigin().ResourceName();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006354 CHECK_EQ(0, strcmp(*v8::String::Utf8Value(resource), "inner"));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006355 CHECK_EQ(0,
6356 strcmp(*v8::String::Utf8Value(message->Get()), "Uncaught Error: a"));
6357 CHECK_EQ(1, message->GetLineNumber(CcTest::isolate()->GetCurrentContext())
6358 .FromJust());
6359 CHECK_EQ(0, message->GetStartColumn(CcTest::isolate()->GetCurrentContext())
6360 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006361}
6362
6363
6364void TryCatchMixedNestingHelper(
6365 const v8::FunctionCallbackInfo<v8::Value>& args) {
6366 ApiTestFuzzer::Fuzz();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006367 v8::TryCatch try_catch(args.GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006368 CompileRunWithOrigin("throw new Error('a');\n", "inner", 0, 0);
6369 CHECK(try_catch.HasCaught());
6370 TryCatchMixedNestingCheck(&try_catch);
6371 try_catch.ReThrow();
6372}
6373
6374
6375// This test ensures that an outer TryCatch in the following situation:
6376// C++/TryCatch -> JS -> C++/TryCatch -> JS w/ SyntaxError
6377// does not clobber the Message object generated for the inner TryCatch.
6378// This exercises the ability of TryCatch.ReThrow() to restore the
6379// inner pending Message before throwing the exception again.
6380TEST(TryCatchMixedNesting) {
6381 v8::Isolate* isolate = CcTest::isolate();
6382 v8::HandleScope scope(isolate);
6383 v8::V8::Initialize();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006384 v8::TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006385 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6386 templ->Set(v8_str("TryCatchMixedNestingHelper"),
6387 v8::FunctionTemplate::New(isolate, TryCatchMixedNestingHelper));
6388 LocalContext context(0, templ);
6389 CompileRunWithOrigin("TryCatchMixedNestingHelper();\n", "outer", 1, 1);
6390 TryCatchMixedNestingCheck(&try_catch);
6391}
6392
6393
6394void TryCatchNativeHelper(const v8::FunctionCallbackInfo<v8::Value>& args) {
6395 ApiTestFuzzer::Fuzz();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006396 v8::TryCatch try_catch(args.GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006397 args.GetIsolate()->ThrowException(v8_str("boom"));
6398 CHECK(try_catch.HasCaught());
6399}
6400
6401
6402TEST(TryCatchNative) {
6403 v8::Isolate* isolate = CcTest::isolate();
6404 v8::HandleScope scope(isolate);
6405 v8::V8::Initialize();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006406 v8::TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006407 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6408 templ->Set(v8_str("TryCatchNativeHelper"),
6409 v8::FunctionTemplate::New(isolate, TryCatchNativeHelper));
6410 LocalContext context(0, templ);
6411 CompileRun("TryCatchNativeHelper();");
6412 CHECK(!try_catch.HasCaught());
6413}
6414
6415
6416void TryCatchNativeResetHelper(
6417 const v8::FunctionCallbackInfo<v8::Value>& args) {
6418 ApiTestFuzzer::Fuzz();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006419 v8::TryCatch try_catch(args.GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006420 args.GetIsolate()->ThrowException(v8_str("boom"));
6421 CHECK(try_catch.HasCaught());
6422 try_catch.Reset();
6423 CHECK(!try_catch.HasCaught());
6424}
6425
6426
6427TEST(TryCatchNativeReset) {
6428 v8::Isolate* isolate = CcTest::isolate();
6429 v8::HandleScope scope(isolate);
6430 v8::V8::Initialize();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006431 v8::TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006432 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6433 templ->Set(v8_str("TryCatchNativeResetHelper"),
6434 v8::FunctionTemplate::New(isolate, TryCatchNativeResetHelper));
6435 LocalContext context(0, templ);
6436 CompileRun("TryCatchNativeResetHelper();");
6437 CHECK(!try_catch.HasCaught());
6438}
6439
6440
6441THREADED_TEST(Equality) {
6442 LocalContext context;
6443 v8::Isolate* isolate = context->GetIsolate();
6444 v8::HandleScope scope(context->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00006445 // Check that equality works at all before relying on CHECK_EQ
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006446 CHECK(v8_str("a")->Equals(context.local(), v8_str("a")).FromJust());
6447 CHECK(!v8_str("a")->Equals(context.local(), v8_str("b")).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00006448
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006449 CHECK(v8_str("a")->Equals(context.local(), v8_str("a")).FromJust());
6450 CHECK(!v8_str("a")->Equals(context.local(), v8_str("b")).FromJust());
6451 CHECK(v8_num(1)->Equals(context.local(), v8_num(1)).FromJust());
6452 CHECK(v8_num(1.00)->Equals(context.local(), v8_num(1)).FromJust());
6453 CHECK(!v8_num(1)->Equals(context.local(), v8_num(2)).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00006454
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006455 // Assume String is not internalized.
Steve Blocka7e24c12009-10-30 11:49:00 +00006456 CHECK(v8_str("a")->StrictEquals(v8_str("a")));
6457 CHECK(!v8_str("a")->StrictEquals(v8_str("b")));
6458 CHECK(!v8_str("5")->StrictEquals(v8_num(5)));
6459 CHECK(v8_num(1)->StrictEquals(v8_num(1)));
6460 CHECK(!v8_num(1)->StrictEquals(v8_num(2)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006461 CHECK(v8_num(0.0)->StrictEquals(v8_num(-0.0)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006462 Local<Value> not_a_number = v8_num(std::numeric_limits<double>::quiet_NaN());
Steve Blocka7e24c12009-10-30 11:49:00 +00006463 CHECK(!not_a_number->StrictEquals(not_a_number));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006464 CHECK(v8::False(isolate)->StrictEquals(v8::False(isolate)));
6465 CHECK(!v8::False(isolate)->StrictEquals(v8::Undefined(isolate)));
Steve Blocka7e24c12009-10-30 11:49:00 +00006466
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006467 v8::Local<v8::Object> obj = v8::Object::New(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006468 v8::Persistent<v8::Object> alias(isolate, obj);
6469 CHECK(v8::Local<v8::Object>::New(isolate, alias)->StrictEquals(obj));
6470 alias.Reset();
6471
6472 CHECK(v8_str("a")->SameValue(v8_str("a")));
6473 CHECK(!v8_str("a")->SameValue(v8_str("b")));
6474 CHECK(!v8_str("5")->SameValue(v8_num(5)));
6475 CHECK(v8_num(1)->SameValue(v8_num(1)));
6476 CHECK(!v8_num(1)->SameValue(v8_num(2)));
6477 CHECK(!v8_num(0.0)->SameValue(v8_num(-0.0)));
6478 CHECK(not_a_number->SameValue(not_a_number));
6479 CHECK(v8::False(isolate)->SameValue(v8::False(isolate)));
6480 CHECK(!v8::False(isolate)->SameValue(v8::Undefined(isolate)));
Steve Blocka7e24c12009-10-30 11:49:00 +00006481}
6482
Ben Murdochc5610432016-08-08 18:44:38 +01006483THREADED_TEST(TypeOf) {
6484 LocalContext context;
6485 v8::Isolate* isolate = context->GetIsolate();
6486 v8::HandleScope scope(context->GetIsolate());
6487
6488 Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
6489 Local<v8::Function> fun = t1->GetFunction(context.local()).ToLocalChecked();
6490
6491 CHECK(v8::Undefined(isolate)
6492 ->TypeOf(isolate)
6493 ->Equals(context.local(), v8_str("undefined"))
6494 .FromJust());
6495 CHECK(v8::Null(isolate)
6496 ->TypeOf(isolate)
6497 ->Equals(context.local(), v8_str("object"))
6498 .FromJust());
6499 CHECK(v8_str("str")
6500 ->TypeOf(isolate)
6501 ->Equals(context.local(), v8_str("string"))
6502 .FromJust());
6503 CHECK(v8_num(0.0)
6504 ->TypeOf(isolate)
6505 ->Equals(context.local(), v8_str("number"))
6506 .FromJust());
6507 CHECK(v8_num(1)
6508 ->TypeOf(isolate)
6509 ->Equals(context.local(), v8_str("number"))
6510 .FromJust());
6511 CHECK(v8::Object::New(isolate)
6512 ->TypeOf(isolate)
6513 ->Equals(context.local(), v8_str("object"))
6514 .FromJust());
6515 CHECK(v8::Boolean::New(isolate, true)
6516 ->TypeOf(isolate)
6517 ->Equals(context.local(), v8_str("boolean"))
6518 .FromJust());
6519 CHECK(fun->TypeOf(isolate)
6520 ->Equals(context.local(), v8_str("function"))
6521 .FromJust());
6522}
Steve Blocka7e24c12009-10-30 11:49:00 +00006523
6524THREADED_TEST(MultiRun) {
Steve Blocka7e24c12009-10-30 11:49:00 +00006525 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006526 v8::HandleScope scope(context->GetIsolate());
6527 Local<Script> script = v8_compile("x");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006528 for (int i = 0; i < 10; i++) {
6529 script->Run(context.local()).IsEmpty();
6530 }
Steve Blocka7e24c12009-10-30 11:49:00 +00006531}
6532
6533
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006534static void GetXValue(Local<Name> name,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006535 const v8::PropertyCallbackInfo<v8::Value>& info) {
Steve Blocka7e24c12009-10-30 11:49:00 +00006536 ApiTestFuzzer::Fuzz();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006537 CHECK(info.Data()
6538 ->Equals(CcTest::isolate()->GetCurrentContext(), v8_str("donut"))
6539 .FromJust());
6540 CHECK(name->Equals(CcTest::isolate()->GetCurrentContext(), v8_str("x"))
6541 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006542 info.GetReturnValue().Set(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00006543}
6544
6545
6546THREADED_TEST(SimplePropertyRead) {
Steve Blocka7e24c12009-10-30 11:49:00 +00006547 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006548 v8::Isolate* isolate = context->GetIsolate();
6549 v8::HandleScope scope(isolate);
6550 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6551 templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006552 CHECK(context->Global()
6553 ->Set(context.local(), v8_str("obj"),
6554 templ->NewInstance(context.local()).ToLocalChecked())
6555 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006556 Local<Script> script = v8_compile("obj.x");
Steve Blocka7e24c12009-10-30 11:49:00 +00006557 for (int i = 0; i < 10; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006558 Local<Value> result = script->Run(context.local()).ToLocalChecked();
6559 CHECK(result->Equals(context.local(), v8_str("x")).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00006560 }
6561}
6562
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006563
Andrei Popescu31002712010-02-23 13:46:05 +00006564THREADED_TEST(DefinePropertyOnAPIAccessor) {
Andrei Popescu31002712010-02-23 13:46:05 +00006565 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006566 v8::Isolate* isolate = context->GetIsolate();
6567 v8::HandleScope scope(isolate);
6568 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6569 templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006570 CHECK(context->Global()
6571 ->Set(context.local(), v8_str("obj"),
6572 templ->NewInstance(context.local()).ToLocalChecked())
6573 .FromJust());
Andrei Popescu31002712010-02-23 13:46:05 +00006574
6575 // Uses getOwnPropertyDescriptor to check the configurable status
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006576 Local<Script> script_desc = v8_compile(
6577 "var prop = Object.getOwnPropertyDescriptor( "
6578 "obj, 'x');"
6579 "prop.configurable;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006580 Local<Value> result = script_desc->Run(context.local()).ToLocalChecked();
6581 CHECK_EQ(result->BooleanValue(context.local()).FromJust(), true);
Andrei Popescu31002712010-02-23 13:46:05 +00006582
6583 // Redefine get - but still configurable
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006584 Local<Script> script_define = v8_compile(
6585 "var desc = { get: function(){return 42; },"
6586 " configurable: true };"
6587 "Object.defineProperty(obj, 'x', desc);"
6588 "obj.x");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006589 result = script_define->Run(context.local()).ToLocalChecked();
6590 CHECK(result->Equals(context.local(), v8_num(42)).FromJust());
Andrei Popescu31002712010-02-23 13:46:05 +00006591
6592 // Check that the accessor is still configurable
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006593 result = script_desc->Run(context.local()).ToLocalChecked();
6594 CHECK_EQ(result->BooleanValue(context.local()).FromJust(), true);
Andrei Popescu31002712010-02-23 13:46:05 +00006595
6596 // Redefine to a non-configurable
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006597 script_define = v8_compile(
6598 "var desc = { get: function(){return 43; },"
6599 " configurable: false };"
6600 "Object.defineProperty(obj, 'x', desc);"
6601 "obj.x");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006602 result = script_define->Run(context.local()).ToLocalChecked();
6603 CHECK(result->Equals(context.local(), v8_num(43)).FromJust());
6604 result = script_desc->Run(context.local()).ToLocalChecked();
6605 CHECK_EQ(result->BooleanValue(context.local()).FromJust(), false);
Andrei Popescu31002712010-02-23 13:46:05 +00006606
6607 // Make sure that it is not possible to redefine again
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006608 v8::TryCatch try_catch(isolate);
6609 CHECK(script_define->Run(context.local()).IsEmpty());
Andrei Popescu31002712010-02-23 13:46:05 +00006610 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006611 String::Utf8Value exception_value(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006612 CHECK_EQ(0,
6613 strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
Andrei Popescu31002712010-02-23 13:46:05 +00006614}
6615
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006616
Andrei Popescu31002712010-02-23 13:46:05 +00006617THREADED_TEST(DefinePropertyOnDefineGetterSetter) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006618 v8::Isolate* isolate = CcTest::isolate();
6619 v8::HandleScope scope(isolate);
6620 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Andrei Popescu31002712010-02-23 13:46:05 +00006621 templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
6622 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006623 CHECK(context->Global()
6624 ->Set(context.local(), v8_str("obj"),
6625 templ->NewInstance(context.local()).ToLocalChecked())
6626 .FromJust());
Andrei Popescu31002712010-02-23 13:46:05 +00006627
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006628 Local<Script> script_desc = v8_compile(
6629 "var prop ="
6630 "Object.getOwnPropertyDescriptor( "
6631 "obj, 'x');"
6632 "prop.configurable;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006633 Local<Value> result = script_desc->Run(context.local()).ToLocalChecked();
6634 CHECK_EQ(result->BooleanValue(context.local()).FromJust(), true);
Andrei Popescu31002712010-02-23 13:46:05 +00006635
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006636 Local<Script> script_define = v8_compile(
6637 "var desc = {get: function(){return 42; },"
6638 " configurable: true };"
6639 "Object.defineProperty(obj, 'x', desc);"
6640 "obj.x");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006641 result = script_define->Run(context.local()).ToLocalChecked();
6642 CHECK(result->Equals(context.local(), v8_num(42)).FromJust());
Andrei Popescu31002712010-02-23 13:46:05 +00006643
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006644 result = script_desc->Run(context.local()).ToLocalChecked();
6645 CHECK_EQ(result->BooleanValue(context.local()).FromJust(), true);
Andrei Popescu31002712010-02-23 13:46:05 +00006646
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006647 script_define = v8_compile(
6648 "var desc = {get: function(){return 43; },"
6649 " configurable: false };"
6650 "Object.defineProperty(obj, 'x', desc);"
6651 "obj.x");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006652 result = script_define->Run(context.local()).ToLocalChecked();
6653 CHECK(result->Equals(context.local(), v8_num(43)).FromJust());
Andrei Popescu31002712010-02-23 13:46:05 +00006654
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006655 result = script_desc->Run(context.local()).ToLocalChecked();
6656 CHECK_EQ(result->BooleanValue(context.local()).FromJust(), false);
Andrei Popescu31002712010-02-23 13:46:05 +00006657
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006658 v8::TryCatch try_catch(isolate);
6659 CHECK(script_define->Run(context.local()).IsEmpty());
Andrei Popescu31002712010-02-23 13:46:05 +00006660 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006661 String::Utf8Value exception_value(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006662 CHECK_EQ(0,
6663 strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
Andrei Popescu31002712010-02-23 13:46:05 +00006664}
6665
6666
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006667static v8::Local<v8::Object> GetGlobalProperty(LocalContext* context,
6668 char const* name) {
6669 return v8::Local<v8::Object>::Cast(
6670 (*context)
6671 ->Global()
6672 ->Get(CcTest::isolate()->GetCurrentContext(), v8_str(name))
6673 .ToLocalChecked());
Leon Clarkef7060e22010-06-03 12:02:55 +01006674}
Andrei Popescu31002712010-02-23 13:46:05 +00006675
6676
Leon Clarkef7060e22010-06-03 12:02:55 +01006677THREADED_TEST(DefineAPIAccessorOnObject) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006678 v8::Isolate* isolate = CcTest::isolate();
6679 v8::HandleScope scope(isolate);
6680 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Leon Clarkef7060e22010-06-03 12:02:55 +01006681 LocalContext context;
6682
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006683 CHECK(context->Global()
6684 ->Set(context.local(), v8_str("obj1"),
6685 templ->NewInstance(context.local()).ToLocalChecked())
6686 .FromJust());
Leon Clarkef7060e22010-06-03 12:02:55 +01006687 CompileRun("var obj2 = {};");
6688
6689 CHECK(CompileRun("obj1.x")->IsUndefined());
6690 CHECK(CompileRun("obj2.x")->IsUndefined());
6691
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006692 CHECK(GetGlobalProperty(&context, "obj1")
6693 ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
6694 v8_str("donut"))
6695 .FromJust());
Leon Clarkef7060e22010-06-03 12:02:55 +01006696
6697 ExpectString("obj1.x", "x");
6698 CHECK(CompileRun("obj2.x")->IsUndefined());
6699
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006700 CHECK(GetGlobalProperty(&context, "obj2")
6701 ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
6702 v8_str("donut"))
6703 .FromJust());
Leon Clarkef7060e22010-06-03 12:02:55 +01006704
6705 ExpectString("obj1.x", "x");
6706 ExpectString("obj2.x", "x");
6707
6708 ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
6709 ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
6710
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006711 CompileRun(
6712 "Object.defineProperty(obj1, 'x',"
6713 "{ get: function() { return 'y'; }, configurable: true })");
Leon Clarkef7060e22010-06-03 12:02:55 +01006714
6715 ExpectString("obj1.x", "y");
6716 ExpectString("obj2.x", "x");
6717
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006718 CompileRun(
6719 "Object.defineProperty(obj2, 'x',"
6720 "{ get: function() { return 'y'; }, configurable: true })");
Leon Clarkef7060e22010-06-03 12:02:55 +01006721
6722 ExpectString("obj1.x", "y");
6723 ExpectString("obj2.x", "y");
6724
6725 ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
6726 ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
6727
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006728 CHECK(GetGlobalProperty(&context, "obj1")
6729 ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
6730 v8_str("donut"))
6731 .FromJust());
6732 CHECK(GetGlobalProperty(&context, "obj2")
6733 ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
6734 v8_str("donut"))
6735 .FromJust());
Leon Clarkef7060e22010-06-03 12:02:55 +01006736
6737 ExpectString("obj1.x", "x");
6738 ExpectString("obj2.x", "x");
6739
6740 ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
6741 ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
6742
6743 // Define getters/setters, but now make them not configurable.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006744 CompileRun(
6745 "Object.defineProperty(obj1, 'x',"
6746 "{ get: function() { return 'z'; }, configurable: false })");
6747 CompileRun(
6748 "Object.defineProperty(obj2, 'x',"
6749 "{ get: function() { return 'z'; }, configurable: false })");
Leon Clarkef7060e22010-06-03 12:02:55 +01006750 ExpectTrue("!Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
6751 ExpectTrue("!Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
6752
6753 ExpectString("obj1.x", "z");
6754 ExpectString("obj2.x", "z");
6755
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006756 CHECK(GetGlobalProperty(&context, "obj1")
6757 ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
6758 v8_str("donut"))
6759 .IsNothing());
6760 CHECK(GetGlobalProperty(&context, "obj2")
6761 ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
6762 v8_str("donut"))
6763 .IsNothing());
Leon Clarkef7060e22010-06-03 12:02:55 +01006764
6765 ExpectString("obj1.x", "z");
6766 ExpectString("obj2.x", "z");
6767}
6768
6769
6770THREADED_TEST(DontDeleteAPIAccessorsCannotBeOverriden) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006771 v8::Isolate* isolate = CcTest::isolate();
6772 v8::HandleScope scope(isolate);
6773 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Leon Clarkef7060e22010-06-03 12:02:55 +01006774 LocalContext context;
6775
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006776 CHECK(context->Global()
6777 ->Set(context.local(), v8_str("obj1"),
6778 templ->NewInstance(context.local()).ToLocalChecked())
6779 .FromJust());
Leon Clarkef7060e22010-06-03 12:02:55 +01006780 CompileRun("var obj2 = {};");
6781
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006782 CHECK(GetGlobalProperty(&context, "obj1")
6783 ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
6784 v8_str("donut"), v8::DEFAULT, v8::DontDelete)
6785 .FromJust());
6786 CHECK(GetGlobalProperty(&context, "obj2")
6787 ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
6788 v8_str("donut"), v8::DEFAULT, v8::DontDelete)
6789 .FromJust());
Leon Clarkef7060e22010-06-03 12:02:55 +01006790
6791 ExpectString("obj1.x", "x");
6792 ExpectString("obj2.x", "x");
6793
6794 ExpectTrue("!Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
6795 ExpectTrue("!Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
6796
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006797 CHECK(GetGlobalProperty(&context, "obj1")
6798 ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
6799 v8_str("donut"))
6800 .IsNothing());
6801 CHECK(GetGlobalProperty(&context, "obj2")
6802 ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
6803 v8_str("donut"))
6804 .IsNothing());
Leon Clarkef7060e22010-06-03 12:02:55 +01006805
6806 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006807 v8::TryCatch try_catch(isolate);
6808 CompileRun(
6809 "Object.defineProperty(obj1, 'x',"
Leon Clarkef7060e22010-06-03 12:02:55 +01006810 "{get: function() { return 'func'; }})");
6811 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006812 String::Utf8Value exception_value(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006813 CHECK_EQ(
6814 0, strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
Leon Clarkef7060e22010-06-03 12:02:55 +01006815 }
6816 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006817 v8::TryCatch try_catch(isolate);
6818 CompileRun(
6819 "Object.defineProperty(obj2, 'x',"
Leon Clarkef7060e22010-06-03 12:02:55 +01006820 "{get: function() { return 'func'; }})");
6821 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006822 String::Utf8Value exception_value(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006823 CHECK_EQ(
6824 0, strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
Leon Clarkef7060e22010-06-03 12:02:55 +01006825 }
6826}
6827
6828
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006829static void Get239Value(Local<Name> name,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006830 const v8::PropertyCallbackInfo<v8::Value>& info) {
Leon Clarkef7060e22010-06-03 12:02:55 +01006831 ApiTestFuzzer::Fuzz();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006832 CHECK(info.Data()
6833 ->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("donut"))
6834 .FromJust());
6835 CHECK(name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("239"))
6836 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006837 info.GetReturnValue().Set(name);
Leon Clarkef7060e22010-06-03 12:02:55 +01006838}
6839
6840
6841THREADED_TEST(ElementAPIAccessor) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006842 v8::Isolate* isolate = CcTest::isolate();
6843 v8::HandleScope scope(isolate);
6844 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Leon Clarkef7060e22010-06-03 12:02:55 +01006845 LocalContext context;
6846
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006847 CHECK(context->Global()
6848 ->Set(context.local(), v8_str("obj1"),
6849 templ->NewInstance(context.local()).ToLocalChecked())
6850 .FromJust());
Leon Clarkef7060e22010-06-03 12:02:55 +01006851 CompileRun("var obj2 = {};");
6852
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006853 CHECK(GetGlobalProperty(&context, "obj1")
6854 ->SetAccessor(context.local(), v8_str("239"), Get239Value, NULL,
6855 v8_str("donut"))
6856 .FromJust());
6857 CHECK(GetGlobalProperty(&context, "obj2")
6858 ->SetAccessor(context.local(), v8_str("239"), Get239Value, NULL,
6859 v8_str("donut"))
6860 .FromJust());
Leon Clarkef7060e22010-06-03 12:02:55 +01006861
6862 ExpectString("obj1[239]", "239");
6863 ExpectString("obj2[239]", "239");
6864 ExpectString("obj1['239']", "239");
6865 ExpectString("obj2['239']", "239");
6866}
6867
Steve Blocka7e24c12009-10-30 11:49:00 +00006868
6869v8::Persistent<Value> xValue;
6870
6871
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006872static void SetXValue(Local<Name> name, Local<Value> value,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006873 const v8::PropertyCallbackInfo<void>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006874 Local<Context> context = info.GetIsolate()->GetCurrentContext();
6875 CHECK(value->Equals(context, v8_num(4)).FromJust());
6876 CHECK(info.Data()->Equals(context, v8_str("donut")).FromJust());
6877 CHECK(name->Equals(context, v8_str("x")).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00006878 CHECK(xValue.IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006879 xValue.Reset(info.GetIsolate(), value);
Steve Blocka7e24c12009-10-30 11:49:00 +00006880}
6881
6882
6883THREADED_TEST(SimplePropertyWrite) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006884 v8::Isolate* isolate = CcTest::isolate();
6885 v8::HandleScope scope(isolate);
6886 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00006887 templ->SetAccessor(v8_str("x"), GetXValue, SetXValue, v8_str("donut"));
6888 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006889 CHECK(context->Global()
6890 ->Set(context.local(), v8_str("obj"),
6891 templ->NewInstance(context.local()).ToLocalChecked())
6892 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006893 Local<Script> script = v8_compile("obj.x = 4");
Steve Blocka7e24c12009-10-30 11:49:00 +00006894 for (int i = 0; i < 10; i++) {
6895 CHECK(xValue.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006896 script->Run(context.local()).ToLocalChecked();
6897 CHECK(v8_num(4)
6898 ->Equals(context.local(),
6899 Local<Value>::New(CcTest::isolate(), xValue))
6900 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006901 xValue.Reset();
Steve Blocka7e24c12009-10-30 11:49:00 +00006902 }
6903}
6904
6905
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006906THREADED_TEST(SetterOnly) {
6907 v8::Isolate* isolate = CcTest::isolate();
6908 v8::HandleScope scope(isolate);
6909 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6910 templ->SetAccessor(v8_str("x"), NULL, SetXValue, v8_str("donut"));
6911 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006912 CHECK(context->Global()
6913 ->Set(context.local(), v8_str("obj"),
6914 templ->NewInstance(context.local()).ToLocalChecked())
6915 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006916 Local<Script> script = v8_compile("obj.x = 4; obj.x");
6917 for (int i = 0; i < 10; i++) {
6918 CHECK(xValue.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006919 script->Run(context.local()).ToLocalChecked();
6920 CHECK(v8_num(4)
6921 ->Equals(context.local(),
6922 Local<Value>::New(CcTest::isolate(), xValue))
6923 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006924 xValue.Reset();
6925 }
6926}
6927
6928
6929THREADED_TEST(NoAccessors) {
6930 v8::Isolate* isolate = CcTest::isolate();
6931 v8::HandleScope scope(isolate);
6932 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006933 templ->SetAccessor(v8_str("x"), static_cast<v8::AccessorGetterCallback>(NULL),
6934 NULL, v8_str("donut"));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006935 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006936 CHECK(context->Global()
6937 ->Set(context.local(), v8_str("obj"),
6938 templ->NewInstance(context.local()).ToLocalChecked())
6939 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006940 Local<Script> script = v8_compile("obj.x = 4; obj.x");
6941 for (int i = 0; i < 10; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006942 script->Run(context.local()).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006943 }
6944}
6945
6946
Steve Blocka7e24c12009-10-30 11:49:00 +00006947THREADED_TEST(MultiContexts) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006948 v8::Isolate* isolate = CcTest::isolate();
6949 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006950 v8::Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6951 templ->Set(v8_str("dummy"),
6952 v8::FunctionTemplate::New(isolate, DummyCallHandler));
Steve Blocka7e24c12009-10-30 11:49:00 +00006953
6954 Local<String> password = v8_str("Password");
6955
6956 // Create an environment
6957 LocalContext context0(0, templ);
6958 context0->SetSecurityToken(password);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006959 v8::Local<v8::Object> global0 = context0->Global();
6960 CHECK(global0->Set(context0.local(), v8_str("custom"), v8_num(1234))
6961 .FromJust());
6962 CHECK_EQ(1234, global0->Get(context0.local(), v8_str("custom"))
6963 .ToLocalChecked()
6964 ->Int32Value(context0.local())
6965 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00006966
6967 // Create an independent environment
6968 LocalContext context1(0, templ);
6969 context1->SetSecurityToken(password);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006970 v8::Local<v8::Object> global1 = context1->Global();
6971 CHECK(global1->Set(context1.local(), v8_str("custom"), v8_num(1234))
6972 .FromJust());
6973 CHECK(!global0->Equals(context1.local(), global1).FromJust());
6974 CHECK_EQ(1234, global0->Get(context1.local(), v8_str("custom"))
6975 .ToLocalChecked()
6976 ->Int32Value(context0.local())
6977 .FromJust());
6978 CHECK_EQ(1234, global1->Get(context1.local(), v8_str("custom"))
6979 .ToLocalChecked()
6980 ->Int32Value(context1.local())
6981 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00006982
6983 // Now create a new context with the old global
6984 LocalContext context2(0, templ, global1);
6985 context2->SetSecurityToken(password);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006986 v8::Local<v8::Object> global2 = context2->Global();
6987 CHECK(global1->Equals(context2.local(), global2).FromJust());
6988 CHECK_EQ(0, global1->Get(context2.local(), v8_str("custom"))
6989 .ToLocalChecked()
6990 ->Int32Value(context1.local())
6991 .FromJust());
6992 CHECK_EQ(0, global2->Get(context2.local(), v8_str("custom"))
6993 .ToLocalChecked()
6994 ->Int32Value(context2.local())
6995 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00006996}
6997
6998
6999THREADED_TEST(FunctionPrototypeAcrossContexts) {
7000 // Make sure that functions created by cloning boilerplates cannot
7001 // communicate through their __proto__ field.
7002
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007003 v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00007004
7005 LocalContext env0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007006 v8::Local<v8::Object> global0 = env0->Global();
7007 v8::Local<v8::Object> object0 = global0->Get(env0.local(), v8_str("Object"))
7008 .ToLocalChecked()
7009 .As<v8::Object>();
7010 v8::Local<v8::Object> tostring0 =
7011 object0->Get(env0.local(), v8_str("toString"))
7012 .ToLocalChecked()
7013 .As<v8::Object>();
7014 v8::Local<v8::Object> proto0 =
7015 tostring0->Get(env0.local(), v8_str("__proto__"))
7016 .ToLocalChecked()
7017 .As<v8::Object>();
7018 CHECK(proto0->Set(env0.local(), v8_str("custom"), v8_num(1234)).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00007019
7020 LocalContext env1;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007021 v8::Local<v8::Object> global1 = env1->Global();
7022 v8::Local<v8::Object> object1 = global1->Get(env1.local(), v8_str("Object"))
7023 .ToLocalChecked()
7024 .As<v8::Object>();
7025 v8::Local<v8::Object> tostring1 =
7026 object1->Get(env1.local(), v8_str("toString"))
7027 .ToLocalChecked()
7028 .As<v8::Object>();
7029 v8::Local<v8::Object> proto1 =
7030 tostring1->Get(env1.local(), v8_str("__proto__"))
7031 .ToLocalChecked()
7032 .As<v8::Object>();
7033 CHECK(!proto1->Has(env1.local(), v8_str("custom")).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00007034}
7035
7036
7037THREADED_TEST(Regress892105) {
7038 // Make sure that object and array literals created by cloning
7039 // boilerplates cannot communicate through their __proto__
7040 // field. This is rather difficult to check, but we try to add stuff
7041 // to Object.prototype and Array.prototype and create a new
7042 // environment. This should succeed.
7043
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007044 v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00007045
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007046 Local<String> source = v8_str(
7047 "Object.prototype.obj = 1234;"
7048 "Array.prototype.arr = 4567;"
7049 "8901");
Steve Blocka7e24c12009-10-30 11:49:00 +00007050
7051 LocalContext env0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007052 Local<Script> script0 = v8_compile(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007053 CHECK_EQ(8901.0, script0->Run(env0.local())
7054 .ToLocalChecked()
7055 ->NumberValue(env0.local())
7056 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00007057
7058 LocalContext env1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007059 Local<Script> script1 = v8_compile(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007060 CHECK_EQ(8901.0, script1->Run(env1.local())
7061 .ToLocalChecked()
7062 ->NumberValue(env1.local())
7063 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00007064}
7065
7066
Steve Blocka7e24c12009-10-30 11:49:00 +00007067THREADED_TEST(UndetectableObject) {
Steve Blocka7e24c12009-10-30 11:49:00 +00007068 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007069 v8::HandleScope scope(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00007070
7071 Local<v8::FunctionTemplate> desc =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007072 v8::FunctionTemplate::New(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00007073 desc->InstanceTemplate()->MarkAsUndetectable(); // undetectable
7074
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007075 Local<v8::Object> obj = desc->GetFunction(env.local())
7076 .ToLocalChecked()
7077 ->NewInstance(env.local())
7078 .ToLocalChecked();
7079 CHECK(
7080 env->Global()->Set(env.local(), v8_str("undetectable"), obj).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00007081
7082 ExpectString("undetectable.toString()", "[object Object]");
7083 ExpectString("typeof undetectable", "undefined");
7084 ExpectString("typeof(undetectable)", "undefined");
7085 ExpectBoolean("typeof undetectable == 'undefined'", true);
7086 ExpectBoolean("typeof undetectable == 'object'", false);
7087 ExpectBoolean("if (undetectable) { true; } else { false; }", false);
7088 ExpectBoolean("!undetectable", true);
7089
7090 ExpectObject("true&&undetectable", obj);
7091 ExpectBoolean("false&&undetectable", false);
7092 ExpectBoolean("true||undetectable", true);
7093 ExpectObject("false||undetectable", obj);
7094
7095 ExpectObject("undetectable&&true", obj);
7096 ExpectObject("undetectable&&false", obj);
7097 ExpectBoolean("undetectable||true", true);
7098 ExpectBoolean("undetectable||false", false);
7099
7100 ExpectBoolean("undetectable==null", true);
7101 ExpectBoolean("null==undetectable", true);
7102 ExpectBoolean("undetectable==undefined", true);
7103 ExpectBoolean("undefined==undetectable", true);
7104 ExpectBoolean("undetectable==undetectable", true);
7105
7106
7107 ExpectBoolean("undetectable===null", false);
7108 ExpectBoolean("null===undetectable", false);
7109 ExpectBoolean("undetectable===undefined", false);
7110 ExpectBoolean("undefined===undetectable", false);
7111 ExpectBoolean("undetectable===undetectable", true);
7112}
7113
7114
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007115THREADED_TEST(VoidLiteral) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007116 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007117 v8::Isolate* isolate = env->GetIsolate();
7118 v8::HandleScope scope(isolate);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007119
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007120 Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007121 desc->InstanceTemplate()->MarkAsUndetectable(); // undetectable
7122
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007123 Local<v8::Object> obj = desc->GetFunction(env.local())
7124 .ToLocalChecked()
7125 ->NewInstance(env.local())
7126 .ToLocalChecked();
7127 CHECK(
7128 env->Global()->Set(env.local(), v8_str("undetectable"), obj).FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007129
7130 ExpectBoolean("undefined == void 0", true);
7131 ExpectBoolean("undetectable == void 0", true);
7132 ExpectBoolean("null == void 0", true);
7133 ExpectBoolean("undefined === void 0", true);
7134 ExpectBoolean("undetectable === void 0", false);
7135 ExpectBoolean("null === void 0", false);
7136
7137 ExpectBoolean("void 0 == undefined", true);
7138 ExpectBoolean("void 0 == undetectable", true);
7139 ExpectBoolean("void 0 == null", true);
7140 ExpectBoolean("void 0 === undefined", true);
7141 ExpectBoolean("void 0 === undetectable", false);
7142 ExpectBoolean("void 0 === null", false);
7143
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007144 ExpectString(
7145 "(function() {"
7146 " try {"
7147 " return x === void 0;"
7148 " } catch(e) {"
7149 " return e.toString();"
7150 " }"
7151 "})()",
7152 "ReferenceError: x is not defined");
7153 ExpectString(
7154 "(function() {"
7155 " try {"
7156 " return void 0 === x;"
7157 " } catch(e) {"
7158 " return e.toString();"
7159 " }"
7160 "})()",
7161 "ReferenceError: x is not defined");
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007162}
7163
Steve Block8defd9f2010-07-08 12:39:36 +01007164
7165THREADED_TEST(ExtensibleOnUndetectable) {
Steve Block8defd9f2010-07-08 12:39:36 +01007166 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007167 v8::Isolate* isolate = env->GetIsolate();
7168 v8::HandleScope scope(isolate);
Steve Block8defd9f2010-07-08 12:39:36 +01007169
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007170 Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
Steve Block8defd9f2010-07-08 12:39:36 +01007171 desc->InstanceTemplate()->MarkAsUndetectable(); // undetectable
7172
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007173 Local<v8::Object> obj = desc->GetFunction(env.local())
7174 .ToLocalChecked()
7175 ->NewInstance(env.local())
7176 .ToLocalChecked();
7177 CHECK(
7178 env->Global()->Set(env.local(), v8_str("undetectable"), obj).FromJust());
Steve Block8defd9f2010-07-08 12:39:36 +01007179
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007180 Local<String> source = v8_str(
7181 "undetectable.x = 42;"
7182 "undetectable.x");
Steve Block8defd9f2010-07-08 12:39:36 +01007183
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007184 Local<Script> script = v8_compile(source);
Steve Block8defd9f2010-07-08 12:39:36 +01007185
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007186 CHECK(v8::Integer::New(isolate, 42)
7187 ->Equals(env.local(), script->Run(env.local()).ToLocalChecked())
7188 .FromJust());
Steve Block8defd9f2010-07-08 12:39:36 +01007189
7190 ExpectBoolean("Object.isExtensible(undetectable)", true);
7191
7192 source = v8_str("Object.preventExtensions(undetectable);");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007193 script = v8_compile(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007194 script->Run(env.local()).ToLocalChecked();
Steve Block8defd9f2010-07-08 12:39:36 +01007195 ExpectBoolean("Object.isExtensible(undetectable)", false);
7196
7197 source = v8_str("undetectable.y = 2000;");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007198 script = v8_compile(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007199 script->Run(env.local()).ToLocalChecked();
Steve Block44f0eee2011-05-26 01:26:41 +01007200 ExpectBoolean("undetectable.y == undefined", true);
Steve Block8defd9f2010-07-08 12:39:36 +01007201}
7202
7203
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007204// The point of this test is type checking. We run it only so compilers
7205// don't complain about an unused function.
7206TEST(PersistentHandles) {
7207 LocalContext env;
7208 v8::Isolate* isolate = CcTest::isolate();
7209 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00007210 Local<String> str = v8_str("foo");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007211 v8::Persistent<String> p_str(isolate, str);
7212 p_str.Reset();
7213 Local<Script> scr = v8_compile("");
7214 v8::Persistent<Script> p_scr(isolate, scr);
7215 p_scr.Reset();
7216 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
7217 v8::Persistent<ObjectTemplate> p_templ(isolate, templ);
7218 p_templ.Reset();
Steve Blocka7e24c12009-10-30 11:49:00 +00007219}
7220
7221
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007222static void HandleLogDelegator(
7223 const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +00007224 ApiTestFuzzer::Fuzz();
Steve Blocka7e24c12009-10-30 11:49:00 +00007225}
7226
7227
7228THREADED_TEST(GlobalObjectTemplate) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007229 v8::Isolate* isolate = CcTest::isolate();
7230 v8::HandleScope handle_scope(isolate);
7231 Local<ObjectTemplate> global_template = ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00007232 global_template->Set(v8_str("JSNI_Log"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007233 v8::FunctionTemplate::New(isolate, HandleLogDelegator));
7234 v8::Local<Context> context = Context::New(isolate, 0, global_template);
Steve Blocka7e24c12009-10-30 11:49:00 +00007235 Context::Scope context_scope(context);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007236 CompileRun("JSNI_Log('LOG')");
Steve Blocka7e24c12009-10-30 11:49:00 +00007237}
7238
7239
7240static const char* kSimpleExtensionSource =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007241 "function Foo() {"
7242 " return 4;"
7243 "}";
Steve Blocka7e24c12009-10-30 11:49:00 +00007244
7245
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007246TEST(SimpleExtensions) {
7247 v8::HandleScope handle_scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00007248 v8::RegisterExtension(new Extension("simpletest", kSimpleExtensionSource));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007249 const char* extension_names[] = {"simpletest"};
Steve Blocka7e24c12009-10-30 11:49:00 +00007250 v8::ExtensionConfiguration extensions(1, extension_names);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007251 v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
Steve Blocka7e24c12009-10-30 11:49:00 +00007252 Context::Scope lock(context);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007253 v8::Local<Value> result = CompileRun("Foo()");
7254 CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 4))
7255 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007256}
7257
7258
7259static const char* kStackTraceFromExtensionSource =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007260 "function foo() {"
7261 " throw new Error();"
7262 "}"
7263 "function bar() {"
7264 " foo();"
7265 "}";
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007266
7267
7268TEST(StackTraceInExtension) {
7269 v8::HandleScope handle_scope(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007270 v8::RegisterExtension(
7271 new Extension("stacktracetest", kStackTraceFromExtensionSource));
7272 const char* extension_names[] = {"stacktracetest"};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007273 v8::ExtensionConfiguration extensions(1, extension_names);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007274 v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007275 Context::Scope lock(context);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007276 CompileRun(
7277 "function user() { bar(); }"
7278 "var error;"
7279 "try{ user(); } catch (e) { error = e; }");
7280 CHECK_EQ(-1, v8_run_int32value(v8_compile("error.stack.indexOf('foo')")));
7281 CHECK_EQ(-1, v8_run_int32value(v8_compile("error.stack.indexOf('bar')")));
7282 CHECK_NE(-1, v8_run_int32value(v8_compile("error.stack.indexOf('user')")));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007283}
7284
7285
7286TEST(NullExtensions) {
7287 v8::HandleScope handle_scope(CcTest::isolate());
7288 v8::RegisterExtension(new Extension("nulltest", NULL));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007289 const char* extension_names[] = {"nulltest"};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007290 v8::ExtensionConfiguration extensions(1, extension_names);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007291 v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007292 Context::Scope lock(context);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007293 v8::Local<Value> result = CompileRun("1+3");
7294 CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 4))
7295 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00007296}
7297
7298
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007299static const char* kEmbeddedExtensionSource =
7300 "function Ret54321(){return 54321;}~~@@$"
7301 "$%% THIS IS A SERIES OF NON-NULL-TERMINATED STRINGS.";
7302static const int kEmbeddedExtensionSourceValidLen = 34;
7303
7304
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007305TEST(ExtensionMissingSourceLength) {
7306 v8::HandleScope handle_scope(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007307 v8::RegisterExtension(
7308 new Extension("srclentest_fail", kEmbeddedExtensionSource));
7309 const char* extension_names[] = {"srclentest_fail"};
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007310 v8::ExtensionConfiguration extensions(1, extension_names);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007311 v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
7312 CHECK(0 == *context);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007313}
7314
7315
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007316TEST(ExtensionWithSourceLength) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007317 for (int source_len = kEmbeddedExtensionSourceValidLen - 1;
7318 source_len <= kEmbeddedExtensionSourceValidLen + 1; ++source_len) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007319 v8::HandleScope handle_scope(CcTest::isolate());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007320 i::ScopedVector<char> extension_name(32);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007321 i::SNPrintF(extension_name, "ext #%d", source_len);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007322 v8::RegisterExtension(new Extension(
7323 extension_name.start(), kEmbeddedExtensionSource, 0, 0, source_len));
7324 const char* extension_names[1] = {extension_name.start()};
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007325 v8::ExtensionConfiguration extensions(1, extension_names);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007326 v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007327 if (source_len == kEmbeddedExtensionSourceValidLen) {
7328 Context::Scope lock(context);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007329 v8::Local<Value> result = CompileRun("Ret54321()");
7330 CHECK(v8::Integer::New(CcTest::isolate(), 54321)
7331 ->Equals(context, result)
7332 .FromJust());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007333 } else {
7334 // Anything but exactly the right length should fail to compile.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007335 CHECK(0 == *context);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007336 }
7337 }
7338}
7339
7340
Steve Blocka7e24c12009-10-30 11:49:00 +00007341static const char* kEvalExtensionSource1 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007342 "function UseEval1() {"
7343 " var x = 42;"
7344 " return eval('x');"
7345 "}";
Steve Blocka7e24c12009-10-30 11:49:00 +00007346
7347
7348static const char* kEvalExtensionSource2 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007349 "(function() {"
7350 " var x = 42;"
7351 " function e() {"
7352 " return eval('x');"
7353 " }"
7354 " this.UseEval2 = e;"
7355 "})()";
Steve Blocka7e24c12009-10-30 11:49:00 +00007356
7357
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007358TEST(UseEvalFromExtension) {
7359 v8::HandleScope handle_scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00007360 v8::RegisterExtension(new Extension("evaltest1", kEvalExtensionSource1));
7361 v8::RegisterExtension(new Extension("evaltest2", kEvalExtensionSource2));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007362 const char* extension_names[] = {"evaltest1", "evaltest2"};
Steve Blocka7e24c12009-10-30 11:49:00 +00007363 v8::ExtensionConfiguration extensions(2, extension_names);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007364 v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
Steve Blocka7e24c12009-10-30 11:49:00 +00007365 Context::Scope lock(context);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007366 v8::Local<Value> result = CompileRun("UseEval1()");
7367 CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 42))
7368 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007369 result = CompileRun("UseEval2()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007370 CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 42))
7371 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00007372}
7373
7374
7375static const char* kWithExtensionSource1 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007376 "function UseWith1() {"
7377 " var x = 42;"
7378 " with({x:87}) { return x; }"
7379 "}";
Steve Blocka7e24c12009-10-30 11:49:00 +00007380
7381
7382static const char* kWithExtensionSource2 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007383 "(function() {"
7384 " var x = 42;"
7385 " function e() {"
7386 " with ({x:87}) { return x; }"
7387 " }"
7388 " this.UseWith2 = e;"
7389 "})()";
Steve Blocka7e24c12009-10-30 11:49:00 +00007390
7391
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007392TEST(UseWithFromExtension) {
7393 v8::HandleScope handle_scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00007394 v8::RegisterExtension(new Extension("withtest1", kWithExtensionSource1));
7395 v8::RegisterExtension(new Extension("withtest2", kWithExtensionSource2));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007396 const char* extension_names[] = {"withtest1", "withtest2"};
Steve Blocka7e24c12009-10-30 11:49:00 +00007397 v8::ExtensionConfiguration extensions(2, extension_names);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007398 v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
Steve Blocka7e24c12009-10-30 11:49:00 +00007399 Context::Scope lock(context);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007400 v8::Local<Value> result = CompileRun("UseWith1()");
7401 CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 87))
7402 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007403 result = CompileRun("UseWith2()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007404 CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 87))
7405 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00007406}
7407
7408
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007409TEST(AutoExtensions) {
7410 v8::HandleScope handle_scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00007411 Extension* extension = new Extension("autotest", kSimpleExtensionSource);
7412 extension->set_auto_enable(true);
7413 v8::RegisterExtension(extension);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007414 v8::Local<Context> context = Context::New(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00007415 Context::Scope lock(context);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007416 v8::Local<Value> result = CompileRun("Foo()");
7417 CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 4))
7418 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00007419}
7420
7421
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007422static const char* kSyntaxErrorInExtensionSource = "[";
Steve Blockd0582a62009-12-15 09:54:21 +00007423
7424
7425// Test that a syntax error in an extension does not cause a fatal
7426// error but results in an empty context.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007427TEST(SyntaxErrorExtensions) {
7428 v8::HandleScope handle_scope(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007429 v8::RegisterExtension(
7430 new Extension("syntaxerror", kSyntaxErrorInExtensionSource));
7431 const char* extension_names[] = {"syntaxerror"};
Steve Blockd0582a62009-12-15 09:54:21 +00007432 v8::ExtensionConfiguration extensions(1, extension_names);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007433 v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
Steve Blockd0582a62009-12-15 09:54:21 +00007434 CHECK(context.IsEmpty());
7435}
7436
7437
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007438static const char* kExceptionInExtensionSource = "throw 42";
Steve Blockd0582a62009-12-15 09:54:21 +00007439
7440
7441// Test that an exception when installing an extension does not cause
7442// a fatal error but results in an empty context.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007443TEST(ExceptionExtensions) {
7444 v8::HandleScope handle_scope(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007445 v8::RegisterExtension(
7446 new Extension("exception", kExceptionInExtensionSource));
7447 const char* extension_names[] = {"exception"};
Steve Blockd0582a62009-12-15 09:54:21 +00007448 v8::ExtensionConfiguration extensions(1, extension_names);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007449 v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
Steve Blockd0582a62009-12-15 09:54:21 +00007450 CHECK(context.IsEmpty());
7451}
7452
7453
Iain Merrick9ac36c92010-09-13 15:29:50 +01007454static const char* kNativeCallInExtensionSource =
7455 "function call_runtime_last_index_of(x) {"
7456 " return %StringLastIndexOf(x, 'bob', 10);"
7457 "}";
7458
7459
7460static const char* kNativeCallTest =
7461 "call_runtime_last_index_of('bobbobboellebobboellebobbob');";
7462
7463// Test that a native runtime calls are supported in extensions.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007464TEST(NativeCallInExtensions) {
7465 v8::HandleScope handle_scope(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007466 v8::RegisterExtension(
7467 new Extension("nativecall", kNativeCallInExtensionSource));
7468 const char* extension_names[] = {"nativecall"};
Iain Merrick9ac36c92010-09-13 15:29:50 +01007469 v8::ExtensionConfiguration extensions(1, extension_names);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007470 v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
Iain Merrick9ac36c92010-09-13 15:29:50 +01007471 Context::Scope lock(context);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007472 v8::Local<Value> result = CompileRun(kNativeCallTest);
7473 CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 3))
7474 .FromJust());
Iain Merrick9ac36c92010-09-13 15:29:50 +01007475}
7476
7477
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007478class NativeFunctionExtension : public Extension {
7479 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007480 NativeFunctionExtension(const char* name, const char* source,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007481 v8::FunctionCallback fun = &Echo)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007482 : Extension(name, source), function_(fun) {}
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007483
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007484 virtual v8::Local<v8::FunctionTemplate> GetNativeFunctionTemplate(
7485 v8::Isolate* isolate, v8::Local<v8::String> name) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007486 return v8::FunctionTemplate::New(isolate, function_);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007487 }
7488
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007489 static void Echo(const v8::FunctionCallbackInfo<v8::Value>& args) {
7490 if (args.Length() >= 1) args.GetReturnValue().Set(args[0]);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007491 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007492
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007493 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007494 v8::FunctionCallback function_;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007495};
7496
7497
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007498TEST(NativeFunctionDeclaration) {
7499 v8::HandleScope handle_scope(CcTest::isolate());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007500 const char* name = "nativedecl";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007501 v8::RegisterExtension(
7502 new NativeFunctionExtension(name, "native function foo();"));
7503 const char* extension_names[] = {name};
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007504 v8::ExtensionConfiguration extensions(1, extension_names);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007505 v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007506 Context::Scope lock(context);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007507 v8::Local<Value> result = CompileRun("foo(42);");
7508 CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 42))
7509 .FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007510}
7511
7512
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007513TEST(NativeFunctionDeclarationError) {
7514 v8::HandleScope handle_scope(CcTest::isolate());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007515 const char* name = "nativedeclerr";
7516 // Syntax error in extension code.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007517 v8::RegisterExtension(
7518 new NativeFunctionExtension(name, "native\nfunction foo();"));
7519 const char* extension_names[] = {name};
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007520 v8::ExtensionConfiguration extensions(1, extension_names);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007521 v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007522 CHECK(context.IsEmpty());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007523}
7524
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007525
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007526TEST(NativeFunctionDeclarationErrorEscape) {
7527 v8::HandleScope handle_scope(CcTest::isolate());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007528 const char* name = "nativedeclerresc";
7529 // Syntax error in extension code - escape code in "native" means that
7530 // it's not treated as a keyword.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007531 v8::RegisterExtension(
7532 new NativeFunctionExtension(name, "nativ\\u0065 function foo();"));
7533 const char* extension_names[] = {name};
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007534 v8::ExtensionConfiguration extensions(1, extension_names);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007535 v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007536 CHECK(context.IsEmpty());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007537}
7538
7539
Steve Blocka7e24c12009-10-30 11:49:00 +00007540static void CheckDependencies(const char* name, const char* expected) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007541 v8::HandleScope handle_scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00007542 v8::ExtensionConfiguration config(1, &name);
7543 LocalContext context(&config);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007544 CHECK(
7545 v8_str(expected)
7546 ->Equals(context.local(), context->Global()
7547 ->Get(context.local(), v8_str("loaded"))
7548 .ToLocalChecked())
7549 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00007550}
7551
7552
7553/*
7554 * Configuration:
7555 *
7556 * /-- B <--\
7557 * A <- -- D <-- E
7558 * \-- C <--/
7559 */
7560THREADED_TEST(ExtensionDependency) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007561 static const char* kEDeps[] = {"D"};
Steve Blocka7e24c12009-10-30 11:49:00 +00007562 v8::RegisterExtension(new Extension("E", "this.loaded += 'E';", 1, kEDeps));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007563 static const char* kDDeps[] = {"B", "C"};
Steve Blocka7e24c12009-10-30 11:49:00 +00007564 v8::RegisterExtension(new Extension("D", "this.loaded += 'D';", 2, kDDeps));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007565 static const char* kBCDeps[] = {"A"};
Steve Blocka7e24c12009-10-30 11:49:00 +00007566 v8::RegisterExtension(new Extension("B", "this.loaded += 'B';", 1, kBCDeps));
7567 v8::RegisterExtension(new Extension("C", "this.loaded += 'C';", 1, kBCDeps));
7568 v8::RegisterExtension(new Extension("A", "this.loaded += 'A';"));
7569 CheckDependencies("A", "undefinedA");
7570 CheckDependencies("B", "undefinedAB");
7571 CheckDependencies("C", "undefinedAC");
7572 CheckDependencies("D", "undefinedABCD");
7573 CheckDependencies("E", "undefinedABCDE");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007574 v8::HandleScope handle_scope(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007575 static const char* exts[2] = {"C", "E"};
Steve Blocka7e24c12009-10-30 11:49:00 +00007576 v8::ExtensionConfiguration config(2, exts);
7577 LocalContext context(&config);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007578 CHECK(
7579 v8_str("undefinedACBDE")
7580 ->Equals(context.local(), context->Global()
7581 ->Get(context.local(), v8_str("loaded"))
7582 .ToLocalChecked())
7583 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00007584}
7585
7586
7587static const char* kExtensionTestScript =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007588 "native function A();"
7589 "native function B();"
7590 "native function C();"
7591 "function Foo(i) {"
7592 " if (i == 0) return A();"
7593 " if (i == 1) return B();"
7594 " if (i == 2) return C();"
7595 "}";
Steve Blocka7e24c12009-10-30 11:49:00 +00007596
7597
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007598static void CallFun(const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +00007599 ApiTestFuzzer::Fuzz();
Leon Clarkee46be812010-01-19 14:06:41 +00007600 if (args.IsConstructCall()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007601 CHECK(args.This()
7602 ->Set(args.GetIsolate()->GetCurrentContext(), v8_str("data"),
7603 args.Data())
7604 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007605 args.GetReturnValue().SetNull();
7606 return;
Leon Clarkee46be812010-01-19 14:06:41 +00007607 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007608 args.GetReturnValue().Set(args.Data());
Steve Blocka7e24c12009-10-30 11:49:00 +00007609}
7610
7611
7612class FunctionExtension : public Extension {
7613 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007614 FunctionExtension() : Extension("functiontest", kExtensionTestScript) {}
7615 virtual v8::Local<v8::FunctionTemplate> GetNativeFunctionTemplate(
7616 v8::Isolate* isolate, v8::Local<String> name);
Steve Blocka7e24c12009-10-30 11:49:00 +00007617};
7618
7619
7620static int lookup_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007621v8::Local<v8::FunctionTemplate> FunctionExtension::GetNativeFunctionTemplate(
7622 v8::Isolate* isolate, v8::Local<String> name) {
Steve Blocka7e24c12009-10-30 11:49:00 +00007623 lookup_count++;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007624 if (name->Equals(isolate->GetCurrentContext(), v8_str("A")).FromJust()) {
7625 return v8::FunctionTemplate::New(isolate, CallFun,
7626 v8::Integer::New(isolate, 8));
7627 } else if (name->Equals(isolate->GetCurrentContext(), v8_str("B"))
7628 .FromJust()) {
7629 return v8::FunctionTemplate::New(isolate, CallFun,
7630 v8::Integer::New(isolate, 7));
7631 } else if (name->Equals(isolate->GetCurrentContext(), v8_str("C"))
7632 .FromJust()) {
7633 return v8::FunctionTemplate::New(isolate, CallFun,
7634 v8::Integer::New(isolate, 6));
Steve Blocka7e24c12009-10-30 11:49:00 +00007635 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007636 return v8::Local<v8::FunctionTemplate>();
Steve Blocka7e24c12009-10-30 11:49:00 +00007637 }
7638}
7639
7640
7641THREADED_TEST(FunctionLookup) {
7642 v8::RegisterExtension(new FunctionExtension());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007643 v8::HandleScope handle_scope(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007644 static const char* exts[1] = {"functiontest"};
Steve Blocka7e24c12009-10-30 11:49:00 +00007645 v8::ExtensionConfiguration config(1, exts);
7646 LocalContext context(&config);
7647 CHECK_EQ(3, lookup_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007648 CHECK(v8::Integer::New(CcTest::isolate(), 8)
7649 ->Equals(context.local(), CompileRun("Foo(0)"))
7650 .FromJust());
7651 CHECK(v8::Integer::New(CcTest::isolate(), 7)
7652 ->Equals(context.local(), CompileRun("Foo(1)"))
7653 .FromJust());
7654 CHECK(v8::Integer::New(CcTest::isolate(), 6)
7655 ->Equals(context.local(), CompileRun("Foo(2)"))
7656 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00007657}
7658
7659
Leon Clarkee46be812010-01-19 14:06:41 +00007660THREADED_TEST(NativeFunctionConstructCall) {
7661 v8::RegisterExtension(new FunctionExtension());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007662 v8::HandleScope handle_scope(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007663 static const char* exts[1] = {"functiontest"};
Leon Clarkee46be812010-01-19 14:06:41 +00007664 v8::ExtensionConfiguration config(1, exts);
7665 LocalContext context(&config);
Leon Clarked91b9f72010-01-27 17:25:45 +00007666 for (int i = 0; i < 10; i++) {
7667 // Run a few times to ensure that allocation of objects doesn't
7668 // change behavior of a constructor function.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007669 CHECK(v8::Integer::New(CcTest::isolate(), 8)
7670 ->Equals(context.local(), CompileRun("(new A()).data"))
7671 .FromJust());
7672 CHECK(v8::Integer::New(CcTest::isolate(), 7)
7673 ->Equals(context.local(), CompileRun("(new B()).data"))
7674 .FromJust());
7675 CHECK(v8::Integer::New(CcTest::isolate(), 6)
7676 ->Equals(context.local(), CompileRun("(new C()).data"))
7677 .FromJust());
Leon Clarked91b9f72010-01-27 17:25:45 +00007678 }
Leon Clarkee46be812010-01-19 14:06:41 +00007679}
7680
7681
Steve Blocka7e24c12009-10-30 11:49:00 +00007682static const char* last_location;
7683static const char* last_message;
7684void StoringErrorCallback(const char* location, const char* message) {
7685 if (last_location == NULL) {
7686 last_location = location;
7687 last_message = message;
7688 }
7689}
7690
7691
7692// ErrorReporting creates a circular extensions configuration and
7693// tests that the fatal error handler gets called. This renders V8
7694// unusable and therefore this test cannot be run in parallel.
7695TEST(ErrorReporting) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007696 CcTest::isolate()->SetFatalErrorHandler(StoringErrorCallback);
7697 static const char* aDeps[] = {"B"};
Steve Blocka7e24c12009-10-30 11:49:00 +00007698 v8::RegisterExtension(new Extension("A", "", 1, aDeps));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007699 static const char* bDeps[] = {"A"};
Steve Blocka7e24c12009-10-30 11:49:00 +00007700 v8::RegisterExtension(new Extension("B", "", 1, bDeps));
7701 last_location = NULL;
7702 v8::ExtensionConfiguration config(1, bDeps);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007703 v8::Local<Context> context = Context::New(CcTest::isolate(), &config);
Steve Blocka7e24c12009-10-30 11:49:00 +00007704 CHECK(context.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007705 CHECK(last_location);
Steve Blocka7e24c12009-10-30 11:49:00 +00007706}
7707
7708
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007709static void MissingScriptInfoMessageListener(v8::Local<v8::Message> message,
7710 v8::Local<Value> data) {
7711 v8::Isolate* isolate = CcTest::isolate();
7712 Local<Context> context = isolate->GetCurrentContext();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007713 CHECK(message->GetScriptOrigin().ResourceName()->IsUndefined());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007714 CHECK(v8::Undefined(isolate)
7715 ->Equals(context, message->GetScriptOrigin().ResourceName())
7716 .FromJust());
7717 message->GetLineNumber(context).FromJust();
7718 message->GetSourceLine(context).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00007719}
7720
7721
7722THREADED_TEST(ErrorWithMissingScriptInfo) {
Steve Blocka7e24c12009-10-30 11:49:00 +00007723 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007724 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007725 context->GetIsolate()->AddMessageListener(MissingScriptInfoMessageListener);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007726 CompileRun("throw Error()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007727 context->GetIsolate()->RemoveMessageListeners(
7728 MissingScriptInfoMessageListener);
Steve Blocka7e24c12009-10-30 11:49:00 +00007729}
7730
7731
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007732struct FlagAndPersistent {
7733 bool flag;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007734 v8::Global<v8::Object> handle;
Steve Blocka7e24c12009-10-30 11:49:00 +00007735};
7736
Steve Blocka7e24c12009-10-30 11:49:00 +00007737
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007738static void SetFlag(const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007739 data.GetParameter()->flag = true;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007740 data.GetParameter()->handle.Reset();
Steve Blockd0582a62009-12-15 09:54:21 +00007741}
7742
Steve Blockd0582a62009-12-15 09:54:21 +00007743
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007744static void IndependentWeakHandle(bool global_gc, bool interlinked) {
7745 v8::Isolate* iso = CcTest::isolate();
7746 v8::HandleScope scope(iso);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007747 v8::Local<Context> context = Context::New(iso);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007748 Context::Scope context_scope(context);
7749
7750 FlagAndPersistent object_a, object_b;
7751
7752 intptr_t big_heap_size;
7753
7754 {
7755 v8::HandleScope handle_scope(iso);
7756 Local<Object> a(v8::Object::New(iso));
7757 Local<Object> b(v8::Object::New(iso));
7758 object_a.handle.Reset(iso, a);
7759 object_b.handle.Reset(iso, b);
7760 if (interlinked) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007761 a->Set(context, v8_str("x"), b).FromJust();
7762 b->Set(context, v8_str("x"), a).FromJust();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007763 }
7764 if (global_gc) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007765 CcTest::heap()->CollectAllGarbage();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007766 } else {
7767 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
7768 }
7769 // We are relying on this creating a big flag array and reserving the space
7770 // up front.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007771 v8::Local<Value> big_array = CompileRun("new Array(5000)");
7772 a->Set(context, v8_str("y"), big_array).FromJust();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007773 big_heap_size = CcTest::heap()->SizeOfObjects();
7774 }
7775
7776 object_a.flag = false;
7777 object_b.flag = false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007778 object_a.handle.SetWeak(&object_a, &SetFlag,
7779 v8::WeakCallbackType::kParameter);
7780 object_b.handle.SetWeak(&object_b, &SetFlag,
7781 v8::WeakCallbackType::kParameter);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007782 CHECK(!object_b.handle.IsIndependent());
7783 object_a.handle.MarkIndependent();
7784 object_b.handle.MarkIndependent();
7785 CHECK(object_b.handle.IsIndependent());
7786 if (global_gc) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007787 CcTest::heap()->CollectAllGarbage();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007788 } else {
7789 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
7790 }
7791 // A single GC should be enough to reclaim the memory, since we are using
7792 // phantom handles.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007793 CHECK_LT(CcTest::heap()->SizeOfObjects(), big_heap_size - 20000);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007794 CHECK(object_a.flag);
7795 CHECK(object_b.flag);
7796}
7797
7798
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007799TEST(IndependentWeakHandle) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007800 IndependentWeakHandle(false, false);
7801 IndependentWeakHandle(false, true);
7802 IndependentWeakHandle(true, false);
7803 IndependentWeakHandle(true, true);
7804}
7805
7806
7807class Trivial {
7808 public:
7809 explicit Trivial(int x) : x_(x) {}
7810
7811 int x() { return x_; }
7812 void set_x(int x) { x_ = x; }
7813
7814 private:
7815 int x_;
7816};
7817
7818
7819class Trivial2 {
7820 public:
7821 Trivial2(int x, int y) : y_(y), x_(x) {}
7822
7823 int x() { return x_; }
7824 void set_x(int x) { x_ = x; }
7825
7826 int y() { return y_; }
7827 void set_y(int y) { y_ = y; }
7828
7829 private:
7830 int y_;
7831 int x_;
7832};
7833
7834
7835void CheckInternalFields(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007836 const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
7837 v8::Persistent<v8::Object>* handle = data.GetParameter();
7838 handle->Reset();
7839 Trivial* t1 = reinterpret_cast<Trivial*>(data.GetInternalField(0));
7840 Trivial2* t2 = reinterpret_cast<Trivial2*>(data.GetInternalField(1));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007841 CHECK_EQ(42, t1->x());
7842 CHECK_EQ(103, t2->x());
7843 t1->set_x(1729);
7844 t2->set_x(33550336);
7845}
7846
7847
7848void InternalFieldCallback(bool global_gc) {
7849 LocalContext env;
7850 v8::Isolate* isolate = env->GetIsolate();
7851 v8::HandleScope scope(isolate);
7852
7853 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
7854 Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
7855 Trivial* t1;
7856 Trivial2* t2;
7857 instance_templ->SetInternalFieldCount(2);
7858 {
7859 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007860 Local<v8::Object> obj = templ->GetFunction(env.local())
7861 .ToLocalChecked()
7862 ->NewInstance(env.local())
7863 .ToLocalChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007864 v8::Persistent<v8::Object> handle(isolate, obj);
7865 CHECK_EQ(2, obj->InternalFieldCount());
7866 CHECK(obj->GetInternalField(0)->IsUndefined());
7867 t1 = new Trivial(42);
7868 t2 = new Trivial2(103, 9);
7869
7870 obj->SetAlignedPointerInInternalField(0, t1);
7871 t1 = reinterpret_cast<Trivial*>(obj->GetAlignedPointerFromInternalField(0));
7872 CHECK_EQ(42, t1->x());
7873
7874 obj->SetAlignedPointerInInternalField(1, t2);
7875 t2 =
7876 reinterpret_cast<Trivial2*>(obj->GetAlignedPointerFromInternalField(1));
7877 CHECK_EQ(103, t2->x());
7878
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007879 handle.SetWeak<v8::Persistent<v8::Object>>(
7880 &handle, CheckInternalFields, v8::WeakCallbackType::kInternalFields);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007881 if (!global_gc) {
7882 handle.MarkIndependent();
7883 }
7884 }
7885 if (global_gc) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007886 CcTest::heap()->CollectAllGarbage();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007887 } else {
7888 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
7889 }
7890
7891 CHECK_EQ(1729, t1->x());
7892 CHECK_EQ(33550336, t2->x());
7893
7894 delete t1;
7895 delete t2;
7896}
7897
7898
7899THREADED_TEST(InternalFieldCallback) {
7900 InternalFieldCallback(false);
7901 InternalFieldCallback(true);
7902}
7903
7904
7905static void ResetUseValueAndSetFlag(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007906 const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007907 // Blink will reset the handle, and then use the other handle, so they
7908 // can't use the same backing slot.
7909 data.GetParameter()->handle.Reset();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007910 data.GetParameter()->flag = true;
7911}
7912
7913
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007914void v8::internal::HeapTester::ResetWeakHandle(bool global_gc) {
7915 using v8::Context;
7916 using v8::Local;
7917 using v8::Object;
7918
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007919 v8::Isolate* iso = CcTest::isolate();
7920 v8::HandleScope scope(iso);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007921 v8::Local<Context> context = Context::New(iso);
Steve Blockd0582a62009-12-15 09:54:21 +00007922 Context::Scope context_scope(context);
7923
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007924 FlagAndPersistent object_a, object_b;
Steve Blockd0582a62009-12-15 09:54:21 +00007925
7926 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007927 v8::HandleScope handle_scope(iso);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007928 Local<Object> a(v8::Object::New(iso));
7929 Local<Object> b(v8::Object::New(iso));
7930 object_a.handle.Reset(iso, a);
7931 object_b.handle.Reset(iso, b);
7932 if (global_gc) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007933 CcTest::heap()->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007934 } else {
7935 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
7936 }
Steve Blockd0582a62009-12-15 09:54:21 +00007937 }
7938
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007939 object_a.flag = false;
7940 object_b.flag = false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007941 object_a.handle.SetWeak(&object_a, &ResetUseValueAndSetFlag,
7942 v8::WeakCallbackType::kParameter);
7943 object_b.handle.SetWeak(&object_b, &ResetUseValueAndSetFlag,
7944 v8::WeakCallbackType::kParameter);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007945 if (!global_gc) {
7946 object_a.handle.MarkIndependent();
7947 object_b.handle.MarkIndependent();
7948 CHECK(object_b.handle.IsIndependent());
7949 }
7950 if (global_gc) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007951 CcTest::heap()->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007952 } else {
7953 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
7954 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007955 CHECK(object_a.flag);
7956 CHECK(object_b.flag);
Ben Murdoch257744e2011-11-30 15:57:28 +00007957}
Steve Blockd0582a62009-12-15 09:54:21 +00007958
Ben Murdoch257744e2011-11-30 15:57:28 +00007959
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007960THREADED_HEAP_TEST(ResetWeakHandle) {
7961 v8::internal::HeapTester::ResetWeakHandle(false);
7962 v8::internal::HeapTester::ResetWeakHandle(true);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007963}
7964
7965
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007966static void InvokeScavenge() { CcTest::heap()->CollectGarbage(i::NEW_SPACE); }
Ben Murdoch257744e2011-11-30 15:57:28 +00007967
7968
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007969static void InvokeMarkSweep() { CcTest::heap()->CollectAllGarbage(); }
Ben Murdoch257744e2011-11-30 15:57:28 +00007970
7971
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007972static void ForceScavenge2(
7973 const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007974 data.GetParameter()->flag = true;
Ben Murdoch257744e2011-11-30 15:57:28 +00007975 InvokeScavenge();
7976}
7977
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007978static void ForceScavenge1(
7979 const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007980 data.GetParameter()->handle.Reset();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007981 data.SetSecondPassCallback(ForceScavenge2);
7982}
7983
7984
7985static void ForceMarkSweep2(
7986 const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007987 data.GetParameter()->flag = true;
Ben Murdoch257744e2011-11-30 15:57:28 +00007988 InvokeMarkSweep();
7989}
7990
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007991static void ForceMarkSweep1(
7992 const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
7993 data.GetParameter()->handle.Reset();
7994 data.SetSecondPassCallback(ForceMarkSweep2);
7995}
7996
Ben Murdoch257744e2011-11-30 15:57:28 +00007997
7998THREADED_TEST(GCFromWeakCallbacks) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007999 v8::Isolate* isolate = CcTest::isolate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008000 v8::Locker locker(CcTest::isolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008001 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008002 v8::Local<Context> context = Context::New(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +00008003 Context::Scope context_scope(context);
8004
8005 static const int kNumberOfGCTypes = 2;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008006 typedef v8::WeakCallbackInfo<FlagAndPersistent>::Callback Callback;
8007 Callback gc_forcing_callback[kNumberOfGCTypes] = {&ForceScavenge1,
8008 &ForceMarkSweep1};
Ben Murdoch257744e2011-11-30 15:57:28 +00008009
8010 typedef void (*GCInvoker)();
8011 GCInvoker invoke_gc[kNumberOfGCTypes] = {&InvokeScavenge, &InvokeMarkSweep};
8012
8013 for (int outer_gc = 0; outer_gc < kNumberOfGCTypes; outer_gc++) {
8014 for (int inner_gc = 0; inner_gc < kNumberOfGCTypes; inner_gc++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008015 FlagAndPersistent object;
Ben Murdoch257744e2011-11-30 15:57:28 +00008016 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008017 v8::HandleScope handle_scope(isolate);
8018 object.handle.Reset(isolate, v8::Object::New(isolate));
Ben Murdoch257744e2011-11-30 15:57:28 +00008019 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008020 object.flag = false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008021 object.handle.SetWeak(&object, gc_forcing_callback[inner_gc],
8022 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008023 object.handle.MarkIndependent();
Ben Murdoch257744e2011-11-30 15:57:28 +00008024 invoke_gc[outer_gc]();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008025 EmptyMessageQueues(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008026 CHECK(object.flag);
Ben Murdoch257744e2011-11-30 15:57:28 +00008027 }
Steve Blockd0582a62009-12-15 09:54:21 +00008028 }
Ben Murdoch257744e2011-11-30 15:57:28 +00008029}
8030
8031
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008032v8::Local<Function> args_fun;
Steve Blocka7e24c12009-10-30 11:49:00 +00008033
8034
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008035static void ArgumentsTestCallback(
8036 const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +00008037 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008038 v8::Isolate* isolate = args.GetIsolate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008039 Local<Context> context = isolate->GetCurrentContext();
Steve Blocka7e24c12009-10-30 11:49:00 +00008040 CHECK_EQ(3, args.Length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008041 CHECK(v8::Integer::New(isolate, 1)->Equals(context, args[0]).FromJust());
8042 CHECK(v8::Integer::New(isolate, 2)->Equals(context, args[1]).FromJust());
8043 CHECK(v8::Integer::New(isolate, 3)->Equals(context, args[2]).FromJust());
8044 CHECK(v8::Undefined(isolate)->Equals(context, args[3]).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008045 v8::HandleScope scope(args.GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008046 CcTest::heap()->CollectAllGarbage();
Steve Blocka7e24c12009-10-30 11:49:00 +00008047}
8048
8049
8050THREADED_TEST(Arguments) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008051 v8::Isolate* isolate = CcTest::isolate();
8052 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008053 v8::Local<v8::ObjectTemplate> global = ObjectTemplate::New(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008054 global->Set(v8_str("f"),
8055 v8::FunctionTemplate::New(isolate, ArgumentsTestCallback));
Steve Blocka7e24c12009-10-30 11:49:00 +00008056 LocalContext context(NULL, global);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008057 args_fun = context->Global()
8058 ->Get(context.local(), v8_str("f"))
8059 .ToLocalChecked()
8060 .As<Function>();
8061 v8_compile("f(1, 2, 3)")->Run(context.local()).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00008062}
8063
8064
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008065static int p_getter_count;
8066static int p_getter_count2;
Steve Blocka7e24c12009-10-30 11:49:00 +00008067
8068
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008069static void PGetter(Local<Name> name,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008070 const v8::PropertyCallbackInfo<v8::Value>& info) {
Steve Blocka7e24c12009-10-30 11:49:00 +00008071 ApiTestFuzzer::Fuzz();
8072 p_getter_count++;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008073 v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
8074 v8::Local<v8::Object> global = context->Global();
8075 CHECK(
8076 info.Holder()
8077 ->Equals(context, global->Get(context, v8_str("o1")).ToLocalChecked())
8078 .FromJust());
8079 if (name->Equals(context, v8_str("p1")).FromJust()) {
8080 CHECK(info.This()
8081 ->Equals(context,
8082 global->Get(context, v8_str("o1")).ToLocalChecked())
8083 .FromJust());
8084 } else if (name->Equals(context, v8_str("p2")).FromJust()) {
8085 CHECK(info.This()
8086 ->Equals(context,
8087 global->Get(context, v8_str("o2")).ToLocalChecked())
8088 .FromJust());
8089 } else if (name->Equals(context, v8_str("p3")).FromJust()) {
8090 CHECK(info.This()
8091 ->Equals(context,
8092 global->Get(context, v8_str("o3")).ToLocalChecked())
8093 .FromJust());
8094 } else if (name->Equals(context, v8_str("p4")).FromJust()) {
8095 CHECK(info.This()
8096 ->Equals(context,
8097 global->Get(context, v8_str("o4")).ToLocalChecked())
8098 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00008099 }
Steve Blocka7e24c12009-10-30 11:49:00 +00008100}
8101
8102
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008103static void RunHolderTest(v8::Local<v8::ObjectTemplate> obj) {
Steve Blocka7e24c12009-10-30 11:49:00 +00008104 ApiTestFuzzer::Fuzz();
8105 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008106 CHECK(context->Global()
8107 ->Set(context.local(), v8_str("o1"),
8108 obj->NewInstance(context.local()).ToLocalChecked())
8109 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00008110 CompileRun(
8111 "o1.__proto__ = { };"
8112 "var o2 = { __proto__: o1 };"
8113 "var o3 = { __proto__: o2 };"
8114 "var o4 = { __proto__: o3 };"
8115 "for (var i = 0; i < 10; i++) o4.p4;"
8116 "for (var i = 0; i < 10; i++) o3.p3;"
8117 "for (var i = 0; i < 10; i++) o2.p2;"
8118 "for (var i = 0; i < 10; i++) o1.p1;");
8119}
8120
8121
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008122static void PGetter2(Local<Name> name,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008123 const v8::PropertyCallbackInfo<v8::Value>& info) {
Steve Blocka7e24c12009-10-30 11:49:00 +00008124 ApiTestFuzzer::Fuzz();
8125 p_getter_count2++;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008126 v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
8127 v8::Local<v8::Object> global = context->Global();
8128 CHECK(
8129 info.Holder()
8130 ->Equals(context, global->Get(context, v8_str("o1")).ToLocalChecked())
8131 .FromJust());
8132 if (name->Equals(context, v8_str("p1")).FromJust()) {
8133 CHECK(info.This()
8134 ->Equals(context,
8135 global->Get(context, v8_str("o1")).ToLocalChecked())
8136 .FromJust());
8137 } else if (name->Equals(context, v8_str("p2")).FromJust()) {
8138 CHECK(info.This()
8139 ->Equals(context,
8140 global->Get(context, v8_str("o2")).ToLocalChecked())
8141 .FromJust());
8142 } else if (name->Equals(context, v8_str("p3")).FromJust()) {
8143 CHECK(info.This()
8144 ->Equals(context,
8145 global->Get(context, v8_str("o3")).ToLocalChecked())
8146 .FromJust());
8147 } else if (name->Equals(context, v8_str("p4")).FromJust()) {
8148 CHECK(info.This()
8149 ->Equals(context,
8150 global->Get(context, v8_str("o4")).ToLocalChecked())
8151 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00008152 }
Steve Blocka7e24c12009-10-30 11:49:00 +00008153}
8154
8155
8156THREADED_TEST(GetterHolders) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008157 v8::Isolate* isolate = CcTest::isolate();
8158 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008159 v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00008160 obj->SetAccessor(v8_str("p1"), PGetter);
8161 obj->SetAccessor(v8_str("p2"), PGetter);
8162 obj->SetAccessor(v8_str("p3"), PGetter);
8163 obj->SetAccessor(v8_str("p4"), PGetter);
8164 p_getter_count = 0;
8165 RunHolderTest(obj);
8166 CHECK_EQ(40, p_getter_count);
8167}
8168
8169
8170THREADED_TEST(PreInterceptorHolders) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008171 v8::Isolate* isolate = CcTest::isolate();
8172 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008173 v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008174 obj->SetHandler(v8::NamedPropertyHandlerConfiguration(PGetter2));
Steve Blocka7e24c12009-10-30 11:49:00 +00008175 p_getter_count2 = 0;
8176 RunHolderTest(obj);
8177 CHECK_EQ(40, p_getter_count2);
8178}
8179
8180
8181THREADED_TEST(ObjectInstantiation) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008182 v8::Isolate* isolate = CcTest::isolate();
8183 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008184 v8::Local<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00008185 templ->SetAccessor(v8_str("t"), PGetter2);
8186 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008187 CHECK(context->Global()
8188 ->Set(context.local(), v8_str("o"),
8189 templ->NewInstance(context.local()).ToLocalChecked())
8190 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00008191 for (int i = 0; i < 100; i++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008192 v8::HandleScope inner_scope(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008193 v8::Local<v8::Object> obj =
8194 templ->NewInstance(context.local()).ToLocalChecked();
8195 CHECK(!obj->Equals(context.local(), context->Global()
8196 ->Get(context.local(), v8_str("o"))
8197 .ToLocalChecked())
8198 .FromJust());
8199 CHECK(
8200 context->Global()->Set(context.local(), v8_str("o2"), obj).FromJust());
8201 v8::Local<Value> value = CompileRun("o.__proto__ === o2.__proto__");
8202 CHECK(v8::True(isolate)->Equals(context.local(), value).FromJust());
8203 CHECK(context->Global()->Set(context.local(), v8_str("o"), obj).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00008204 }
8205}
8206
8207
Ben Murdochb0fe1622011-05-05 13:52:32 +01008208static int StrCmp16(uint16_t* a, uint16_t* b) {
8209 while (true) {
8210 if (*a == 0 && *b == 0) return 0;
8211 if (*a != *b) return 0 + *a - *b;
8212 a++;
8213 b++;
8214 }
8215}
8216
8217
8218static int StrNCmp16(uint16_t* a, uint16_t* b, int n) {
8219 while (true) {
8220 if (n-- == 0) return 0;
8221 if (*a == 0 && *b == 0) return 0;
8222 if (*a != *b) return 0 + *a - *b;
8223 a++;
8224 b++;
8225 }
8226}
8227
8228
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008229int GetUtf8Length(Local<String> str) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008230 int len = str->Utf8Length();
8231 if (len < 0) {
8232 i::Handle<i::String> istr(v8::Utils::OpenHandle(*str));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008233 i::String::Flatten(istr);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008234 len = str->Utf8Length();
8235 }
8236 return len;
8237}
8238
8239
Steve Blocka7e24c12009-10-30 11:49:00 +00008240THREADED_TEST(StringWrite) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008241 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008242 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008243 v8::Local<String> str = v8_str("abcde");
Ben Murdochb0fe1622011-05-05 13:52:32 +01008244 // abc<Icelandic eth><Unicode snowman>.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008245 v8::Local<String> str2 = v8_str("abc\303\260\342\230\203");
8246 v8::Local<String> str3 =
8247 v8::String::NewFromUtf8(context->GetIsolate(), "abc\0def",
8248 v8::NewStringType::kNormal, 7)
8249 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008250 // "ab" + lead surrogate + "cd" + trail surrogate + "ef"
8251 uint16_t orphans[8] = { 0x61, 0x62, 0xd800, 0x63, 0x64, 0xdc00, 0x65, 0x66 };
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008252 v8::Local<String> orphans_str =
8253 v8::String::NewFromTwoByte(context->GetIsolate(), orphans,
8254 v8::NewStringType::kNormal, 8)
8255 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008256 // single lead surrogate
8257 uint16_t lead[1] = { 0xd800 };
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008258 v8::Local<String> lead_str =
8259 v8::String::NewFromTwoByte(context->GetIsolate(), lead,
8260 v8::NewStringType::kNormal, 1)
8261 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008262 // single trail surrogate
8263 uint16_t trail[1] = { 0xdc00 };
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008264 v8::Local<String> trail_str =
8265 v8::String::NewFromTwoByte(context->GetIsolate(), trail,
8266 v8::NewStringType::kNormal, 1)
8267 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008268 // surrogate pair
8269 uint16_t pair[2] = { 0xd800, 0xdc00 };
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008270 v8::Local<String> pair_str =
8271 v8::String::NewFromTwoByte(context->GetIsolate(), pair,
8272 v8::NewStringType::kNormal, 2)
8273 .ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008274 const int kStride = 4; // Must match stride in for loops in JS below.
8275 CompileRun(
8276 "var left = '';"
8277 "for (var i = 0; i < 0xd800; i += 4) {"
8278 " left = left + String.fromCharCode(i);"
8279 "}");
8280 CompileRun(
8281 "var right = '';"
8282 "for (var i = 0; i < 0xd800; i += 4) {"
8283 " right = String.fromCharCode(i) + right;"
8284 "}");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008285 v8::Local<v8::Object> global = context->Global();
8286 Local<String> left_tree = global->Get(context.local(), v8_str("left"))
8287 .ToLocalChecked()
8288 .As<String>();
8289 Local<String> right_tree = global->Get(context.local(), v8_str("right"))
8290 .ToLocalChecked()
8291 .As<String>();
Ben Murdochb0fe1622011-05-05 13:52:32 +01008292
8293 CHECK_EQ(5, str2->Length());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008294 CHECK_EQ(0xd800 / kStride, left_tree->Length());
8295 CHECK_EQ(0xd800 / kStride, right_tree->Length());
Steve Blocka7e24c12009-10-30 11:49:00 +00008296
8297 char buf[100];
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008298 char utf8buf[0xd800 * 3];
Ben Murdochb0fe1622011-05-05 13:52:32 +01008299 uint16_t wbuf[100];
Steve Blocka7e24c12009-10-30 11:49:00 +00008300 int len;
Ben Murdochb0fe1622011-05-05 13:52:32 +01008301 int charlen;
8302
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008303 memset(utf8buf, 0x1, 1000);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008304 len = str2->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen);
Steve Block44f0eee2011-05-26 01:26:41 +01008305 CHECK_EQ(9, len);
8306 CHECK_EQ(5, charlen);
8307 CHECK_EQ(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008308
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008309 memset(utf8buf, 0x1, 1000);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008310 len = str2->WriteUtf8(utf8buf, 8, &charlen);
Steve Block44f0eee2011-05-26 01:26:41 +01008311 CHECK_EQ(8, len);
8312 CHECK_EQ(5, charlen);
8313 CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\342\230\203\1", 9));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008314
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008315 memset(utf8buf, 0x1, 1000);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008316 len = str2->WriteUtf8(utf8buf, 7, &charlen);
Steve Block44f0eee2011-05-26 01:26:41 +01008317 CHECK_EQ(5, len);
8318 CHECK_EQ(4, charlen);
8319 CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008320
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008321 memset(utf8buf, 0x1, 1000);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008322 len = str2->WriteUtf8(utf8buf, 6, &charlen);
Steve Block44f0eee2011-05-26 01:26:41 +01008323 CHECK_EQ(5, len);
8324 CHECK_EQ(4, charlen);
8325 CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008326
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008327 memset(utf8buf, 0x1, 1000);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008328 len = str2->WriteUtf8(utf8buf, 5, &charlen);
Steve Block44f0eee2011-05-26 01:26:41 +01008329 CHECK_EQ(5, len);
8330 CHECK_EQ(4, charlen);
8331 CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008332
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008333 memset(utf8buf, 0x1, 1000);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008334 len = str2->WriteUtf8(utf8buf, 4, &charlen);
Steve Block44f0eee2011-05-26 01:26:41 +01008335 CHECK_EQ(3, len);
8336 CHECK_EQ(3, charlen);
8337 CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008338
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008339 memset(utf8buf, 0x1, 1000);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008340 len = str2->WriteUtf8(utf8buf, 3, &charlen);
Steve Block44f0eee2011-05-26 01:26:41 +01008341 CHECK_EQ(3, len);
8342 CHECK_EQ(3, charlen);
8343 CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008344
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008345 memset(utf8buf, 0x1, 1000);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008346 len = str2->WriteUtf8(utf8buf, 2, &charlen);
Steve Block44f0eee2011-05-26 01:26:41 +01008347 CHECK_EQ(2, len);
8348 CHECK_EQ(2, charlen);
8349 CHECK_EQ(0, strncmp(utf8buf, "ab\1", 3));
Steve Blocka7e24c12009-10-30 11:49:00 +00008350
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008351 // allow orphan surrogates by default
8352 memset(utf8buf, 0x1, 1000);
8353 len = orphans_str->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen);
8354 CHECK_EQ(13, len);
8355 CHECK_EQ(8, charlen);
8356 CHECK_EQ(0, strcmp(utf8buf, "ab\355\240\200cd\355\260\200ef"));
8357
8358 // replace orphan surrogates with unicode replacement character
8359 memset(utf8buf, 0x1, 1000);
8360 len = orphans_str->WriteUtf8(utf8buf,
8361 sizeof(utf8buf),
8362 &charlen,
8363 String::REPLACE_INVALID_UTF8);
8364 CHECK_EQ(13, len);
8365 CHECK_EQ(8, charlen);
8366 CHECK_EQ(0, strcmp(utf8buf, "ab\357\277\275cd\357\277\275ef"));
8367
8368 // replace single lead surrogate with unicode replacement character
8369 memset(utf8buf, 0x1, 1000);
8370 len = lead_str->WriteUtf8(utf8buf,
8371 sizeof(utf8buf),
8372 &charlen,
8373 String::REPLACE_INVALID_UTF8);
8374 CHECK_EQ(4, len);
8375 CHECK_EQ(1, charlen);
8376 CHECK_EQ(0, strcmp(utf8buf, "\357\277\275"));
8377
8378 // replace single trail surrogate with unicode replacement character
8379 memset(utf8buf, 0x1, 1000);
8380 len = trail_str->WriteUtf8(utf8buf,
8381 sizeof(utf8buf),
8382 &charlen,
8383 String::REPLACE_INVALID_UTF8);
8384 CHECK_EQ(4, len);
8385 CHECK_EQ(1, charlen);
8386 CHECK_EQ(0, strcmp(utf8buf, "\357\277\275"));
8387
8388 // do not replace / write anything if surrogate pair does not fit the buffer
8389 // space
8390 memset(utf8buf, 0x1, 1000);
8391 len = pair_str->WriteUtf8(utf8buf,
8392 3,
8393 &charlen,
8394 String::REPLACE_INVALID_UTF8);
8395 CHECK_EQ(0, len);
8396 CHECK_EQ(0, charlen);
8397
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008398 memset(utf8buf, 0x1, sizeof(utf8buf));
8399 len = GetUtf8Length(left_tree);
8400 int utf8_expected =
8401 (0x80 + (0x800 - 0x80) * 2 + (0xd800 - 0x800) * 3) / kStride;
8402 CHECK_EQ(utf8_expected, len);
8403 len = left_tree->WriteUtf8(utf8buf, utf8_expected, &charlen);
8404 CHECK_EQ(utf8_expected, len);
8405 CHECK_EQ(0xd800 / kStride, charlen);
8406 CHECK_EQ(0xed, static_cast<unsigned char>(utf8buf[utf8_expected - 3]));
8407 CHECK_EQ(0x9f, static_cast<unsigned char>(utf8buf[utf8_expected - 2]));
8408 CHECK_EQ(0xc0 - kStride,
8409 static_cast<unsigned char>(utf8buf[utf8_expected - 1]));
8410 CHECK_EQ(1, utf8buf[utf8_expected]);
8411
8412 memset(utf8buf, 0x1, sizeof(utf8buf));
8413 len = GetUtf8Length(right_tree);
8414 CHECK_EQ(utf8_expected, len);
8415 len = right_tree->WriteUtf8(utf8buf, utf8_expected, &charlen);
8416 CHECK_EQ(utf8_expected, len);
8417 CHECK_EQ(0xd800 / kStride, charlen);
8418 CHECK_EQ(0xed, static_cast<unsigned char>(utf8buf[0]));
8419 CHECK_EQ(0x9f, static_cast<unsigned char>(utf8buf[1]));
8420 CHECK_EQ(0xc0 - kStride, static_cast<unsigned char>(utf8buf[2]));
8421 CHECK_EQ(1, utf8buf[utf8_expected]);
8422
Steve Blocka7e24c12009-10-30 11:49:00 +00008423 memset(buf, 0x1, sizeof(buf));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008424 memset(wbuf, 0x1, sizeof(wbuf));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008425 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf));
Steve Block44f0eee2011-05-26 01:26:41 +01008426 CHECK_EQ(5, len);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008427 len = str->Write(wbuf);
Steve Block44f0eee2011-05-26 01:26:41 +01008428 CHECK_EQ(5, len);
8429 CHECK_EQ(0, strcmp("abcde", buf));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008430 uint16_t answer1[] = {'a', 'b', 'c', 'd', 'e', '\0'};
Steve Block44f0eee2011-05-26 01:26:41 +01008431 CHECK_EQ(0, StrCmp16(answer1, wbuf));
Steve Blocka7e24c12009-10-30 11:49:00 +00008432
8433 memset(buf, 0x1, sizeof(buf));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008434 memset(wbuf, 0x1, sizeof(wbuf));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008435 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 4);
Steve Block44f0eee2011-05-26 01:26:41 +01008436 CHECK_EQ(4, len);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008437 len = str->Write(wbuf, 0, 4);
Steve Block44f0eee2011-05-26 01:26:41 +01008438 CHECK_EQ(4, len);
8439 CHECK_EQ(0, strncmp("abcd\1", buf, 5));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008440 uint16_t answer2[] = {'a', 'b', 'c', 'd', 0x101};
Steve Block44f0eee2011-05-26 01:26:41 +01008441 CHECK_EQ(0, StrNCmp16(answer2, wbuf, 5));
Steve Blocka7e24c12009-10-30 11:49:00 +00008442
8443 memset(buf, 0x1, sizeof(buf));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008444 memset(wbuf, 0x1, sizeof(wbuf));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008445 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 5);
Steve Block44f0eee2011-05-26 01:26:41 +01008446 CHECK_EQ(5, len);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008447 len = str->Write(wbuf, 0, 5);
Steve Block44f0eee2011-05-26 01:26:41 +01008448 CHECK_EQ(5, len);
8449 CHECK_EQ(0, strncmp("abcde\1", buf, 6));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008450 uint16_t answer3[] = {'a', 'b', 'c', 'd', 'e', 0x101};
Steve Block44f0eee2011-05-26 01:26:41 +01008451 CHECK_EQ(0, StrNCmp16(answer3, wbuf, 6));
Steve Blocka7e24c12009-10-30 11:49:00 +00008452
8453 memset(buf, 0x1, sizeof(buf));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008454 memset(wbuf, 0x1, sizeof(wbuf));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008455 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 6);
Steve Block44f0eee2011-05-26 01:26:41 +01008456 CHECK_EQ(5, len);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008457 len = str->Write(wbuf, 0, 6);
Steve Block44f0eee2011-05-26 01:26:41 +01008458 CHECK_EQ(5, len);
8459 CHECK_EQ(0, strcmp("abcde", buf));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008460 uint16_t answer4[] = {'a', 'b', 'c', 'd', 'e', '\0'};
Steve Block44f0eee2011-05-26 01:26:41 +01008461 CHECK_EQ(0, StrCmp16(answer4, wbuf));
Steve Blocka7e24c12009-10-30 11:49:00 +00008462
8463 memset(buf, 0x1, sizeof(buf));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008464 memset(wbuf, 0x1, sizeof(wbuf));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008465 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, -1);
Steve Block44f0eee2011-05-26 01:26:41 +01008466 CHECK_EQ(1, len);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008467 len = str->Write(wbuf, 4, -1);
Steve Block44f0eee2011-05-26 01:26:41 +01008468 CHECK_EQ(1, len);
8469 CHECK_EQ(0, strcmp("e", buf));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008470 uint16_t answer5[] = {'e', '\0'};
Steve Block44f0eee2011-05-26 01:26:41 +01008471 CHECK_EQ(0, StrCmp16(answer5, wbuf));
Steve Blocka7e24c12009-10-30 11:49:00 +00008472
8473 memset(buf, 0x1, sizeof(buf));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008474 memset(wbuf, 0x1, sizeof(wbuf));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008475 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, 6);
Steve Block44f0eee2011-05-26 01:26:41 +01008476 CHECK_EQ(1, len);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008477 len = str->Write(wbuf, 4, 6);
Steve Block44f0eee2011-05-26 01:26:41 +01008478 CHECK_EQ(1, len);
8479 CHECK_EQ(0, strcmp("e", buf));
8480 CHECK_EQ(0, StrCmp16(answer5, wbuf));
Steve Blocka7e24c12009-10-30 11:49:00 +00008481
8482 memset(buf, 0x1, sizeof(buf));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008483 memset(wbuf, 0x1, sizeof(wbuf));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008484 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, 1);
Steve Block44f0eee2011-05-26 01:26:41 +01008485 CHECK_EQ(1, len);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008486 len = str->Write(wbuf, 4, 1);
Steve Block44f0eee2011-05-26 01:26:41 +01008487 CHECK_EQ(1, len);
8488 CHECK_EQ(0, strncmp("e\1", buf, 2));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008489 uint16_t answer6[] = {'e', 0x101};
Steve Block44f0eee2011-05-26 01:26:41 +01008490 CHECK_EQ(0, StrNCmp16(answer6, wbuf, 2));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008491
8492 memset(buf, 0x1, sizeof(buf));
8493 memset(wbuf, 0x1, sizeof(wbuf));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008494 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 3, 1);
Steve Block44f0eee2011-05-26 01:26:41 +01008495 CHECK_EQ(1, len);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008496 len = str->Write(wbuf, 3, 1);
Steve Block44f0eee2011-05-26 01:26:41 +01008497 CHECK_EQ(1, len);
8498 CHECK_EQ(0, strncmp("d\1", buf, 2));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008499 uint16_t answer7[] = {'d', 0x101};
Steve Block44f0eee2011-05-26 01:26:41 +01008500 CHECK_EQ(0, StrNCmp16(answer7, wbuf, 2));
Ben Murdoch69a99ed2011-11-30 16:03:39 +00008501
8502 memset(wbuf, 0x1, sizeof(wbuf));
8503 wbuf[5] = 'X';
8504 len = str->Write(wbuf, 0, 6, String::NO_NULL_TERMINATION);
8505 CHECK_EQ(5, len);
8506 CHECK_EQ('X', wbuf[5]);
8507 uint16_t answer8a[] = {'a', 'b', 'c', 'd', 'e'};
8508 uint16_t answer8b[] = {'a', 'b', 'c', 'd', 'e', '\0'};
8509 CHECK_EQ(0, StrNCmp16(answer8a, wbuf, 5));
8510 CHECK_NE(0, StrCmp16(answer8b, wbuf));
8511 wbuf[5] = '\0';
8512 CHECK_EQ(0, StrCmp16(answer8b, wbuf));
8513
8514 memset(buf, 0x1, sizeof(buf));
8515 buf[5] = 'X';
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008516 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf),
8517 0,
8518 6,
8519 String::NO_NULL_TERMINATION);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00008520 CHECK_EQ(5, len);
8521 CHECK_EQ('X', buf[5]);
8522 CHECK_EQ(0, strncmp("abcde", buf, 5));
8523 CHECK_NE(0, strcmp("abcde", buf));
8524 buf[5] = '\0';
8525 CHECK_EQ(0, strcmp("abcde", buf));
8526
8527 memset(utf8buf, 0x1, sizeof(utf8buf));
8528 utf8buf[8] = 'X';
8529 len = str2->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen,
8530 String::NO_NULL_TERMINATION);
8531 CHECK_EQ(8, len);
8532 CHECK_EQ('X', utf8buf[8]);
8533 CHECK_EQ(5, charlen);
8534 CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\342\230\203", 8));
8535 CHECK_NE(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
8536 utf8buf[8] = '\0';
8537 CHECK_EQ(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008538
8539 memset(utf8buf, 0x1, sizeof(utf8buf));
8540 utf8buf[5] = 'X';
8541 len = str->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen,
8542 String::NO_NULL_TERMINATION);
8543 CHECK_EQ(5, len);
8544 CHECK_EQ('X', utf8buf[5]); // Test that the sixth character is untouched.
8545 CHECK_EQ(5, charlen);
8546 utf8buf[5] = '\0';
8547 CHECK_EQ(0, strcmp(utf8buf, "abcde"));
8548
8549 memset(buf, 0x1, sizeof(buf));
8550 len = str3->WriteOneByte(reinterpret_cast<uint8_t*>(buf));
8551 CHECK_EQ(7, len);
8552 CHECK_EQ(0, strcmp("abc", buf));
8553 CHECK_EQ(0, buf[3]);
8554 CHECK_EQ(0, strcmp("def", buf + 4));
8555
8556 CHECK_EQ(0, str->WriteOneByte(NULL, 0, 0, String::NO_NULL_TERMINATION));
8557 CHECK_EQ(0, str->WriteUtf8(NULL, 0, 0, String::NO_NULL_TERMINATION));
8558 CHECK_EQ(0, str->Write(NULL, 0, 0, String::NO_NULL_TERMINATION));
Steve Blocka7e24c12009-10-30 11:49:00 +00008559}
8560
8561
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008562static void Utf16Helper(
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008563 LocalContext& context, // NOLINT
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008564 const char* name,
8565 const char* lengths_name,
8566 int len) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008567 Local<v8::Array> a = Local<v8::Array>::Cast(
8568 context->Global()->Get(context.local(), v8_str(name)).ToLocalChecked());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008569 Local<v8::Array> alens =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008570 Local<v8::Array>::Cast(context->Global()
8571 ->Get(context.local(), v8_str(lengths_name))
8572 .ToLocalChecked());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008573 for (int i = 0; i < len; i++) {
8574 Local<v8::String> string =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008575 Local<v8::String>::Cast(a->Get(context.local(), i).ToLocalChecked());
8576 Local<v8::Number> expected_len = Local<v8::Number>::Cast(
8577 alens->Get(context.local(), i).ToLocalChecked());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008578 int length = GetUtf8Length(string);
8579 CHECK_EQ(static_cast<int>(expected_len->Value()), length);
8580 }
8581}
8582
8583
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008584THREADED_TEST(Utf16) {
8585 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008586 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008587 CompileRun(
8588 "var pad = '01234567890123456789';"
8589 "var p = [];"
8590 "var plens = [20, 3, 3];"
8591 "p.push('01234567890123456789');"
8592 "var lead = 0xd800;"
8593 "var trail = 0xdc00;"
8594 "p.push(String.fromCharCode(0xd800));"
8595 "p.push(String.fromCharCode(0xdc00));"
8596 "var a = [];"
8597 "var b = [];"
8598 "var c = [];"
8599 "var alens = [];"
8600 "for (var i = 0; i < 3; i++) {"
8601 " p[1] = String.fromCharCode(lead++);"
8602 " for (var j = 0; j < 3; j++) {"
8603 " p[2] = String.fromCharCode(trail++);"
8604 " a.push(p[i] + p[j]);"
8605 " b.push(p[i] + p[j]);"
8606 " c.push(p[i] + p[j]);"
8607 " alens.push(plens[i] + plens[j]);"
8608 " }"
8609 "}"
8610 "alens[5] -= 2;" // Here the surrogate pairs match up.
8611 "var a2 = [];"
8612 "var b2 = [];"
8613 "var c2 = [];"
8614 "var a2lens = [];"
8615 "for (var m = 0; m < 9; m++) {"
8616 " for (var n = 0; n < 9; n++) {"
8617 " a2.push(a[m] + a[n]);"
8618 " b2.push(b[m] + b[n]);"
8619 " var newc = 'x' + c[m] + c[n] + 'y';"
8620 " c2.push(newc.substring(1, newc.length - 1));"
8621 " var utf = alens[m] + alens[n];" // And here.
8622 // The 'n's that start with 0xdc.. are 6-8
8623 // The 'm's that end with 0xd8.. are 1, 4 and 7
8624 " if ((m % 3) == 1 && n >= 6) utf -= 2;"
8625 " a2lens.push(utf);"
8626 " }"
8627 "}");
8628 Utf16Helper(context, "a", "alens", 9);
8629 Utf16Helper(context, "a2", "a2lens", 81);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008630}
8631
8632
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008633static bool SameSymbol(Local<String> s1, Local<String> s2) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008634 i::Handle<i::String> is1(v8::Utils::OpenHandle(*s1));
8635 i::Handle<i::String> is2(v8::Utils::OpenHandle(*s2));
8636 return *is1 == *is2;
8637}
8638
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008639
8640THREADED_TEST(Utf16Symbol) {
8641 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008642 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008643
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008644 Local<String> symbol1 =
8645 v8::String::NewFromUtf8(context->GetIsolate(), "abc",
8646 v8::NewStringType::kInternalized)
8647 .ToLocalChecked();
8648 Local<String> symbol2 =
8649 v8::String::NewFromUtf8(context->GetIsolate(), "abc",
8650 v8::NewStringType::kInternalized)
8651 .ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008652 CHECK(SameSymbol(symbol1, symbol2));
8653
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008654 CompileRun(
8655 "var sym0 = 'benedictus';"
8656 "var sym0b = 'S\303\270ren';"
8657 "var sym1 = '\355\240\201\355\260\207';"
8658 "var sym2 = '\360\220\220\210';"
8659 "var sym3 = 'x\355\240\201\355\260\207';"
8660 "var sym4 = 'x\360\220\220\210';"
8661 "if (sym1.length != 2) throw sym1;"
8662 "if (sym1.charCodeAt(1) != 0xdc07) throw sym1.charCodeAt(1);"
8663 "if (sym2.length != 2) throw sym2;"
8664 "if (sym2.charCodeAt(1) != 0xdc08) throw sym2.charCodeAt(2);"
8665 "if (sym3.length != 3) throw sym3;"
8666 "if (sym3.charCodeAt(2) != 0xdc07) throw sym1.charCodeAt(2);"
8667 "if (sym4.length != 3) throw sym4;"
8668 "if (sym4.charCodeAt(2) != 0xdc08) throw sym2.charCodeAt(2);");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008669 Local<String> sym0 =
8670 v8::String::NewFromUtf8(context->GetIsolate(), "benedictus",
8671 v8::NewStringType::kInternalized)
8672 .ToLocalChecked();
8673 Local<String> sym0b =
8674 v8::String::NewFromUtf8(context->GetIsolate(), "S\303\270ren",
8675 v8::NewStringType::kInternalized)
8676 .ToLocalChecked();
8677 Local<String> sym1 =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008678 v8::String::NewFromUtf8(context->GetIsolate(), "\355\240\201\355\260\207",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008679 v8::NewStringType::kInternalized)
8680 .ToLocalChecked();
8681 Local<String> sym2 =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008682 v8::String::NewFromUtf8(context->GetIsolate(), "\360\220\220\210",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008683 v8::NewStringType::kInternalized)
8684 .ToLocalChecked();
8685 Local<String> sym3 = v8::String::NewFromUtf8(context->GetIsolate(),
8686 "x\355\240\201\355\260\207",
8687 v8::NewStringType::kInternalized)
8688 .ToLocalChecked();
8689 Local<String> sym4 =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008690 v8::String::NewFromUtf8(context->GetIsolate(), "x\360\220\220\210",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008691 v8::NewStringType::kInternalized)
8692 .ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008693 v8::Local<v8::Object> global = context->Global();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008694 Local<Value> s0 =
8695 global->Get(context.local(), v8_str("sym0")).ToLocalChecked();
8696 Local<Value> s0b =
8697 global->Get(context.local(), v8_str("sym0b")).ToLocalChecked();
8698 Local<Value> s1 =
8699 global->Get(context.local(), v8_str("sym1")).ToLocalChecked();
8700 Local<Value> s2 =
8701 global->Get(context.local(), v8_str("sym2")).ToLocalChecked();
8702 Local<Value> s3 =
8703 global->Get(context.local(), v8_str("sym3")).ToLocalChecked();
8704 Local<Value> s4 =
8705 global->Get(context.local(), v8_str("sym4")).ToLocalChecked();
8706 CHECK(SameSymbol(sym0, Local<String>::Cast(s0)));
8707 CHECK(SameSymbol(sym0b, Local<String>::Cast(s0b)));
8708 CHECK(SameSymbol(sym1, Local<String>::Cast(s1)));
8709 CHECK(SameSymbol(sym2, Local<String>::Cast(s2)));
8710 CHECK(SameSymbol(sym3, Local<String>::Cast(s3)));
8711 CHECK(SameSymbol(sym4, Local<String>::Cast(s4)));
8712}
8713
8714
8715THREADED_TEST(Utf16MissingTrailing) {
8716 LocalContext context;
8717 v8::HandleScope scope(context->GetIsolate());
8718
8719 // Make sure it will go past the buffer, so it will call `WriteUtf16Slow`
8720 int size = 1024 * 64;
8721 uint8_t* buffer = new uint8_t[size];
8722 for (int i = 0; i < size; i += 4) {
8723 buffer[i] = 0xf0;
8724 buffer[i + 1] = 0x9d;
8725 buffer[i + 2] = 0x80;
8726 buffer[i + 3] = 0x9e;
8727 }
8728
8729 // Now invoke the decoder without last 3 bytes
8730 v8::Local<v8::String> str =
8731 v8::String::NewFromUtf8(
8732 context->GetIsolate(), reinterpret_cast<char*>(buffer),
8733 v8::NewStringType::kNormal, size - 3).ToLocalChecked();
8734 USE(str);
8735 delete[] buffer;
8736}
8737
8738
8739THREADED_TEST(Utf16Trailing3Byte) {
8740 LocalContext context;
8741 v8::HandleScope scope(context->GetIsolate());
8742
8743 // Make sure it will go past the buffer, so it will call `WriteUtf16Slow`
8744 int size = 1024 * 63;
8745 uint8_t* buffer = new uint8_t[size];
8746 for (int i = 0; i < size; i += 3) {
8747 buffer[i] = 0xe2;
8748 buffer[i + 1] = 0x80;
8749 buffer[i + 2] = 0xa6;
8750 }
8751
8752 // Now invoke the decoder without last 3 bytes
8753 v8::Local<v8::String> str =
8754 v8::String::NewFromUtf8(
8755 context->GetIsolate(), reinterpret_cast<char*>(buffer),
8756 v8::NewStringType::kNormal, size).ToLocalChecked();
8757
8758 v8::String::Value value(str);
8759 CHECK_EQ(value.length(), size / 3);
8760 CHECK_EQ((*value)[value.length() - 1], 0x2026);
8761
8762 delete[] buffer;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008763}
8764
8765
Steve Blocka7e24c12009-10-30 11:49:00 +00008766THREADED_TEST(ToArrayIndex) {
Steve Blocka7e24c12009-10-30 11:49:00 +00008767 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008768 v8::Isolate* isolate = context->GetIsolate();
8769 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00008770
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008771 v8::Local<String> str = v8_str("42");
8772 v8::MaybeLocal<v8::Uint32> index = str->ToArrayIndex(context.local());
Steve Blocka7e24c12009-10-30 11:49:00 +00008773 CHECK(!index.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008774 CHECK_EQ(42.0,
8775 index.ToLocalChecked()->Uint32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00008776 str = v8_str("42asdf");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008777 index = str->ToArrayIndex(context.local());
Steve Blocka7e24c12009-10-30 11:49:00 +00008778 CHECK(index.IsEmpty());
8779 str = v8_str("-42");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008780 index = str->ToArrayIndex(context.local());
Steve Blocka7e24c12009-10-30 11:49:00 +00008781 CHECK(index.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008782 str = v8_str("4294967294");
8783 index = str->ToArrayIndex(context.local());
Steve Blocka7e24c12009-10-30 11:49:00 +00008784 CHECK(!index.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008785 CHECK_EQ(4294967294.0,
8786 index.ToLocalChecked()->Uint32Value(context.local()).FromJust());
8787 v8::Local<v8::Number> num = v8::Number::New(isolate, 1);
8788 index = num->ToArrayIndex(context.local());
Steve Blocka7e24c12009-10-30 11:49:00 +00008789 CHECK(!index.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008790 CHECK_EQ(1.0,
8791 index.ToLocalChecked()->Uint32Value(context.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008792 num = v8::Number::New(isolate, -1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008793 index = num->ToArrayIndex(context.local());
Steve Blocka7e24c12009-10-30 11:49:00 +00008794 CHECK(index.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008795 v8::Local<v8::Object> obj = v8::Object::New(isolate);
8796 index = obj->ToArrayIndex(context.local());
Steve Blocka7e24c12009-10-30 11:49:00 +00008797 CHECK(index.IsEmpty());
8798}
8799
8800
8801THREADED_TEST(ErrorConstruction) {
Steve Blocka7e24c12009-10-30 11:49:00 +00008802 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008803 v8::HandleScope scope(context->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00008804
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008805 v8::Local<String> foo = v8_str("foo");
8806 v8::Local<String> message = v8_str("message");
8807 v8::Local<Value> range_error = v8::Exception::RangeError(foo);
Steve Blocka7e24c12009-10-30 11:49:00 +00008808 CHECK(range_error->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008809 CHECK(range_error.As<v8::Object>()
8810 ->Get(context.local(), message)
8811 .ToLocalChecked()
8812 ->Equals(context.local(), foo)
8813 .FromJust());
8814 v8::Local<Value> reference_error = v8::Exception::ReferenceError(foo);
Steve Blocka7e24c12009-10-30 11:49:00 +00008815 CHECK(reference_error->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008816 CHECK(reference_error.As<v8::Object>()
8817 ->Get(context.local(), message)
8818 .ToLocalChecked()
8819 ->Equals(context.local(), foo)
8820 .FromJust());
8821 v8::Local<Value> syntax_error = v8::Exception::SyntaxError(foo);
Steve Blocka7e24c12009-10-30 11:49:00 +00008822 CHECK(syntax_error->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008823 CHECK(syntax_error.As<v8::Object>()
8824 ->Get(context.local(), message)
8825 .ToLocalChecked()
8826 ->Equals(context.local(), foo)
8827 .FromJust());
8828 v8::Local<Value> type_error = v8::Exception::TypeError(foo);
Steve Blocka7e24c12009-10-30 11:49:00 +00008829 CHECK(type_error->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008830 CHECK(type_error.As<v8::Object>()
8831 ->Get(context.local(), message)
8832 .ToLocalChecked()
8833 ->Equals(context.local(), foo)
8834 .FromJust());
8835 v8::Local<Value> error = v8::Exception::Error(foo);
Steve Blocka7e24c12009-10-30 11:49:00 +00008836 CHECK(error->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008837 CHECK(error.As<v8::Object>()
8838 ->Get(context.local(), message)
8839 .ToLocalChecked()
8840 ->Equals(context.local(), foo)
8841 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00008842}
8843
8844
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008845static void ThrowV8Exception(const v8::FunctionCallbackInfo<v8::Value>& info) {
8846 ApiTestFuzzer::Fuzz();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008847 v8::Local<String> foo = v8_str("foo");
8848 v8::Local<String> message = v8_str("message");
8849 v8::Local<Value> error = v8::Exception::Error(foo);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008850 CHECK(error->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008851 v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
8852 CHECK(error.As<v8::Object>()
8853 ->Get(context, message)
8854 .ToLocalChecked()
8855 ->Equals(context, foo)
8856 .FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008857 info.GetIsolate()->ThrowException(error);
8858 info.GetReturnValue().SetUndefined();
8859}
8860
8861
8862THREADED_TEST(ExceptionCreateMessage) {
8863 LocalContext context;
8864 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008865 v8::Local<String> foo_str = v8_str("foo");
8866 v8::Local<String> message_str = v8_str("message");
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008867
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008868 context->GetIsolate()->SetCaptureStackTraceForUncaughtExceptions(true);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008869
8870 Local<v8::FunctionTemplate> fun =
8871 v8::FunctionTemplate::New(context->GetIsolate(), ThrowV8Exception);
8872 v8::Local<v8::Object> global = context->Global();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008873 CHECK(global->Set(context.local(), v8_str("throwV8Exception"),
8874 fun->GetFunction(context.local()).ToLocalChecked())
8875 .FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008876
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008877 TryCatch try_catch(context->GetIsolate());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008878 CompileRun(
8879 "function f1() {\n"
8880 " throwV8Exception();\n"
8881 "};\n"
8882 "f1();");
8883 CHECK(try_catch.HasCaught());
8884
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008885 v8::Local<v8::Value> error = try_catch.Exception();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008886 CHECK(error->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008887 CHECK(error.As<v8::Object>()
8888 ->Get(context.local(), message_str)
8889 .ToLocalChecked()
8890 ->Equals(context.local(), foo_str)
8891 .FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008892
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008893 v8::Local<v8::Message> message =
8894 v8::Exception::CreateMessage(context->GetIsolate(), error);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008895 CHECK(!message.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008896 CHECK_EQ(2, message->GetLineNumber(context.local()).FromJust());
8897 CHECK_EQ(2, message->GetStartColumn(context.local()).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008898
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008899 v8::Local<v8::StackTrace> stackTrace = message->GetStackTrace();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008900 CHECK(!stackTrace.IsEmpty());
8901 CHECK_EQ(2, stackTrace->GetFrameCount());
8902
8903 stackTrace = v8::Exception::GetStackTrace(error);
8904 CHECK(!stackTrace.IsEmpty());
8905 CHECK_EQ(2, stackTrace->GetFrameCount());
8906
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008907 context->GetIsolate()->SetCaptureStackTraceForUncaughtExceptions(false);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008908
8909 // Now check message location when SetCaptureStackTraceForUncaughtExceptions
8910 // is false.
8911 try_catch.Reset();
8912
8913 CompileRun(
8914 "function f2() {\n"
8915 " return throwV8Exception();\n"
8916 "};\n"
8917 "f2();");
8918 CHECK(try_catch.HasCaught());
8919
8920 error = try_catch.Exception();
8921 CHECK(error->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008922 CHECK(error.As<v8::Object>()
8923 ->Get(context.local(), message_str)
8924 .ToLocalChecked()
8925 ->Equals(context.local(), foo_str)
8926 .FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008927
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008928 message = v8::Exception::CreateMessage(context->GetIsolate(), error);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008929 CHECK(!message.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008930 CHECK_EQ(2, message->GetLineNumber(context.local()).FromJust());
8931 CHECK_EQ(9, message->GetStartColumn(context.local()).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008932
8933 // Should be empty stack trace.
8934 stackTrace = message->GetStackTrace();
8935 CHECK(stackTrace.IsEmpty());
8936 CHECK(v8::Exception::GetStackTrace(error).IsEmpty());
8937}
8938
8939
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008940THREADED_TEST(ExceptionCreateMessageLength) {
8941 LocalContext context;
8942 v8::HandleScope scope(context->GetIsolate());
8943
8944 // Test that the message is not truncated.
8945 TryCatch try_catch(context->GetIsolate());
8946 CompileRun(
8947 "var message = 'm';"
8948 "while (message.length < 1000) message += message;"
8949 "throw message;");
8950 CHECK(try_catch.HasCaught());
8951
8952 CHECK_LT(1000, try_catch.Message()->Get()->Length());
8953}
8954
8955
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008956static void YGetter(Local<String> name,
8957 const v8::PropertyCallbackInfo<v8::Value>& info) {
Steve Blocka7e24c12009-10-30 11:49:00 +00008958 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008959 info.GetReturnValue().Set(v8_num(10));
Steve Blocka7e24c12009-10-30 11:49:00 +00008960}
8961
8962
8963static void YSetter(Local<String> name,
8964 Local<Value> value,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008965 const v8::PropertyCallbackInfo<void>& info) {
8966 Local<Object> this_obj = Local<Object>::Cast(info.This());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008967 v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
8968 if (this_obj->Has(context, name).FromJust())
8969 this_obj->Delete(context, name).FromJust();
8970 CHECK(this_obj->Set(context, name, value).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00008971}
8972
8973
8974THREADED_TEST(DeleteAccessor) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008975 v8::Isolate* isolate = CcTest::isolate();
8976 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008977 v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00008978 obj->SetAccessor(v8_str("y"), YGetter, YSetter);
8979 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008980 v8::Local<v8::Object> holder =
8981 obj->NewInstance(context.local()).ToLocalChecked();
8982 CHECK(context->Global()
8983 ->Set(context.local(), v8_str("holder"), holder)
8984 .FromJust());
8985 v8::Local<Value> result =
8986 CompileRun("holder.y = 11; holder.y = 12; holder.y");
8987 CHECK_EQ(12u, result->Uint32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00008988}
8989
8990
Steve Blocka7e24c12009-10-30 11:49:00 +00008991static int trouble_nesting = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008992static void TroubleCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +00008993 ApiTestFuzzer::Fuzz();
8994 trouble_nesting++;
8995
8996 // Call a JS function that throws an uncaught exception.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008997 Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
8998 Local<v8::Object> arg_this = context->Global();
8999 Local<Value> trouble_callee =
9000 (trouble_nesting == 3)
9001 ? arg_this->Get(context, v8_str("trouble_callee")).ToLocalChecked()
9002 : arg_this->Get(context, v8_str("trouble_caller")).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00009003 CHECK(trouble_callee->IsFunction());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009004 args.GetReturnValue().Set(Function::Cast(*trouble_callee)
9005 ->Call(context, arg_this, 0, NULL)
9006 .FromMaybe(v8::Local<v8::Value>()));
Steve Blocka7e24c12009-10-30 11:49:00 +00009007}
9008
9009
9010static int report_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009011static void ApiUncaughtExceptionTestListener(v8::Local<v8::Message>,
9012 v8::Local<Value>) {
Steve Blocka7e24c12009-10-30 11:49:00 +00009013 report_count++;
9014}
9015
9016
9017// Counts uncaught exceptions, but other tests running in parallel
9018// also have uncaught exceptions.
9019TEST(ApiUncaughtException) {
9020 report_count = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +00009021 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009022 v8::Isolate* isolate = env->GetIsolate();
9023 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009024 isolate->AddMessageListener(ApiUncaughtExceptionTestListener);
Steve Blocka7e24c12009-10-30 11:49:00 +00009025
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009026 Local<v8::FunctionTemplate> fun =
9027 v8::FunctionTemplate::New(isolate, TroubleCallback);
Steve Blocka7e24c12009-10-30 11:49:00 +00009028 v8::Local<v8::Object> global = env->Global();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009029 CHECK(global->Set(env.local(), v8_str("trouble"),
9030 fun->GetFunction(env.local()).ToLocalChecked())
9031 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009032
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009033 CompileRun(
9034 "function trouble_callee() {"
9035 " var x = null;"
9036 " return x.foo;"
9037 "};"
9038 "function trouble_caller() {"
9039 " trouble();"
9040 "};");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009041 Local<Value> trouble =
9042 global->Get(env.local(), v8_str("trouble")).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00009043 CHECK(trouble->IsFunction());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009044 Local<Value> trouble_callee =
9045 global->Get(env.local(), v8_str("trouble_callee")).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00009046 CHECK(trouble_callee->IsFunction());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009047 Local<Value> trouble_caller =
9048 global->Get(env.local(), v8_str("trouble_caller")).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00009049 CHECK(trouble_caller->IsFunction());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009050 Function::Cast(*trouble_caller)
9051 ->Call(env.local(), global, 0, NULL)
9052 .FromMaybe(v8::Local<v8::Value>());
Steve Blocka7e24c12009-10-30 11:49:00 +00009053 CHECK_EQ(1, report_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009054 isolate->RemoveMessageListeners(ApiUncaughtExceptionTestListener);
Steve Blocka7e24c12009-10-30 11:49:00 +00009055}
9056
Emily Bernierd0a1eb72015-03-24 16:35:39 -04009057
Leon Clarke4515c472010-02-03 11:58:03 +00009058static const char* script_resource_name = "ExceptionInNativeScript.js";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009059static void ExceptionInNativeScriptTestListener(v8::Local<v8::Message> message,
9060 v8::Local<Value>) {
9061 v8::Local<v8::Value> name_val = message->GetScriptOrigin().ResourceName();
Leon Clarke4515c472010-02-03 11:58:03 +00009062 CHECK(!name_val.IsEmpty() && name_val->IsString());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009063 v8::String::Utf8Value name(message->GetScriptOrigin().ResourceName());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009064 CHECK_EQ(0, strcmp(script_resource_name, *name));
9065 v8::Local<v8::Context> context =
9066 v8::Isolate::GetCurrent()->GetCurrentContext();
9067 CHECK_EQ(3, message->GetLineNumber(context).FromJust());
9068 v8::String::Utf8Value source_line(
9069 message->GetSourceLine(context).ToLocalChecked());
9070 CHECK_EQ(0, strcmp(" new o.foo();", *source_line));
Leon Clarke4515c472010-02-03 11:58:03 +00009071}
9072
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009073
Leon Clarke4515c472010-02-03 11:58:03 +00009074TEST(ExceptionInNativeScript) {
Leon Clarke4515c472010-02-03 11:58:03 +00009075 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009076 v8::Isolate* isolate = env->GetIsolate();
9077 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009078 isolate->AddMessageListener(ExceptionInNativeScriptTestListener);
Leon Clarke4515c472010-02-03 11:58:03 +00009079
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009080 Local<v8::FunctionTemplate> fun =
9081 v8::FunctionTemplate::New(isolate, TroubleCallback);
Leon Clarke4515c472010-02-03 11:58:03 +00009082 v8::Local<v8::Object> global = env->Global();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009083 CHECK(global->Set(env.local(), v8_str("trouble"),
9084 fun->GetFunction(env.local()).ToLocalChecked())
9085 .FromJust());
Leon Clarke4515c472010-02-03 11:58:03 +00009086
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009087 CompileRunWithOrigin(
9088 "function trouble() {\n"
9089 " var o = {};\n"
9090 " new o.foo();\n"
9091 "};",
9092 script_resource_name);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009093 Local<Value> trouble =
9094 global->Get(env.local(), v8_str("trouble")).ToLocalChecked();
Leon Clarke4515c472010-02-03 11:58:03 +00009095 CHECK(trouble->IsFunction());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009096 CHECK(Function::Cast(*trouble)->Call(env.local(), global, 0, NULL).IsEmpty());
9097 isolate->RemoveMessageListeners(ExceptionInNativeScriptTestListener);
Leon Clarke4515c472010-02-03 11:58:03 +00009098}
9099
Steve Blocka7e24c12009-10-30 11:49:00 +00009100
9101TEST(CompilationErrorUsingTryCatchHandler) {
Steve Blocka7e24c12009-10-30 11:49:00 +00009102 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009103 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009104 v8::TryCatch try_catch(env->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009105 v8_compile("This doesn't &*&@#$&*^ compile.");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009106 CHECK(*try_catch.Exception());
Steve Blocka7e24c12009-10-30 11:49:00 +00009107 CHECK(try_catch.HasCaught());
9108}
9109
9110
9111TEST(TryCatchFinallyUsingTryCatchHandler) {
Steve Blocka7e24c12009-10-30 11:49:00 +00009112 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009113 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009114 v8::TryCatch try_catch(env->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009115 CompileRun("try { throw ''; } catch (e) {}");
Steve Blocka7e24c12009-10-30 11:49:00 +00009116 CHECK(!try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009117 CompileRun("try { throw ''; } finally {}");
Steve Blocka7e24c12009-10-30 11:49:00 +00009118 CHECK(try_catch.HasCaught());
9119 try_catch.Reset();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009120 CompileRun(
9121 "(function() {"
9122 "try { throw ''; } finally { return; }"
9123 "})()");
Steve Blocka7e24c12009-10-30 11:49:00 +00009124 CHECK(!try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009125 CompileRun(
9126 "(function()"
9127 " { try { throw ''; } finally { throw 0; }"
9128 "})()");
Steve Blocka7e24c12009-10-30 11:49:00 +00009129 CHECK(try_catch.HasCaught());
9130}
9131
9132
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009133void CEvaluate(const v8::FunctionCallbackInfo<v8::Value>& args) {
9134 v8::HandleScope scope(args.GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009135 CompileRun(args[0]
9136 ->ToString(args.GetIsolate()->GetCurrentContext())
9137 .ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009138}
9139
9140
9141TEST(TryCatchFinallyStoresMessageUsingTryCatchHandler) {
9142 v8::Isolate* isolate = CcTest::isolate();
9143 v8::HandleScope scope(isolate);
9144 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
9145 templ->Set(v8_str("CEvaluate"),
9146 v8::FunctionTemplate::New(isolate, CEvaluate));
9147 LocalContext context(0, templ);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009148 v8::TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009149 CompileRun("try {"
9150 " CEvaluate('throw 1;');"
9151 "} finally {"
9152 "}");
9153 CHECK(try_catch.HasCaught());
9154 CHECK(!try_catch.Message().IsEmpty());
9155 String::Utf8Value exception_value(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009156 CHECK_EQ(0, strcmp(*exception_value, "1"));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009157 try_catch.Reset();
9158 CompileRun("try {"
9159 " CEvaluate('throw 1;');"
9160 "} finally {"
9161 " throw 2;"
9162 "}");
9163 CHECK(try_catch.HasCaught());
9164 CHECK(!try_catch.Message().IsEmpty());
9165 String::Utf8Value finally_exception_value(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009166 CHECK_EQ(0, strcmp(*finally_exception_value, "2"));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009167}
9168
9169
9170// For use within the TestSecurityHandler() test.
9171static bool g_security_callback_result = false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009172static bool SecurityTestCallback(Local<v8::Context> accessing_context,
Ben Murdoch097c5b22016-05-18 11:27:45 +01009173 Local<v8::Object> accessed_object,
9174 Local<v8::Value> data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009175 printf("a\n");
Ben Murdoch097c5b22016-05-18 11:27:45 +01009176 CHECK(!data.IsEmpty() && data->IsInt32());
9177 CHECK_EQ(42, data->Int32Value(accessing_context).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009178 return g_security_callback_result;
9179}
9180
9181
Steve Blocka7e24c12009-10-30 11:49:00 +00009182// SecurityHandler can't be run twice
9183TEST(SecurityHandler) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009184 v8::Isolate* isolate = CcTest::isolate();
9185 v8::HandleScope scope0(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009186 v8::Local<v8::ObjectTemplate> global_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009187 v8::ObjectTemplate::New(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +01009188 global_template->SetAccessCheckCallback(SecurityTestCallback, v8_num(42));
Steve Blocka7e24c12009-10-30 11:49:00 +00009189 // Create an environment
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009190 v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
Steve Blocka7e24c12009-10-30 11:49:00 +00009191 context0->Enter();
9192
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009193 v8::Local<v8::Object> global0 = context0->Global();
9194 v8::Local<Script> script0 = v8_compile("foo = 111");
9195 script0->Run(context0).ToLocalChecked();
9196 CHECK(global0->Set(context0, v8_str("0"), v8_num(999)).FromJust());
9197 v8::Local<Value> foo0 =
9198 global0->Get(context0, v8_str("foo")).ToLocalChecked();
9199 CHECK_EQ(111, foo0->Int32Value(context0).FromJust());
9200 v8::Local<Value> z0 = global0->Get(context0, v8_str("0")).ToLocalChecked();
9201 CHECK_EQ(999, z0->Int32Value(context0).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009202
9203 // Create another environment, should fail security checks.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009204 v8::HandleScope scope1(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00009205
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009206 v8::Local<Context> context1 = Context::New(isolate, NULL, global_template);
Steve Blocka7e24c12009-10-30 11:49:00 +00009207 context1->Enter();
9208
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009209 v8::Local<v8::Object> global1 = context1->Global();
9210 global1->Set(context1, v8_str("othercontext"), global0).FromJust();
Steve Blocka7e24c12009-10-30 11:49:00 +00009211 // This set will fail the security check.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009212 v8::Local<Script> script1 =
9213 v8_compile("othercontext.foo = 222; othercontext[0] = 888;");
9214 CHECK(script1->Run(context1).IsEmpty());
9215 g_security_callback_result = true;
Steve Blocka7e24c12009-10-30 11:49:00 +00009216 // This read will pass the security check.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009217 v8::Local<Value> foo1 =
9218 global0->Get(context1, v8_str("foo")).ToLocalChecked();
9219 CHECK_EQ(111, foo1->Int32Value(context0).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009220 // This read will pass the security check.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009221 v8::Local<Value> z1 = global0->Get(context1, v8_str("0")).ToLocalChecked();
9222 CHECK_EQ(999, z1->Int32Value(context1).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009223
9224 // Create another environment, should pass security checks.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009225 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009226 v8::HandleScope scope2(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00009227 LocalContext context2;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009228 v8::Local<v8::Object> global2 = context2->Global();
9229 CHECK(global2->Set(context2.local(), v8_str("othercontext"), global0)
9230 .FromJust());
9231 v8::Local<Script> script2 =
Steve Blocka7e24c12009-10-30 11:49:00 +00009232 v8_compile("othercontext.foo = 333; othercontext[0] = 888;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009233 script2->Run(context2.local()).ToLocalChecked();
9234 v8::Local<Value> foo2 =
9235 global0->Get(context2.local(), v8_str("foo")).ToLocalChecked();
9236 CHECK_EQ(333, foo2->Int32Value(context2.local()).FromJust());
9237 v8::Local<Value> z2 =
9238 global0->Get(context2.local(), v8_str("0")).ToLocalChecked();
9239 CHECK_EQ(888, z2->Int32Value(context2.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009240 }
9241
9242 context1->Exit();
Steve Blocka7e24c12009-10-30 11:49:00 +00009243 context0->Exit();
Steve Blocka7e24c12009-10-30 11:49:00 +00009244}
9245
9246
9247THREADED_TEST(SecurityChecks) {
Steve Blocka7e24c12009-10-30 11:49:00 +00009248 LocalContext env1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009249 v8::HandleScope handle_scope(env1->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009250 v8::Local<Context> env2 = Context::New(env1->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00009251
9252 Local<Value> foo = v8_str("foo");
9253 Local<Value> bar = v8_str("bar");
9254
9255 // Set to the same domain.
9256 env1->SetSecurityToken(foo);
9257
9258 // Create a function in env1.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009259 CompileRun("spy=function(){return spy;}");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009260 Local<Value> spy =
9261 env1->Global()->Get(env1.local(), v8_str("spy")).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00009262 CHECK(spy->IsFunction());
9263
9264 // Create another function accessing global objects.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009265 CompileRun("spy2=function(){return new this.Array();}");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009266 Local<Value> spy2 =
9267 env1->Global()->Get(env1.local(), v8_str("spy2")).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00009268 CHECK(spy2->IsFunction());
9269
9270 // Switch to env2 in the same domain and invoke spy on env2.
9271 {
9272 env2->SetSecurityToken(foo);
9273 // Enter env2
9274 Context::Scope scope_env2(env2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009275 Local<Value> result = Function::Cast(*spy)
9276 ->Call(env2, env2->Global(), 0, NULL)
9277 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00009278 CHECK(result->IsFunction());
9279 }
9280
9281 {
9282 env2->SetSecurityToken(bar);
9283 Context::Scope scope_env2(env2);
9284
9285 // Call cross_domain_call, it should throw an exception
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009286 v8::TryCatch try_catch(env1->GetIsolate());
9287 CHECK(Function::Cast(*spy2)->Call(env2, env2->Global(), 0, NULL).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00009288 CHECK(try_catch.HasCaught());
9289 }
Steve Blocka7e24c12009-10-30 11:49:00 +00009290}
9291
9292
9293// Regression test case for issue 1183439.
9294THREADED_TEST(SecurityChecksForPrototypeChain) {
Steve Blocka7e24c12009-10-30 11:49:00 +00009295 LocalContext current;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009296 v8::HandleScope scope(current->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009297 v8::Local<Context> other = Context::New(current->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00009298
9299 // Change context to be able to get to the Object function in the
9300 // other context without hitting the security checks.
9301 v8::Local<Value> other_object;
9302 { Context::Scope scope(other);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009303 other_object =
9304 other->Global()->Get(other, v8_str("Object")).ToLocalChecked();
9305 CHECK(other->Global()->Set(other, v8_num(42), v8_num(87)).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009306 }
9307
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009308 CHECK(current->Global()
9309 ->Set(current.local(), v8_str("other"), other->Global())
9310 .FromJust());
9311 CHECK(v8_compile("other")
9312 ->Run(current.local())
9313 .ToLocalChecked()
9314 ->Equals(current.local(), other->Global())
9315 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009316
9317 // Make sure the security check fails here and we get an undefined
9318 // result instead of getting the Object function. Repeat in a loop
9319 // to make sure to exercise the IC code.
9320 v8::Local<Script> access_other0 = v8_compile("other.Object");
9321 v8::Local<Script> access_other1 = v8_compile("other[42]");
9322 for (int i = 0; i < 5; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009323 CHECK(access_other0->Run(current.local()).IsEmpty());
9324 CHECK(access_other1->Run(current.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00009325 }
9326
9327 // Create an object that has 'other' in its prototype chain and make
9328 // sure we cannot access the Object function indirectly through
9329 // that. Repeat in a loop to make sure to exercise the IC code.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009330 v8_compile(
9331 "function F() { };"
9332 "F.prototype = other;"
9333 "var f = new F();")
9334 ->Run(current.local())
9335 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00009336 v8::Local<Script> access_f0 = v8_compile("f.Object");
9337 v8::Local<Script> access_f1 = v8_compile("f[42]");
9338 for (int j = 0; j < 5; j++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009339 CHECK(access_f0->Run(current.local()).IsEmpty());
9340 CHECK(access_f1->Run(current.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00009341 }
9342
9343 // Now it gets hairy: Set the prototype for the other global object
9344 // to be the current global object. The prototype chain for 'f' now
9345 // goes through 'other' but ends up in the current global object.
9346 { Context::Scope scope(other);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009347 CHECK(other->Global()
9348 ->Set(other, v8_str("__proto__"), current->Global())
9349 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009350 }
9351 // Set a named and an index property on the current global
9352 // object. To force the lookup to go through the other global object,
9353 // the properties must not exist in the other global object.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009354 CHECK(current->Global()
9355 ->Set(current.local(), v8_str("foo"), v8_num(100))
9356 .FromJust());
9357 CHECK(current->Global()
9358 ->Set(current.local(), v8_num(99), v8_num(101))
9359 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009360 // Try to read the properties from f and make sure that the access
9361 // gets stopped by the security checks on the other global object.
9362 Local<Script> access_f2 = v8_compile("f.foo");
9363 Local<Script> access_f3 = v8_compile("f[99]");
9364 for (int k = 0; k < 5; k++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009365 CHECK(access_f2->Run(current.local()).IsEmpty());
9366 CHECK(access_f3->Run(current.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00009367 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009368}
9369
9370
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009371static bool security_check_with_gc_called;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009372
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009373static bool SecurityTestCallbackWithGC(Local<v8::Context> accessing_context,
Ben Murdoch097c5b22016-05-18 11:27:45 +01009374 Local<v8::Object> accessed_object,
9375 Local<v8::Value> data) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009376 CcTest::heap()->CollectAllGarbage();
9377 security_check_with_gc_called = true;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009378 return true;
9379}
9380
9381
9382TEST(SecurityTestGCAllowed) {
9383 v8::Isolate* isolate = CcTest::isolate();
9384 v8::HandleScope handle_scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009385 v8::Local<v8::ObjectTemplate> object_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009386 v8::ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009387 object_template->SetAccessCheckCallback(SecurityTestCallbackWithGC);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009388
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009389 v8::Local<Context> context = Context::New(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009390 v8::Context::Scope context_scope(context);
9391
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009392 CHECK(context->Global()
9393 ->Set(context, v8_str("obj"),
9394 object_template->NewInstance(context).ToLocalChecked())
9395 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009396
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009397 security_check_with_gc_called = false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009398 CompileRun("obj[0] = new String(1002);");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009399 CHECK(security_check_with_gc_called);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009400
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009401 security_check_with_gc_called = false;
9402 CHECK(CompileRun("obj[0]")
9403 ->ToString(context)
9404 .ToLocalChecked()
9405 ->Equals(context, v8_str("1002"))
9406 .FromJust());
9407 CHECK(security_check_with_gc_called);
Steve Blocka7e24c12009-10-30 11:49:00 +00009408}
9409
9410
9411THREADED_TEST(CrossDomainDelete) {
Steve Blocka7e24c12009-10-30 11:49:00 +00009412 LocalContext env1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009413 v8::HandleScope handle_scope(env1->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009414 v8::Local<Context> env2 = Context::New(env1->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00009415
9416 Local<Value> foo = v8_str("foo");
9417 Local<Value> bar = v8_str("bar");
9418
9419 // Set to the same domain.
9420 env1->SetSecurityToken(foo);
9421 env2->SetSecurityToken(foo);
9422
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009423 CHECK(
9424 env1->Global()->Set(env1.local(), v8_str("prop"), v8_num(3)).FromJust());
9425 CHECK(env2->Global()->Set(env2, v8_str("env1"), env1->Global()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009426
9427 // Change env2 to a different domain and delete env1.prop.
9428 env2->SetSecurityToken(bar);
9429 {
9430 Context::Scope scope_env2(env2);
9431 Local<Value> result =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009432 CompileRun("delete env1.prop");
9433 CHECK(result.IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00009434 }
9435
9436 // Check that env1.prop still exists.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009437 Local<Value> v =
9438 env1->Global()->Get(env1.local(), v8_str("prop")).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00009439 CHECK(v->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009440 CHECK_EQ(3, v->Int32Value(env1.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009441}
9442
9443
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009444THREADED_TEST(CrossDomainPropertyIsEnumerable) {
Steve Blocka7e24c12009-10-30 11:49:00 +00009445 LocalContext env1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009446 v8::HandleScope handle_scope(env1->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009447 v8::Local<Context> env2 = Context::New(env1->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00009448
9449 Local<Value> foo = v8_str("foo");
9450 Local<Value> bar = v8_str("bar");
9451
9452 // Set to the same domain.
9453 env1->SetSecurityToken(foo);
9454 env2->SetSecurityToken(foo);
9455
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009456 CHECK(
9457 env1->Global()->Set(env1.local(), v8_str("prop"), v8_num(3)).FromJust());
9458 CHECK(env2->Global()->Set(env2, v8_str("env1"), env1->Global()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009459
9460 // env1.prop is enumerable in env2.
9461 Local<String> test = v8_str("propertyIsEnumerable.call(env1, 'prop')");
9462 {
9463 Context::Scope scope_env2(env2);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009464 Local<Value> result = CompileRun(test);
Steve Blocka7e24c12009-10-30 11:49:00 +00009465 CHECK(result->IsTrue());
9466 }
9467
9468 // Change env2 to a different domain and test again.
9469 env2->SetSecurityToken(bar);
9470 {
9471 Context::Scope scope_env2(env2);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009472 Local<Value> result = CompileRun(test);
9473 CHECK(result.IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00009474 }
Steve Blocka7e24c12009-10-30 11:49:00 +00009475}
9476
9477
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009478THREADED_TEST(CrossDomainFor) {
Steve Blocka7e24c12009-10-30 11:49:00 +00009479 LocalContext env1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009480 v8::HandleScope handle_scope(env1->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009481 v8::Local<Context> env2 = Context::New(env1->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00009482
9483 Local<Value> foo = v8_str("foo");
9484 Local<Value> bar = v8_str("bar");
9485
9486 // Set to the same domain.
9487 env1->SetSecurityToken(foo);
9488 env2->SetSecurityToken(foo);
9489
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009490 CHECK(
9491 env1->Global()->Set(env1.local(), v8_str("prop"), v8_num(3)).FromJust());
9492 CHECK(env2->Global()->Set(env2, v8_str("env1"), env1->Global()).FromJust());
9493
9494 // Change env2 to a different domain and set env1's global object
9495 // as the __proto__ of an object in env2 and enumerate properties
9496 // in for-in. It shouldn't enumerate properties on env1's global
9497 // object. It shouldn't throw either, just silently ignore them.
9498 env2->SetSecurityToken(bar);
9499 {
9500 Context::Scope scope_env2(env2);
9501 Local<Value> result = CompileRun(
9502 "(function() {"
9503 " try {"
9504 " for (var p in env1) {"
9505 " if (p == 'prop') return false;"
9506 " }"
9507 " return true;"
9508 " } catch (e) {"
9509 " return false;"
9510 " }"
9511 "})()");
9512 CHECK(result->IsTrue());
9513 }
9514}
9515
9516
9517THREADED_TEST(CrossDomainForInOnPrototype) {
9518 LocalContext env1;
9519 v8::HandleScope handle_scope(env1->GetIsolate());
9520 v8::Local<Context> env2 = Context::New(env1->GetIsolate());
9521
9522 Local<Value> foo = v8_str("foo");
9523 Local<Value> bar = v8_str("bar");
9524
9525 // Set to the same domain.
9526 env1->SetSecurityToken(foo);
9527 env2->SetSecurityToken(foo);
9528
9529 CHECK(
9530 env1->Global()->Set(env1.local(), v8_str("prop"), v8_num(3)).FromJust());
9531 CHECK(env2->Global()->Set(env2, v8_str("env1"), env1->Global()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009532
9533 // Change env2 to a different domain and set env1's global object
9534 // as the __proto__ of an object in env2 and enumerate properties
9535 // in for-in. It shouldn't enumerate properties on env1's global
9536 // object.
9537 env2->SetSecurityToken(bar);
9538 {
9539 Context::Scope scope_env2(env2);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009540 Local<Value> result = CompileRun(
9541 "(function() {"
9542 " var obj = { '__proto__': env1 };"
9543 " try {"
9544 " for (var p in obj) {"
9545 " if (p == 'prop') return false;"
9546 " }"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009547 " return true;"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009548 " } catch (e) {"
9549 " return false;"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009550 " }"
9551 "})()");
Steve Blocka7e24c12009-10-30 11:49:00 +00009552 CHECK(result->IsTrue());
9553 }
Steve Blocka7e24c12009-10-30 11:49:00 +00009554}
9555
9556
9557TEST(ContextDetachGlobal) {
Steve Blocka7e24c12009-10-30 11:49:00 +00009558 LocalContext env1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009559 v8::HandleScope handle_scope(env1->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009560 v8::Local<Context> env2 = Context::New(env1->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00009561
Steve Blocka7e24c12009-10-30 11:49:00 +00009562
9563 Local<Value> foo = v8_str("foo");
9564
9565 // Set to the same domain.
9566 env1->SetSecurityToken(foo);
9567 env2->SetSecurityToken(foo);
9568
9569 // Enter env2
9570 env2->Enter();
9571
Andrei Popescu74b3c142010-03-29 12:03:09 +01009572 // Create a function in env2 and add a reference to it in env1.
Steve Blocka7e24c12009-10-30 11:49:00 +00009573 Local<v8::Object> global2 = env2->Global();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009574 CHECK(global2->Set(env2, v8_str("prop"),
9575 v8::Integer::New(env2->GetIsolate(), 1))
9576 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009577 CompileRun("function getProp() {return prop;}");
9578
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009579 CHECK(env1->Global()
9580 ->Set(env1.local(), v8_str("getProp"),
9581 global2->Get(env2, v8_str("getProp")).ToLocalChecked())
9582 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009583
Andrei Popescu74b3c142010-03-29 12:03:09 +01009584 // Detach env2's global, and reuse the global object of env2
Steve Blocka7e24c12009-10-30 11:49:00 +00009585 env2->Exit();
9586 env2->DetachGlobal();
Steve Blocka7e24c12009-10-30 11:49:00 +00009587
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009588 v8::Local<Context> env3 = Context::New(
9589 env1->GetIsolate(), 0, v8::Local<v8::ObjectTemplate>(), global2);
Steve Blocka7e24c12009-10-30 11:49:00 +00009590 env3->SetSecurityToken(v8_str("bar"));
Steve Blocka7e24c12009-10-30 11:49:00 +00009591
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009592 env3->Enter();
Steve Blocka7e24c12009-10-30 11:49:00 +00009593 Local<v8::Object> global3 = env3->Global();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009594 CHECK(global2->Equals(env3, global3).FromJust());
9595 CHECK(global3->Get(env3, v8_str("prop")).ToLocalChecked()->IsUndefined());
9596 CHECK(global3->Get(env3, v8_str("getProp")).ToLocalChecked()->IsUndefined());
9597 CHECK(global3->Set(env3, v8_str("prop"),
9598 v8::Integer::New(env3->GetIsolate(), -1))
9599 .FromJust());
9600 CHECK(global3->Set(env3, v8_str("prop2"),
9601 v8::Integer::New(env3->GetIsolate(), 2))
9602 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009603 env3->Exit();
9604
9605 // Call getProp in env1, and it should return the value 1
9606 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009607 Local<v8::Object> global1 = env1->Global();
9608 Local<Value> get_prop =
9609 global1->Get(env1.local(), v8_str("getProp")).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00009610 CHECK(get_prop->IsFunction());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009611 v8::TryCatch try_catch(env1->GetIsolate());
9612 Local<Value> r = Function::Cast(*get_prop)
9613 ->Call(env1.local(), global1, 0, NULL)
9614 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00009615 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009616 CHECK_EQ(1, r->Int32Value(env1.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009617 }
9618
9619 // Check that env3 is not accessible from env1
9620 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009621 v8::MaybeLocal<Value> r = global3->Get(env1.local(), v8_str("prop2"));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009622 CHECK(r.IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00009623 }
Steve Blocka7e24c12009-10-30 11:49:00 +00009624}
9625
9626
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009627TEST(DetachGlobal) {
Andrei Popescu74b3c142010-03-29 12:03:09 +01009628 LocalContext env1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009629 v8::HandleScope scope(env1->GetIsolate());
Andrei Popescu74b3c142010-03-29 12:03:09 +01009630
9631 // Create second environment.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009632 v8::Local<Context> env2 = Context::New(env1->GetIsolate());
Andrei Popescu74b3c142010-03-29 12:03:09 +01009633
9634 Local<Value> foo = v8_str("foo");
9635
9636 // Set same security token for env1 and env2.
9637 env1->SetSecurityToken(foo);
9638 env2->SetSecurityToken(foo);
9639
9640 // Create a property on the global object in env2.
9641 {
9642 v8::Context::Scope scope(env2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009643 CHECK(env2->Global()
9644 ->Set(env2, v8_str("p"), v8::Integer::New(env2->GetIsolate(), 42))
9645 .FromJust());
Andrei Popescu74b3c142010-03-29 12:03:09 +01009646 }
9647
9648 // Create a reference to env2 global from env1 global.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009649 CHECK(env1->Global()
9650 ->Set(env1.local(), v8_str("other"), env2->Global())
9651 .FromJust());
Andrei Popescu74b3c142010-03-29 12:03:09 +01009652
9653 // Check that we have access to other.p in env2 from env1.
9654 Local<Value> result = CompileRun("other.p");
9655 CHECK(result->IsInt32());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009656 CHECK_EQ(42, result->Int32Value(env1.local()).FromJust());
Andrei Popescu74b3c142010-03-29 12:03:09 +01009657
9658 // Hold on to global from env2 and detach global from env2.
9659 Local<v8::Object> global2 = env2->Global();
9660 env2->DetachGlobal();
9661
9662 // Check that the global has been detached. No other.p property can
9663 // be found.
9664 result = CompileRun("other.p");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009665 CHECK(result.IsEmpty());
Andrei Popescu74b3c142010-03-29 12:03:09 +01009666
9667 // Reuse global2 for env3.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009668 v8::Local<Context> env3 = Context::New(
9669 env1->GetIsolate(), 0, v8::Local<v8::ObjectTemplate>(), global2);
9670 CHECK(global2->Equals(env1.local(), env3->Global()).FromJust());
Andrei Popescu74b3c142010-03-29 12:03:09 +01009671
9672 // Start by using the same security token for env3 as for env1 and env2.
9673 env3->SetSecurityToken(foo);
9674
9675 // Create a property on the global object in env3.
9676 {
9677 v8::Context::Scope scope(env3);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009678 CHECK(env3->Global()
9679 ->Set(env3, v8_str("p"), v8::Integer::New(env3->GetIsolate(), 24))
9680 .FromJust());
Andrei Popescu74b3c142010-03-29 12:03:09 +01009681 }
9682
9683 // Check that other.p is now the property in env3 and that we have access.
9684 result = CompileRun("other.p");
9685 CHECK(result->IsInt32());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009686 CHECK_EQ(24, result->Int32Value(env3).FromJust());
Andrei Popescu74b3c142010-03-29 12:03:09 +01009687
9688 // Change security token for env3 to something different from env1 and env2.
9689 env3->SetSecurityToken(v8_str("bar"));
9690
9691 // Check that we do not have access to other.p in env1. |other| is now
9692 // the global object for env3 which has a different security token,
9693 // so access should be blocked.
9694 result = CompileRun("other.p");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009695 CHECK(result.IsEmpty());
9696}
Andrei Popescu74b3c142010-03-29 12:03:09 +01009697
Andrei Popescu74b3c142010-03-29 12:03:09 +01009698
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009699void GetThisX(const v8::FunctionCallbackInfo<v8::Value>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009700 v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009701 info.GetReturnValue().Set(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009702 context->Global()->Get(context, v8_str("x")).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009703}
Andrei Popescu74b3c142010-03-29 12:03:09 +01009704
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009705
9706TEST(DetachedAccesses) {
9707 LocalContext env1;
9708 v8::HandleScope scope(env1->GetIsolate());
9709
9710 // Create second environment.
9711 Local<ObjectTemplate> inner_global_template =
9712 FunctionTemplate::New(env1->GetIsolate())->InstanceTemplate();
9713 inner_global_template ->SetAccessorProperty(
9714 v8_str("this_x"), FunctionTemplate::New(env1->GetIsolate(), GetThisX));
9715 v8::Local<Context> env2 =
9716 Context::New(env1->GetIsolate(), NULL, inner_global_template);
9717
9718 Local<Value> foo = v8_str("foo");
9719
9720 // Set same security token for env1 and env2.
9721 env1->SetSecurityToken(foo);
9722 env2->SetSecurityToken(foo);
9723
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009724 CHECK(env1->Global()
9725 ->Set(env1.local(), v8_str("x"), v8_str("env1_x"))
9726 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009727
9728 {
9729 v8::Context::Scope scope(env2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009730 CHECK(env2->Global()->Set(env2, v8_str("x"), v8_str("env2_x")).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009731 CompileRun(
9732 "function bound_x() { return x; }"
9733 "function get_x() { return this.x; }"
9734 "function get_x_w() { return (function() {return this.x;})(); }");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009735 CHECK(env1->Global()
9736 ->Set(env1.local(), v8_str("bound_x"), CompileRun("bound_x"))
9737 .FromJust());
9738 CHECK(env1->Global()
9739 ->Set(env1.local(), v8_str("get_x"), CompileRun("get_x"))
9740 .FromJust());
9741 CHECK(env1->Global()
9742 ->Set(env1.local(), v8_str("get_x_w"), CompileRun("get_x_w"))
9743 .FromJust());
9744 env1->Global()
9745 ->Set(env1.local(), v8_str("this_x"),
9746 CompileRun("Object.getOwnPropertyDescriptor(this, 'this_x').get"))
9747 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009748 }
9749
9750 Local<Object> env2_global = env2->Global();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009751 env2->DetachGlobal();
9752
9753 Local<Value> result;
9754 result = CompileRun("bound_x()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009755 CHECK(v8_str("env2_x")->Equals(env1.local(), result).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009756 result = CompileRun("get_x()");
9757 CHECK(result.IsEmpty());
9758 result = CompileRun("get_x_w()");
9759 CHECK(result.IsEmpty());
9760 result = CompileRun("this_x()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009761 CHECK(v8_str("env2_x")->Equals(env1.local(), result).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009762
9763 // Reattach env2's proxy
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009764 env2 = Context::New(env1->GetIsolate(), 0, v8::Local<v8::ObjectTemplate>(),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009765 env2_global);
9766 env2->SetSecurityToken(foo);
9767 {
9768 v8::Context::Scope scope(env2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009769 CHECK(env2->Global()->Set(env2, v8_str("x"), v8_str("env3_x")).FromJust());
9770 CHECK(env2->Global()->Set(env2, v8_str("env1"), env1->Global()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009771 result = CompileRun(
9772 "results = [];"
9773 "for (var i = 0; i < 4; i++ ) {"
9774 " results.push(env1.bound_x());"
9775 " results.push(env1.get_x());"
9776 " results.push(env1.get_x_w());"
9777 " results.push(env1.this_x());"
9778 "}"
9779 "results");
9780 Local<v8::Array> results = Local<v8::Array>::Cast(result);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009781 CHECK_EQ(16u, results->Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009782 for (int i = 0; i < 16; i += 4) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009783 CHECK(v8_str("env2_x")
9784 ->Equals(env2, results->Get(env2, i + 0).ToLocalChecked())
9785 .FromJust());
9786 CHECK(v8_str("env1_x")
9787 ->Equals(env2, results->Get(env2, i + 1).ToLocalChecked())
9788 .FromJust());
9789 CHECK(v8_str("env3_x")
9790 ->Equals(env2, results->Get(env2, i + 2).ToLocalChecked())
9791 .FromJust());
9792 CHECK(v8_str("env2_x")
9793 ->Equals(env2, results->Get(env2, i + 3).ToLocalChecked())
9794 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009795 }
9796 }
9797
9798 result = CompileRun(
9799 "results = [];"
9800 "for (var i = 0; i < 4; i++ ) {"
9801 " results.push(bound_x());"
9802 " results.push(get_x());"
9803 " results.push(get_x_w());"
9804 " results.push(this_x());"
9805 "}"
9806 "results");
9807 Local<v8::Array> results = Local<v8::Array>::Cast(result);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009808 CHECK_EQ(16u, results->Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009809 for (int i = 0; i < 16; i += 4) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009810 CHECK(v8_str("env2_x")
9811 ->Equals(env1.local(),
9812 results->Get(env1.local(), i + 0).ToLocalChecked())
9813 .FromJust());
9814 CHECK(v8_str("env3_x")
9815 ->Equals(env1.local(),
9816 results->Get(env1.local(), i + 1).ToLocalChecked())
9817 .FromJust());
9818 CHECK(v8_str("env3_x")
9819 ->Equals(env1.local(),
9820 results->Get(env1.local(), i + 2).ToLocalChecked())
9821 .FromJust());
9822 CHECK(v8_str("env2_x")
9823 ->Equals(env1.local(),
9824 results->Get(env1.local(), i + 3).ToLocalChecked())
9825 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009826 }
9827
9828 result = CompileRun(
9829 "results = [];"
9830 "for (var i = 0; i < 4; i++ ) {"
9831 " results.push(this.bound_x());"
9832 " results.push(this.get_x());"
9833 " results.push(this.get_x_w());"
9834 " results.push(this.this_x());"
9835 "}"
9836 "results");
9837 results = Local<v8::Array>::Cast(result);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009838 CHECK_EQ(16u, results->Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009839 for (int i = 0; i < 16; i += 4) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009840 CHECK(v8_str("env2_x")
9841 ->Equals(env1.local(),
9842 results->Get(env1.local(), i + 0).ToLocalChecked())
9843 .FromJust());
9844 CHECK(v8_str("env1_x")
9845 ->Equals(env1.local(),
9846 results->Get(env1.local(), i + 1).ToLocalChecked())
9847 .FromJust());
9848 CHECK(v8_str("env3_x")
9849 ->Equals(env1.local(),
9850 results->Get(env1.local(), i + 2).ToLocalChecked())
9851 .FromJust());
9852 CHECK(v8_str("env2_x")
9853 ->Equals(env1.local(),
9854 results->Get(env1.local(), i + 3).ToLocalChecked())
9855 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009856 }
Andrei Popescu74b3c142010-03-29 12:03:09 +01009857}
9858
9859
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009860static bool allowed_access = false;
9861static bool AccessBlocker(Local<v8::Context> accessing_context,
Ben Murdoch097c5b22016-05-18 11:27:45 +01009862 Local<v8::Object> accessed_object,
9863 Local<v8::Value> data) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009864 v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
9865 return context->Global()->Equals(context, accessed_object).FromJust() ||
9866 allowed_access;
Steve Blocka7e24c12009-10-30 11:49:00 +00009867}
9868
9869
9870static int g_echo_value = -1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009871
9872
9873static void EchoGetter(
9874 Local<String> name,
9875 const v8::PropertyCallbackInfo<v8::Value>& info) {
9876 info.GetReturnValue().Set(v8_num(g_echo_value));
Steve Blocka7e24c12009-10-30 11:49:00 +00009877}
9878
9879
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009880static void EchoSetter(Local<String> name, Local<Value> value,
9881 const v8::PropertyCallbackInfo<void>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +00009882 if (value->IsNumber())
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009883 g_echo_value =
9884 value->Int32Value(args.GetIsolate()->GetCurrentContext()).FromJust();
Steve Blocka7e24c12009-10-30 11:49:00 +00009885}
9886
9887
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009888static void UnreachableGetter(
9889 Local<String> name,
9890 const v8::PropertyCallbackInfo<v8::Value>& info) {
Steve Blocka7e24c12009-10-30 11:49:00 +00009891 CHECK(false); // This function should not be called..
Steve Blocka7e24c12009-10-30 11:49:00 +00009892}
9893
9894
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009895static void UnreachableSetter(Local<String>,
9896 Local<Value>,
9897 const v8::PropertyCallbackInfo<void>&) {
Steve Blocka7e24c12009-10-30 11:49:00 +00009898 CHECK(false); // This function should nto be called.
9899}
9900
9901
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009902static void UnreachableFunction(
9903 const v8::FunctionCallbackInfo<v8::Value>& info) {
9904 CHECK(false); // This function should not be called..
9905}
9906
9907
Steve Block1e0659c2011-05-24 12:43:12 +01009908TEST(AccessControl) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009909 v8::Isolate* isolate = CcTest::isolate();
9910 v8::HandleScope handle_scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009911 v8::Local<v8::ObjectTemplate> global_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009912 v8::ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00009913
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009914 global_template->SetAccessCheckCallback(AccessBlocker);
Steve Blocka7e24c12009-10-30 11:49:00 +00009915
9916 // Add an accessor accessible by cross-domain JS code.
9917 global_template->SetAccessor(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009918 v8_str("accessible_prop"), EchoGetter, EchoSetter, v8::Local<Value>(),
Steve Blocka7e24c12009-10-30 11:49:00 +00009919 v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
9920
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009921
Steve Blocka7e24c12009-10-30 11:49:00 +00009922 // Add an accessor that is not accessible by cross-domain JS code.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009923 global_template->SetAccessor(v8_str("blocked_prop"), UnreachableGetter,
9924 UnreachableSetter, v8::Local<Value>(),
Steve Blocka7e24c12009-10-30 11:49:00 +00009925 v8::DEFAULT);
9926
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009927 global_template->SetAccessorProperty(
9928 v8_str("blocked_js_prop"),
9929 v8::FunctionTemplate::New(isolate, UnreachableFunction),
9930 v8::FunctionTemplate::New(isolate, UnreachableFunction),
9931 v8::None,
9932 v8::DEFAULT);
9933
Steve Blocka7e24c12009-10-30 11:49:00 +00009934 // Create an environment
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009935 v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
Steve Blocka7e24c12009-10-30 11:49:00 +00009936 context0->Enter();
9937
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009938 v8::Local<v8::Object> global0 = context0->Global();
Steve Blocka7e24c12009-10-30 11:49:00 +00009939
Steve Block1e0659c2011-05-24 12:43:12 +01009940 // Define a property with JS getter and setter.
9941 CompileRun(
9942 "function getter() { return 'getter'; };\n"
9943 "function setter() { return 'setter'; }\n"
9944 "Object.defineProperty(this, 'js_accessor_p', {get:getter, set:setter})");
9945
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009946 Local<Value> getter =
9947 global0->Get(context0, v8_str("getter")).ToLocalChecked();
9948 Local<Value> setter =
9949 global0->Get(context0, v8_str("setter")).ToLocalChecked();
Steve Block1e0659c2011-05-24 12:43:12 +01009950
9951 // And define normal element.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009952 CHECK(global0->Set(context0, 239, v8_str("239")).FromJust());
Steve Block1e0659c2011-05-24 12:43:12 +01009953
9954 // Define an element with JS getter and setter.
9955 CompileRun(
9956 "function el_getter() { return 'el_getter'; };\n"
9957 "function el_setter() { return 'el_setter'; };\n"
9958 "Object.defineProperty(this, '42', {get: el_getter, set: el_setter});");
9959
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009960 Local<Value> el_getter =
9961 global0->Get(context0, v8_str("el_getter")).ToLocalChecked();
9962 Local<Value> el_setter =
9963 global0->Get(context0, v8_str("el_setter")).ToLocalChecked();
Steve Block1e0659c2011-05-24 12:43:12 +01009964
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009965 v8::HandleScope scope1(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00009966
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009967 v8::Local<Context> context1 = Context::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00009968 context1->Enter();
9969
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009970 v8::Local<v8::Object> global1 = context1->Global();
9971 CHECK(global1->Set(context1, v8_str("other"), global0).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009972
Steve Block1e0659c2011-05-24 12:43:12 +01009973 // Access blocked property.
9974 CompileRun("other.blocked_prop = 1");
9975
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009976 CHECK(CompileRun("other.blocked_prop").IsEmpty());
9977 CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, 'blocked_prop')")
9978 .IsEmpty());
9979 CHECK(
9980 CompileRun("propertyIsEnumerable.call(other, 'blocked_prop')").IsEmpty());
Steve Block1e0659c2011-05-24 12:43:12 +01009981
9982 // Access blocked element.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009983 CHECK(CompileRun("other[239] = 1").IsEmpty());
Steve Block1e0659c2011-05-24 12:43:12 +01009984
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009985 CHECK(CompileRun("other[239]").IsEmpty());
9986 CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, '239')").IsEmpty());
9987 CHECK(CompileRun("propertyIsEnumerable.call(other, '239')").IsEmpty());
Steve Block1e0659c2011-05-24 12:43:12 +01009988
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009989 allowed_access = true;
9990 // Now we can enumerate the property.
Steve Block1e0659c2011-05-24 12:43:12 +01009991 ExpectTrue("propertyIsEnumerable.call(other, '239')");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009992 allowed_access = false;
Steve Block1e0659c2011-05-24 12:43:12 +01009993
9994 // Access a property with JS accessor.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009995 CHECK(CompileRun("other.js_accessor_p = 2").IsEmpty());
Steve Block1e0659c2011-05-24 12:43:12 +01009996
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009997 CHECK(CompileRun("other.js_accessor_p").IsEmpty());
9998 CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, 'js_accessor_p')")
9999 .IsEmpty());
Steve Block1e0659c2011-05-24 12:43:12 +010010000
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010001 allowed_access = true;
Steve Block1e0659c2011-05-24 12:43:12 +010010002
10003 ExpectString("other.js_accessor_p", "getter");
10004 ExpectObject(
10005 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get", getter);
Steve Block1e0659c2011-05-24 12:43:12 +010010006 ExpectObject(
10007 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set", setter);
10008 ExpectUndefined(
10009 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
10010
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010011 allowed_access = false;
Steve Block1e0659c2011-05-24 12:43:12 +010010012
10013 // Access an element with JS accessor.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010014 CHECK(CompileRun("other[42] = 2").IsEmpty());
Steve Block1e0659c2011-05-24 12:43:12 +010010015
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010016 CHECK(CompileRun("other[42]").IsEmpty());
10017 CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, '42')").IsEmpty());
Steve Block1e0659c2011-05-24 12:43:12 +010010018
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010019 allowed_access = true;
Steve Block1e0659c2011-05-24 12:43:12 +010010020
10021 ExpectString("other[42]", "el_getter");
10022 ExpectObject("Object.getOwnPropertyDescriptor(other, '42').get", el_getter);
Steve Block1e0659c2011-05-24 12:43:12 +010010023 ExpectObject("Object.getOwnPropertyDescriptor(other, '42').set", el_setter);
10024 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
10025
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010026 allowed_access = false;
Steve Block1e0659c2011-05-24 12:43:12 +010010027
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010028 v8::Local<Value> value;
Steve Blocka7e24c12009-10-30 11:49:00 +000010029
Steve Blocka7e24c12009-10-30 11:49:00 +000010030 // Access accessible property
Steve Block1e0659c2011-05-24 12:43:12 +010010031 value = CompileRun("other.accessible_prop = 3");
Steve Blocka7e24c12009-10-30 11:49:00 +000010032 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010033 CHECK_EQ(3, value->Int32Value(context1).FromJust());
Andrei Popescu31002712010-02-23 13:46:05 +000010034 CHECK_EQ(3, g_echo_value);
Steve Blocka7e24c12009-10-30 11:49:00 +000010035
Steve Block1e0659c2011-05-24 12:43:12 +010010036 value = CompileRun("other.accessible_prop");
Steve Blocka7e24c12009-10-30 11:49:00 +000010037 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010038 CHECK_EQ(3, value->Int32Value(context1).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010039
Steve Block1e0659c2011-05-24 12:43:12 +010010040 value = CompileRun(
10041 "Object.getOwnPropertyDescriptor(other, 'accessible_prop').value");
10042 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010043 CHECK_EQ(3, value->Int32Value(context1).FromJust());
Steve Block1e0659c2011-05-24 12:43:12 +010010044
10045 value = CompileRun("propertyIsEnumerable.call(other, 'accessible_prop')");
Steve Blocka7e24c12009-10-30 11:49:00 +000010046 CHECK(value->IsTrue());
10047
10048 // Enumeration doesn't enumerate accessors from inaccessible objects in
10049 // the prototype chain even if the accessors are in themselves accessible.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010050 // Enumeration doesn't throw, it silently ignores what it can't access.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010051 value = CompileRun(
10052 "(function() {"
10053 " var obj = { '__proto__': other };"
10054 " try {"
10055 " for (var p in obj) {"
10056 " if (p == 'accessible_prop' ||"
10057 " p == 'blocked_js_prop' ||"
10058 " p == 'blocked_js_prop') {"
10059 " return false;"
10060 " }"
10061 " }"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010062 " return true;"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010063 " } catch (e) {"
10064 " return false;"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010065 " }"
10066 "})()");
Steve Block1e0659c2011-05-24 12:43:12 +010010067 CHECK(value->IsTrue());
Steve Blocka7e24c12009-10-30 11:49:00 +000010068
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010069 // Test that preventExtensions fails on a non-accessible object even if that
10070 // object is already non-extensible.
10071 CHECK(global1->Set(context1, v8_str("checked_object"),
10072 global_template->NewInstance(context1).ToLocalChecked())
10073 .FromJust());
10074 allowed_access = true;
10075 CompileRun("Object.preventExtensions(checked_object)");
10076 ExpectFalse("Object.isExtensible(checked_object)");
10077 allowed_access = false;
10078 CHECK(CompileRun("Object.preventExtensions(checked_object)").IsEmpty());
10079
Steve Blocka7e24c12009-10-30 11:49:00 +000010080 context1->Exit();
10081 context0->Exit();
Steve Blocka7e24c12009-10-30 11:49:00 +000010082}
10083
10084
Ben Murdoche0cee9b2011-05-25 10:26:03 +010010085TEST(AccessControlES5) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010086 v8::Isolate* isolate = CcTest::isolate();
10087 v8::HandleScope handle_scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010088 v8::Local<v8::ObjectTemplate> global_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010089 v8::ObjectTemplate::New(isolate);
Ben Murdoche0cee9b2011-05-25 10:26:03 +010010090
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010091 global_template->SetAccessCheckCallback(AccessBlocker);
Ben Murdoche0cee9b2011-05-25 10:26:03 +010010092
Steve Block44f0eee2011-05-26 01:26:41 +010010093 // Add accessible accessor.
10094 global_template->SetAccessor(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010095 v8_str("accessible_prop"), EchoGetter, EchoSetter, v8::Local<Value>(),
Steve Block44f0eee2011-05-26 01:26:41 +010010096 v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
10097
10098
Ben Murdoche0cee9b2011-05-25 10:26:03 +010010099 // Add an accessor that is not accessible by cross-domain JS code.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010100 global_template->SetAccessor(v8_str("blocked_prop"), UnreachableGetter,
10101 UnreachableSetter, v8::Local<Value>(),
Ben Murdoche0cee9b2011-05-25 10:26:03 +010010102 v8::DEFAULT);
10103
10104 // Create an environment
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010105 v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
Ben Murdoche0cee9b2011-05-25 10:26:03 +010010106 context0->Enter();
10107
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010108 v8::Local<v8::Object> global0 = context0->Global();
Ben Murdoche0cee9b2011-05-25 10:26:03 +010010109
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010110 v8::Local<Context> context1 = Context::New(isolate);
Ben Murdoche0cee9b2011-05-25 10:26:03 +010010111 context1->Enter();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010112 v8::Local<v8::Object> global1 = context1->Global();
10113 CHECK(global1->Set(context1, v8_str("other"), global0).FromJust());
Ben Murdoche0cee9b2011-05-25 10:26:03 +010010114
10115 // Regression test for issue 1154.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010116 CHECK(CompileRun("Object.keys(other).length == 1")
10117 ->BooleanValue(context1)
10118 .FromJust());
10119 CHECK(CompileRun("Object.keys(other)[0] == 'accessible_prop'")
10120 ->BooleanValue(context1)
10121 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010122 CHECK(CompileRun("other.blocked_prop").IsEmpty());
Ben Murdoche0cee9b2011-05-25 10:26:03 +010010123
10124 // Regression test for issue 1027.
10125 CompileRun("Object.defineProperty(\n"
10126 " other, 'blocked_prop', {configurable: false})");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010127 CHECK(CompileRun("other.blocked_prop").IsEmpty());
10128 CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, 'blocked_prop')")
10129 .IsEmpty());
Ben Murdoche0cee9b2011-05-25 10:26:03 +010010130
10131 // Regression test for issue 1171.
10132 ExpectTrue("Object.isExtensible(other)");
10133 CompileRun("Object.preventExtensions(other)");
10134 ExpectTrue("Object.isExtensible(other)");
10135
10136 // Object.seal and Object.freeze.
10137 CompileRun("Object.freeze(other)");
10138 ExpectTrue("Object.isExtensible(other)");
10139
10140 CompileRun("Object.seal(other)");
10141 ExpectTrue("Object.isExtensible(other)");
Steve Block44f0eee2011-05-26 01:26:41 +010010142
10143 // Regression test for issue 1250.
10144 // Make sure that we can set the accessible accessors value using normal
10145 // assignment.
10146 CompileRun("other.accessible_prop = 42");
10147 CHECK_EQ(42, g_echo_value);
10148
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010149 // [[DefineOwnProperty]] always throws for access-checked objects.
10150 CHECK(
10151 CompileRun("Object.defineProperty(other, 'accessible_prop', {value: 43})")
10152 .IsEmpty());
10153 CHECK(CompileRun("other.accessible_prop == 42")->IsTrue());
10154 CHECK_EQ(42, g_echo_value); // Make sure we didn't call the setter.
Ben Murdoche0cee9b2011-05-25 10:26:03 +010010155}
10156
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010157static bool AccessAlwaysBlocked(Local<v8::Context> accessing_context,
Ben Murdoch097c5b22016-05-18 11:27:45 +010010158 Local<v8::Object> global,
10159 Local<v8::Value> data) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010160 i::PrintF("Access blocked.\n");
Leon Clarke4515c472010-02-03 11:58:03 +000010161 return false;
10162}
10163
10164
10165THREADED_TEST(AccessControlGetOwnPropertyNames) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010166 v8::Isolate* isolate = CcTest::isolate();
10167 v8::HandleScope handle_scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010168 v8::Local<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New(isolate);
Leon Clarke4515c472010-02-03 11:58:03 +000010169
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010170 obj_template->Set(v8_str("x"), v8::Integer::New(isolate, 42));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010171 obj_template->SetAccessCheckCallback(AccessAlwaysBlocked);
10172
10173 // Add an accessor accessible by cross-domain JS code.
10174 obj_template->SetAccessor(
10175 v8_str("accessible_prop"), EchoGetter, EchoSetter, v8::Local<Value>(),
10176 v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
Leon Clarke4515c472010-02-03 11:58:03 +000010177
10178 // Create an environment
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010179 v8::Local<Context> context0 = Context::New(isolate, NULL, obj_template);
Leon Clarke4515c472010-02-03 11:58:03 +000010180 context0->Enter();
10181
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010182 v8::Local<v8::Object> global0 = context0->Global();
Leon Clarke4515c472010-02-03 11:58:03 +000010183
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010184 v8::HandleScope scope1(CcTest::isolate());
Leon Clarke4515c472010-02-03 11:58:03 +000010185
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010186 v8::Local<Context> context1 = Context::New(isolate);
Leon Clarke4515c472010-02-03 11:58:03 +000010187 context1->Enter();
10188
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010189 v8::Local<v8::Object> global1 = context1->Global();
10190 CHECK(global1->Set(context1, v8_str("other"), global0).FromJust());
10191 CHECK(global1->Set(context1, v8_str("object"),
10192 obj_template->NewInstance(context1).ToLocalChecked())
10193 .FromJust());
Leon Clarke4515c472010-02-03 11:58:03 +000010194
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010195 v8::Local<Value> value;
Leon Clarke4515c472010-02-03 11:58:03 +000010196
10197 // Attempt to get the property names of the other global object and
10198 // of an object that requires access checks. Accessing the other
10199 // global object should be blocked by access checks on the global
10200 // proxy object. Accessing the object that requires access checks
10201 // is blocked by the access checks on the object itself.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010202 value = CompileRun(
10203 "var names = Object.getOwnPropertyNames(other);"
10204 "names.length == 1 && names[0] == 'accessible_prop';");
10205 CHECK(value->BooleanValue(context1).FromJust());
Leon Clarke4515c472010-02-03 11:58:03 +000010206
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010207 value = CompileRun(
10208 "var names = Object.getOwnPropertyNames(object);"
10209 "names.length == 1 && names[0] == 'accessible_prop';");
10210 CHECK(value->BooleanValue(context1).FromJust());
Leon Clarke4515c472010-02-03 11:58:03 +000010211
10212 context1->Exit();
10213 context0->Exit();
Leon Clarke4515c472010-02-03 11:58:03 +000010214}
10215
10216
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010217TEST(Regress470113) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010218 v8::Isolate* isolate = CcTest::isolate();
10219 v8::HandleScope handle_scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010220 v8::Local<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New(isolate);
10221 obj_template->SetAccessCheckCallback(AccessAlwaysBlocked);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010222 LocalContext env;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010223 CHECK(env->Global()
10224 ->Set(env.local(), v8_str("prohibited"),
10225 obj_template->NewInstance(env.local()).ToLocalChecked())
10226 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010227
Emily Bernierd0a1eb72015-03-24 16:35:39 -040010228 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010229 v8::TryCatch try_catch(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040010230 CompileRun(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010231 "'use strict';\n"
10232 "class C extends Object {\n"
10233 " m() { super.powned = 'Powned!'; }\n"
10234 "}\n"
10235 "let c = new C();\n"
10236 "c.m.call(prohibited)");
10237
Emily Bernierd0a1eb72015-03-24 16:35:39 -040010238 CHECK(try_catch.HasCaught());
10239 }
Steve Block8defd9f2010-07-08 12:39:36 +010010240}
10241
10242
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010243static void ConstTenGetter(Local<String> name,
10244 const v8::PropertyCallbackInfo<v8::Value>& info) {
10245 info.GetReturnValue().Set(v8_num(10));
Steve Blocka7e24c12009-10-30 11:49:00 +000010246}
10247
10248
10249THREADED_TEST(CrossDomainAccessors) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010250 v8::Isolate* isolate = CcTest::isolate();
10251 v8::HandleScope handle_scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010252
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010253 v8::Local<v8::FunctionTemplate> func_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010254 v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010255
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010256 v8::Local<v8::ObjectTemplate> global_template =
Steve Blocka7e24c12009-10-30 11:49:00 +000010257 func_template->InstanceTemplate();
10258
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010259 v8::Local<v8::ObjectTemplate> proto_template =
Steve Blocka7e24c12009-10-30 11:49:00 +000010260 func_template->PrototypeTemplate();
10261
10262 // Add an accessor to proto that's accessible by cross-domain JS code.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010263 proto_template->SetAccessor(v8_str("accessible"), ConstTenGetter, 0,
10264 v8::Local<Value>(), v8::ALL_CAN_READ);
Steve Blocka7e24c12009-10-30 11:49:00 +000010265
10266 // Add an accessor that is not accessible by cross-domain JS code.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010267 global_template->SetAccessor(v8_str("unreachable"), UnreachableGetter, 0,
10268 v8::Local<Value>(), v8::DEFAULT);
Steve Blocka7e24c12009-10-30 11:49:00 +000010269
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010270 v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
Steve Blocka7e24c12009-10-30 11:49:00 +000010271 context0->Enter();
10272
10273 Local<v8::Object> global = context0->Global();
10274 // Add a normal property that shadows 'accessible'
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010275 CHECK(global->Set(context0, v8_str("accessible"), v8_num(11)).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010276
10277 // Enter a new context.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010278 v8::HandleScope scope1(CcTest::isolate());
10279 v8::Local<Context> context1 = Context::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010280 context1->Enter();
10281
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010282 v8::Local<v8::Object> global1 = context1->Global();
10283 CHECK(global1->Set(context1, v8_str("other"), global).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010284
10285 // Should return 10, instead of 11
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010286 v8::Local<Value> value =
10287 v8_compile("other.accessible")->Run(context1).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000010288 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010289 CHECK_EQ(10, value->Int32Value(context1).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010290
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010291 v8::MaybeLocal<v8::Value> maybe_value =
10292 v8_compile("other.unreachable")->Run(context1);
10293 CHECK(maybe_value.IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +000010294
10295 context1->Exit();
10296 context0->Exit();
Steve Blocka7e24c12009-10-30 11:49:00 +000010297}
10298
10299
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010300static int access_count = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +000010301
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010302static bool AccessCounter(Local<v8::Context> accessing_context,
Ben Murdoch097c5b22016-05-18 11:27:45 +010010303 Local<v8::Object> accessed_object,
10304 Local<v8::Value> data) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010305 access_count++;
Steve Blocka7e24c12009-10-30 11:49:00 +000010306 return true;
10307}
10308
10309
10310// This one is too easily disturbed by other tests.
10311TEST(AccessControlIC) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010312 access_count = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +000010313
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010314 v8::Isolate* isolate = CcTest::isolate();
10315 v8::HandleScope handle_scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010316
10317 // Create an environment.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010318 v8::Local<Context> context0 = Context::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010319 context0->Enter();
10320
10321 // Create an object that requires access-check functions to be
10322 // called for cross-domain access.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010323 v8::Local<v8::ObjectTemplate> object_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010324 v8::ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010325 object_template->SetAccessCheckCallback(AccessCounter);
10326 Local<v8::Object> object =
10327 object_template->NewInstance(context0).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000010328
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010329 v8::HandleScope scope1(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010330
10331 // Create another environment.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010332 v8::Local<Context> context1 = Context::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010333 context1->Enter();
10334
10335 // Make easy access to the object from the other environment.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010336 v8::Local<v8::Object> global1 = context1->Global();
10337 CHECK(global1->Set(context1, v8_str("obj"), object).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010338
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010339 v8::Local<Value> value;
Steve Blocka7e24c12009-10-30 11:49:00 +000010340
10341 // Check that the named access-control function is called every time.
10342 CompileRun("function testProp(obj) {"
10343 " for (var i = 0; i < 10; i++) obj.prop = 1;"
10344 " for (var j = 0; j < 10; j++) obj.prop;"
10345 " return obj.prop"
10346 "}");
10347 value = CompileRun("testProp(obj)");
10348 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010349 CHECK_EQ(1, value->Int32Value(context1).FromJust());
10350 CHECK_EQ(21, access_count);
Steve Blocka7e24c12009-10-30 11:49:00 +000010351
10352 // Check that the named access-control function is called every time.
10353 CompileRun("var p = 'prop';"
10354 "function testKeyed(obj) {"
10355 " for (var i = 0; i < 10; i++) obj[p] = 1;"
10356 " for (var j = 0; j < 10; j++) obj[p];"
10357 " return obj[p];"
10358 "}");
10359 // Use obj which requires access checks. No inline caching is used
10360 // in that case.
10361 value = CompileRun("testKeyed(obj)");
10362 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010363 CHECK_EQ(1, value->Int32Value(context1).FromJust());
10364 CHECK_EQ(42, access_count);
Steve Blocka7e24c12009-10-30 11:49:00 +000010365 // Force the inline caches into generic state and try again.
10366 CompileRun("testKeyed({ a: 0 })");
10367 CompileRun("testKeyed({ b: 0 })");
10368 value = CompileRun("testKeyed(obj)");
10369 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010370 CHECK_EQ(1, value->Int32Value(context1).FromJust());
10371 CHECK_EQ(63, access_count);
Steve Blocka7e24c12009-10-30 11:49:00 +000010372
10373 // Check that the indexed access-control function is called every time.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010374 access_count = 0;
10375
Steve Blocka7e24c12009-10-30 11:49:00 +000010376 CompileRun("function testIndexed(obj) {"
10377 " for (var i = 0; i < 10; i++) obj[0] = 1;"
10378 " for (var j = 0; j < 10; j++) obj[0];"
10379 " return obj[0]"
10380 "}");
10381 value = CompileRun("testIndexed(obj)");
10382 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010383 CHECK_EQ(1, value->Int32Value(context1).FromJust());
10384 CHECK_EQ(21, access_count);
Steve Blocka7e24c12009-10-30 11:49:00 +000010385 // Force the inline caches into generic state.
10386 CompileRun("testIndexed(new Array(1))");
10387 // Test that the indexed access check is called.
10388 value = CompileRun("testIndexed(obj)");
10389 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010390 CHECK_EQ(1, value->Int32Value(context1).FromJust());
10391 CHECK_EQ(42, access_count);
Steve Blocka7e24c12009-10-30 11:49:00 +000010392
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010393 access_count = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +000010394 // Check that the named access check is called when invoking
10395 // functions on an object that requires access checks.
10396 CompileRun("obj.f = function() {}");
10397 CompileRun("function testCallNormal(obj) {"
10398 " for (var i = 0; i < 10; i++) obj.f();"
10399 "}");
10400 CompileRun("testCallNormal(obj)");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010401 printf("%i\n", access_count);
10402 CHECK_EQ(11, access_count);
Steve Blocka7e24c12009-10-30 11:49:00 +000010403
10404 // Force obj into slow case.
10405 value = CompileRun("delete obj.prop");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010406 CHECK(value->BooleanValue(context1).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010407 // Force inline caches into dictionary probing mode.
10408 CompileRun("var o = { x: 0 }; delete o.x; testProp(o);");
10409 // Test that the named access check is called.
10410 value = CompileRun("testProp(obj);");
10411 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010412 CHECK_EQ(1, value->Int32Value(context1).FromJust());
10413 CHECK_EQ(33, access_count);
Steve Blocka7e24c12009-10-30 11:49:00 +000010414
10415 // Force the call inline cache into dictionary probing mode.
10416 CompileRun("o.f = function() {}; testCallNormal(o)");
10417 // Test that the named access check is still called for each
10418 // invocation of the function.
10419 value = CompileRun("testCallNormal(obj)");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010420 CHECK_EQ(43, access_count);
Steve Blocka7e24c12009-10-30 11:49:00 +000010421
10422 context1->Exit();
10423 context0->Exit();
Steve Blocka7e24c12009-10-30 11:49:00 +000010424}
10425
10426
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010427THREADED_TEST(Version) { v8::V8::GetVersion(); }
Steve Blocka7e24c12009-10-30 11:49:00 +000010428
10429
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010430static void InstanceFunctionCallback(
10431 const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +000010432 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010433 args.GetReturnValue().Set(v8_num(12));
Steve Blocka7e24c12009-10-30 11:49:00 +000010434}
10435
10436
10437THREADED_TEST(InstanceProperties) {
Steve Blocka7e24c12009-10-30 11:49:00 +000010438 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010439 v8::Isolate* isolate = context->GetIsolate();
10440 v8::HandleScope handle_scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010441
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010442 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010443 Local<ObjectTemplate> instance = t->InstanceTemplate();
10444
10445 instance->Set(v8_str("x"), v8_num(42));
10446 instance->Set(v8_str("f"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010447 v8::FunctionTemplate::New(isolate, InstanceFunctionCallback));
Steve Blocka7e24c12009-10-30 11:49:00 +000010448
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010449 Local<Value> o = t->GetFunction(context.local())
10450 .ToLocalChecked()
10451 ->NewInstance(context.local())
10452 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000010453
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010454 CHECK(context->Global()->Set(context.local(), v8_str("i"), o).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010455 Local<Value> value = CompileRun("i.x");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010456 CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010457
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010458 value = CompileRun("i.f()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010459 CHECK_EQ(12, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010460}
10461
10462
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010463static void GlobalObjectInstancePropertiesGet(
Emily Bernierd0a1eb72015-03-24 16:35:39 -040010464 Local<Name> key, const v8::PropertyCallbackInfo<v8::Value>&) {
Steve Blocka7e24c12009-10-30 11:49:00 +000010465 ApiTestFuzzer::Fuzz();
Steve Blocka7e24c12009-10-30 11:49:00 +000010466}
10467
10468
10469THREADED_TEST(GlobalObjectInstanceProperties) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010470 v8::Isolate* isolate = CcTest::isolate();
10471 v8::HandleScope handle_scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010472
10473 Local<Value> global_object;
10474
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010475 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040010476 t->InstanceTemplate()->SetHandler(
10477 v8::NamedPropertyHandlerConfiguration(GlobalObjectInstancePropertiesGet));
Steve Blocka7e24c12009-10-30 11:49:00 +000010478 Local<ObjectTemplate> instance_template = t->InstanceTemplate();
10479 instance_template->Set(v8_str("x"), v8_num(42));
10480 instance_template->Set(v8_str("f"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010481 v8::FunctionTemplate::New(isolate,
10482 InstanceFunctionCallback));
Steve Blocka7e24c12009-10-30 11:49:00 +000010483
Ben Murdochb0fe1622011-05-05 13:52:32 +010010484 // The script to check how Crankshaft compiles missing global function
10485 // invocations. function g is not defined and should throw on call.
10486 const char* script =
10487 "function wrapper(call) {"
10488 " var x = 0, y = 1;"
10489 " for (var i = 0; i < 1000; i++) {"
10490 " x += i * 100;"
10491 " y += i * 100;"
10492 " }"
10493 " if (call) g();"
10494 "}"
10495 "for (var i = 0; i < 17; i++) wrapper(false);"
10496 "var thrown = 0;"
10497 "try { wrapper(true); } catch (e) { thrown = 1; };"
10498 "thrown";
10499
Steve Blocka7e24c12009-10-30 11:49:00 +000010500 {
10501 LocalContext env(NULL, instance_template);
10502 // Hold on to the global object so it can be used again in another
10503 // environment initialization.
10504 global_object = env->Global();
10505
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010506 Local<Value> value = CompileRun("x");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010507 CHECK_EQ(42, value->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010508 value = CompileRun("f()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010509 CHECK_EQ(12, value->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010510 value = CompileRun(script);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010511 CHECK_EQ(1, value->Int32Value(env.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010512 }
10513
10514 {
10515 // Create new environment reusing the global object.
10516 LocalContext env(NULL, instance_template, global_object);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010517 Local<Value> value = CompileRun("x");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010518 CHECK_EQ(42, value->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010519 value = CompileRun("f()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010520 CHECK_EQ(12, value->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010521 value = CompileRun(script);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010522 CHECK_EQ(1, value->Int32Value(env.local()).FromJust());
Ben Murdochb0fe1622011-05-05 13:52:32 +010010523 }
10524}
10525
Ben Murdochc5610432016-08-08 18:44:38 +010010526THREADED_TEST(ObjectGetOwnPropertyNames) {
10527 LocalContext context;
10528 v8::Isolate* isolate = context->GetIsolate();
10529 v8::HandleScope handle_scope(isolate);
10530
10531 v8::Local<v8::Object> value =
10532 v8::Local<v8::Object>::Cast(v8::StringObject::New(v8_str("test")));
10533 v8::Local<v8::Array> properties;
10534
10535 CHECK(value
10536 ->GetOwnPropertyNames(context.local(),
10537 static_cast<v8::PropertyFilter>(
10538 v8::PropertyFilter::ALL_PROPERTIES |
10539 v8::PropertyFilter::SKIP_SYMBOLS))
10540 .ToLocal(&properties));
10541 CHECK_EQ(5, properties->Length());
10542 v8::Local<v8::Value> property;
10543 CHECK(properties->Get(context.local(), 4).ToLocal(&property) &&
10544 property->IsString());
10545 CHECK(property.As<v8::String>()
10546 ->Equals(context.local(), v8_str("length"))
10547 .FromMaybe(false));
10548 for (int i = 0; i < 4; ++i) {
10549 v8::Local<v8::Value> property;
10550 CHECK(properties->Get(context.local(), i).ToLocal(&property) &&
10551 property->IsInt32());
10552 CHECK_EQ(property.As<v8::Int32>()->Value(), i);
10553 }
10554
10555 CHECK(value->GetOwnPropertyNames(context.local(), v8::ONLY_ENUMERABLE)
10556 .ToLocal(&properties));
10557 CHECK_EQ(4, properties->Length());
10558 for (int i = 0; i < 4; ++i) {
10559 v8::Local<v8::Value> property;
10560 CHECK(properties->Get(context.local(), i).ToLocal(&property) &&
10561 property->IsInt32());
10562 CHECK_EQ(property.As<v8::Int32>()->Value(), i);
10563 }
10564
10565 value = value->GetPrototype().As<v8::Object>();
10566 CHECK(value
10567 ->GetOwnPropertyNames(context.local(),
10568 static_cast<v8::PropertyFilter>(
10569 v8::PropertyFilter::ALL_PROPERTIES |
10570 v8::PropertyFilter::SKIP_SYMBOLS))
10571 .ToLocal(&properties));
10572 bool concat_found = false;
10573 bool starts_with_found = false;
10574 for (uint32_t i = 0; i < properties->Length(); ++i) {
10575 v8::Local<v8::Value> property;
10576 CHECK(properties->Get(context.local(), i).ToLocal(&property));
10577 if (!property->IsString()) continue;
10578 if (!concat_found)
10579 concat_found = property.As<v8::String>()
10580 ->Equals(context.local(), v8_str("concat"))
10581 .FromMaybe(false);
10582 if (!starts_with_found)
10583 starts_with_found = property.As<v8::String>()
10584 ->Equals(context.local(), v8_str("startsWith"))
10585 .FromMaybe(false);
10586 }
10587 CHECK(concat_found && starts_with_found);
10588}
Ben Murdochb0fe1622011-05-05 13:52:32 +010010589
10590THREADED_TEST(CallKnownGlobalReceiver) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010591 v8::Isolate* isolate = CcTest::isolate();
10592 v8::HandleScope handle_scope(isolate);
Ben Murdochb0fe1622011-05-05 13:52:32 +010010593
10594 Local<Value> global_object;
10595
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010596 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
Ben Murdochb0fe1622011-05-05 13:52:32 +010010597 Local<ObjectTemplate> instance_template = t->InstanceTemplate();
10598
10599 // The script to check that we leave global object not
10600 // global object proxy on stack when we deoptimize from inside
10601 // arguments evaluation.
10602 // To provoke error we need to both force deoptimization
10603 // from arguments evaluation and to force CallIC to take
10604 // CallIC_Miss code path that can't cope with global proxy.
10605 const char* script =
10606 "function bar(x, y) { try { } finally { } }"
10607 "function baz(x) { try { } finally { } }"
10608 "function bom(x) { try { } finally { } }"
10609 "function foo(x) { bar([x], bom(2)); }"
10610 "for (var i = 0; i < 10000; i++) foo(1);"
10611 "foo";
10612
10613 Local<Value> foo;
10614 {
10615 LocalContext env(NULL, instance_template);
10616 // Hold on to the global object so it can be used again in another
10617 // environment initialization.
10618 global_object = env->Global();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010619 foo = CompileRun(script);
Ben Murdochb0fe1622011-05-05 13:52:32 +010010620 }
10621
10622 {
10623 // Create new environment reusing the global object.
10624 LocalContext env(NULL, instance_template, global_object);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010625 CHECK(env->Global()->Set(env.local(), v8_str("foo"), foo).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010626 CompileRun("foo()");
Steve Blocka7e24c12009-10-30 11:49:00 +000010627 }
10628}
10629
10630
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010631static void ShadowFunctionCallback(
10632 const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +000010633 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010634 args.GetReturnValue().Set(v8_num(42));
Steve Blocka7e24c12009-10-30 11:49:00 +000010635}
10636
10637
10638static int shadow_y;
10639static int shadow_y_setter_call_count;
10640static int shadow_y_getter_call_count;
10641
10642
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010643static void ShadowYSetter(Local<String>,
10644 Local<Value>,
10645 const v8::PropertyCallbackInfo<void>&) {
Steve Blocka7e24c12009-10-30 11:49:00 +000010646 shadow_y_setter_call_count++;
10647 shadow_y = 42;
10648}
10649
10650
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010651static void ShadowYGetter(Local<String> name,
10652 const v8::PropertyCallbackInfo<v8::Value>& info) {
Steve Blocka7e24c12009-10-30 11:49:00 +000010653 ApiTestFuzzer::Fuzz();
10654 shadow_y_getter_call_count++;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010655 info.GetReturnValue().Set(v8_num(shadow_y));
Steve Blocka7e24c12009-10-30 11:49:00 +000010656}
10657
10658
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010659static void ShadowIndexedGet(uint32_t index,
10660 const v8::PropertyCallbackInfo<v8::Value>&) {
Steve Blocka7e24c12009-10-30 11:49:00 +000010661}
10662
10663
Emily Bernierd0a1eb72015-03-24 16:35:39 -040010664static void ShadowNamedGet(Local<Name> key,
10665 const v8::PropertyCallbackInfo<v8::Value>&) {}
Steve Blocka7e24c12009-10-30 11:49:00 +000010666
10667
10668THREADED_TEST(ShadowObject) {
10669 shadow_y = shadow_y_setter_call_count = shadow_y_getter_call_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010670 v8::Isolate* isolate = CcTest::isolate();
10671 v8::HandleScope handle_scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010672
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010673 Local<ObjectTemplate> global_template = v8::ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010674 LocalContext context(NULL, global_template);
10675
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010676 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040010677 t->InstanceTemplate()->SetHandler(
10678 v8::NamedPropertyHandlerConfiguration(ShadowNamedGet));
10679 t->InstanceTemplate()->SetHandler(
10680 v8::IndexedPropertyHandlerConfiguration(ShadowIndexedGet));
Steve Blocka7e24c12009-10-30 11:49:00 +000010681 Local<ObjectTemplate> proto = t->PrototypeTemplate();
10682 Local<ObjectTemplate> instance = t->InstanceTemplate();
10683
Steve Blocka7e24c12009-10-30 11:49:00 +000010684 proto->Set(v8_str("f"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010685 v8::FunctionTemplate::New(isolate,
10686 ShadowFunctionCallback,
10687 Local<Value>()));
Steve Blocka7e24c12009-10-30 11:49:00 +000010688 proto->Set(v8_str("x"), v8_num(12));
10689
10690 instance->SetAccessor(v8_str("y"), ShadowYGetter, ShadowYSetter);
10691
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010692 Local<Value> o = t->GetFunction(context.local())
10693 .ToLocalChecked()
10694 ->NewInstance(context.local())
10695 .ToLocalChecked();
10696 CHECK(context->Global()
10697 ->Set(context.local(), v8_str("__proto__"), o)
10698 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010699
10700 Local<Value> value =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010701 CompileRun("this.propertyIsEnumerable(0)");
Steve Blocka7e24c12009-10-30 11:49:00 +000010702 CHECK(value->IsBoolean());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010703 CHECK(!value->BooleanValue(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010704
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010705 value = CompileRun("x");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010706 CHECK_EQ(12, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010707
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010708 value = CompileRun("f()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010709 CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010710
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010711 CompileRun("y = 43");
Steve Blocka7e24c12009-10-30 11:49:00 +000010712 CHECK_EQ(1, shadow_y_setter_call_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010713 value = CompileRun("y");
Steve Blocka7e24c12009-10-30 11:49:00 +000010714 CHECK_EQ(1, shadow_y_getter_call_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010715 CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010716}
10717
10718
10719THREADED_TEST(HiddenPrototype) {
Steve Blocka7e24c12009-10-30 11:49:00 +000010720 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010721 v8::Isolate* isolate = context->GetIsolate();
10722 v8::HandleScope handle_scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010723
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010724 Local<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010725 t0->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010726 Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010727 t1->SetHiddenPrototype(true);
10728 t1->InstanceTemplate()->Set(v8_str("y"), v8_num(1));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010729 Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010730 t2->SetHiddenPrototype(true);
10731 t2->InstanceTemplate()->Set(v8_str("z"), v8_num(2));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010732 Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010733 t3->InstanceTemplate()->Set(v8_str("u"), v8_num(3));
10734
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010735 Local<v8::Object> o0 = t0->GetFunction(context.local())
10736 .ToLocalChecked()
10737 ->NewInstance(context.local())
10738 .ToLocalChecked();
10739 Local<v8::Object> o1 = t1->GetFunction(context.local())
10740 .ToLocalChecked()
10741 ->NewInstance(context.local())
10742 .ToLocalChecked();
10743 Local<v8::Object> o2 = t2->GetFunction(context.local())
10744 .ToLocalChecked()
10745 ->NewInstance(context.local())
10746 .ToLocalChecked();
10747 Local<v8::Object> o3 = t3->GetFunction(context.local())
10748 .ToLocalChecked()
10749 ->NewInstance(context.local())
10750 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000010751
10752 // Setting the prototype on an object skips hidden prototypes.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010753 CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
10754 .ToLocalChecked()
10755 ->Int32Value(context.local())
10756 .FromJust());
10757 CHECK(o0->Set(context.local(), v8_str("__proto__"), o1).FromJust());
10758 CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
10759 .ToLocalChecked()
10760 ->Int32Value(context.local())
10761 .FromJust());
10762 CHECK_EQ(1, o0->Get(context.local(), v8_str("y"))
10763 .ToLocalChecked()
10764 ->Int32Value(context.local())
10765 .FromJust());
10766 CHECK(o0->Set(context.local(), v8_str("__proto__"), o2).FromJust());
10767 CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
10768 .ToLocalChecked()
10769 ->Int32Value(context.local())
10770 .FromJust());
10771 CHECK_EQ(1, o0->Get(context.local(), v8_str("y"))
10772 .ToLocalChecked()
10773 ->Int32Value(context.local())
10774 .FromJust());
10775 CHECK_EQ(2, o0->Get(context.local(), v8_str("z"))
10776 .ToLocalChecked()
10777 ->Int32Value(context.local())
10778 .FromJust());
10779 CHECK(o0->Set(context.local(), v8_str("__proto__"), o3).FromJust());
10780 CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
10781 .ToLocalChecked()
10782 ->Int32Value(context.local())
10783 .FromJust());
10784 CHECK_EQ(1, o0->Get(context.local(), v8_str("y"))
10785 .ToLocalChecked()
10786 ->Int32Value(context.local())
10787 .FromJust());
10788 CHECK_EQ(2, o0->Get(context.local(), v8_str("z"))
10789 .ToLocalChecked()
10790 ->Int32Value(context.local())
10791 .FromJust());
10792 CHECK_EQ(3, o0->Get(context.local(), v8_str("u"))
10793 .ToLocalChecked()
10794 ->Int32Value(context.local())
10795 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010796
10797 // Getting the prototype of o0 should get the first visible one
10798 // which is o3. Therefore, z should not be defined on the prototype
10799 // object.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010800 Local<Value> proto =
10801 o0->Get(context.local(), v8_str("__proto__")).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000010802 CHECK(proto->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010803 CHECK(proto.As<v8::Object>()
10804 ->Get(context.local(), v8_str("z"))
10805 .ToLocalChecked()
10806 ->IsUndefined());
Steve Blocka7e24c12009-10-30 11:49:00 +000010807}
10808
10809
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010810THREADED_TEST(HiddenPrototypeSet) {
Andrei Popescu402d9372010-02-26 13:31:12 +000010811 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010812 v8::Isolate* isolate = context->GetIsolate();
10813 v8::HandleScope handle_scope(isolate);
Andrei Popescu402d9372010-02-26 13:31:12 +000010814
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010815 Local<v8::FunctionTemplate> ot = v8::FunctionTemplate::New(isolate);
10816 Local<v8::FunctionTemplate> ht = v8::FunctionTemplate::New(isolate);
10817 ht->SetHiddenPrototype(true);
10818 Local<v8::FunctionTemplate> pt = v8::FunctionTemplate::New(isolate);
10819 ht->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
10820
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010821 Local<v8::Object> o = ot->GetFunction(context.local())
10822 .ToLocalChecked()
10823 ->NewInstance(context.local())
10824 .ToLocalChecked();
10825 Local<v8::Object> h = ht->GetFunction(context.local())
10826 .ToLocalChecked()
10827 ->NewInstance(context.local())
10828 .ToLocalChecked();
10829 Local<v8::Object> p = pt->GetFunction(context.local())
10830 .ToLocalChecked()
10831 ->NewInstance(context.local())
10832 .ToLocalChecked();
10833 CHECK(o->Set(context.local(), v8_str("__proto__"), h).FromJust());
10834 CHECK(h->Set(context.local(), v8_str("__proto__"), p).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010835
10836 // Setting a property that exists on the hidden prototype goes there.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010837 CHECK(o->Set(context.local(), v8_str("x"), v8_num(7)).FromJust());
10838 CHECK_EQ(7, o->Get(context.local(), v8_str("x"))
10839 .ToLocalChecked()
10840 ->Int32Value(context.local())
10841 .FromJust());
10842 CHECK_EQ(7, h->Get(context.local(), v8_str("x"))
10843 .ToLocalChecked()
10844 ->Int32Value(context.local())
10845 .FromJust());
10846 CHECK(p->Get(context.local(), v8_str("x")).ToLocalChecked()->IsUndefined());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010847
10848 // Setting a new property should not be forwarded to the hidden prototype.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010849 CHECK(o->Set(context.local(), v8_str("y"), v8_num(6)).FromJust());
10850 CHECK_EQ(6, o->Get(context.local(), v8_str("y"))
10851 .ToLocalChecked()
10852 ->Int32Value(context.local())
10853 .FromJust());
10854 CHECK(h->Get(context.local(), v8_str("y")).ToLocalChecked()->IsUndefined());
10855 CHECK(p->Get(context.local(), v8_str("y")).ToLocalChecked()->IsUndefined());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010856
10857 // Setting a property that only exists on a prototype of the hidden prototype
10858 // is treated normally again.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010859 CHECK(p->Set(context.local(), v8_str("z"), v8_num(8)).FromJust());
10860 CHECK_EQ(8, o->Get(context.local(), v8_str("z"))
10861 .ToLocalChecked()
10862 ->Int32Value(context.local())
10863 .FromJust());
10864 CHECK_EQ(8, h->Get(context.local(), v8_str("z"))
10865 .ToLocalChecked()
10866 ->Int32Value(context.local())
10867 .FromJust());
10868 CHECK_EQ(8, p->Get(context.local(), v8_str("z"))
10869 .ToLocalChecked()
10870 ->Int32Value(context.local())
10871 .FromJust());
10872 CHECK(o->Set(context.local(), v8_str("z"), v8_num(9)).FromJust());
10873 CHECK_EQ(9, o->Get(context.local(), v8_str("z"))
10874 .ToLocalChecked()
10875 ->Int32Value(context.local())
10876 .FromJust());
10877 CHECK_EQ(8, h->Get(context.local(), v8_str("z"))
10878 .ToLocalChecked()
10879 ->Int32Value(context.local())
10880 .FromJust());
10881 CHECK_EQ(8, p->Get(context.local(), v8_str("z"))
10882 .ToLocalChecked()
10883 ->Int32Value(context.local())
10884 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010885}
10886
10887
10888// Regression test for issue 2457.
10889THREADED_TEST(HiddenPrototypeIdentityHash) {
10890 LocalContext context;
10891 v8::HandleScope handle_scope(context->GetIsolate());
10892
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010893 Local<FunctionTemplate> t = FunctionTemplate::New(context->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010894 t->SetHiddenPrototype(true);
10895 t->InstanceTemplate()->Set(v8_str("foo"), v8_num(75));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010896 Local<Object> p = t->GetFunction(context.local())
10897 .ToLocalChecked()
10898 ->NewInstance(context.local())
10899 .ToLocalChecked();
10900 Local<Object> o = Object::New(context->GetIsolate());
10901 CHECK(o->SetPrototype(context.local(), p).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010902
10903 int hash = o->GetIdentityHash();
10904 USE(hash);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010905 CHECK(o->Set(context.local(), v8_str("foo"), v8_num(42)).FromJust());
10906 CHECK_EQ(hash, o->GetIdentityHash());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010907}
10908
10909
10910THREADED_TEST(SetPrototype) {
10911 LocalContext context;
10912 v8::Isolate* isolate = context->GetIsolate();
10913 v8::HandleScope handle_scope(isolate);
10914
10915 Local<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New(isolate);
Andrei Popescu402d9372010-02-26 13:31:12 +000010916 t0->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010917 Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
Andrei Popescu402d9372010-02-26 13:31:12 +000010918 t1->SetHiddenPrototype(true);
10919 t1->InstanceTemplate()->Set(v8_str("y"), v8_num(1));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010920 Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
Andrei Popescu402d9372010-02-26 13:31:12 +000010921 t2->SetHiddenPrototype(true);
10922 t2->InstanceTemplate()->Set(v8_str("z"), v8_num(2));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010923 Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
Andrei Popescu402d9372010-02-26 13:31:12 +000010924 t3->InstanceTemplate()->Set(v8_str("u"), v8_num(3));
10925
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010926 Local<v8::Object> o0 = t0->GetFunction(context.local())
10927 .ToLocalChecked()
10928 ->NewInstance(context.local())
10929 .ToLocalChecked();
10930 Local<v8::Object> o1 = t1->GetFunction(context.local())
10931 .ToLocalChecked()
10932 ->NewInstance(context.local())
10933 .ToLocalChecked();
10934 Local<v8::Object> o2 = t2->GetFunction(context.local())
10935 .ToLocalChecked()
10936 ->NewInstance(context.local())
10937 .ToLocalChecked();
10938 Local<v8::Object> o3 = t3->GetFunction(context.local())
10939 .ToLocalChecked()
10940 ->NewInstance(context.local())
10941 .ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000010942
10943 // Setting the prototype on an object does not skip hidden prototypes.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010944 CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
10945 .ToLocalChecked()
10946 ->Int32Value(context.local())
10947 .FromJust());
10948 CHECK(o0->SetPrototype(context.local(), o1).FromJust());
10949 CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
10950 .ToLocalChecked()
10951 ->Int32Value(context.local())
10952 .FromJust());
10953 CHECK_EQ(1, o0->Get(context.local(), v8_str("y"))
10954 .ToLocalChecked()
10955 ->Int32Value(context.local())
10956 .FromJust());
10957 CHECK(o1->SetPrototype(context.local(), o2).FromJust());
10958 CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
10959 .ToLocalChecked()
10960 ->Int32Value(context.local())
10961 .FromJust());
10962 CHECK_EQ(1, o0->Get(context.local(), v8_str("y"))
10963 .ToLocalChecked()
10964 ->Int32Value(context.local())
10965 .FromJust());
10966 CHECK_EQ(2, o0->Get(context.local(), v8_str("z"))
10967 .ToLocalChecked()
10968 ->Int32Value(context.local())
10969 .FromJust());
10970 CHECK(o2->SetPrototype(context.local(), o3).FromJust());
10971 CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
10972 .ToLocalChecked()
10973 ->Int32Value(context.local())
10974 .FromJust());
10975 CHECK_EQ(1, o0->Get(context.local(), v8_str("y"))
10976 .ToLocalChecked()
10977 ->Int32Value(context.local())
10978 .FromJust());
10979 CHECK_EQ(2, o0->Get(context.local(), v8_str("z"))
10980 .ToLocalChecked()
10981 ->Int32Value(context.local())
10982 .FromJust());
10983 CHECK_EQ(3, o0->Get(context.local(), v8_str("u"))
10984 .ToLocalChecked()
10985 ->Int32Value(context.local())
10986 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000010987
10988 // Getting the prototype of o0 should get the first visible one
10989 // which is o3. Therefore, z should not be defined on the prototype
10990 // object.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010991 Local<Value> proto =
10992 o0->Get(context.local(), v8_str("__proto__")).ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000010993 CHECK(proto->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010994 CHECK(proto.As<v8::Object>()->Equals(context.local(), o3).FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000010995
10996 // However, Object::GetPrototype ignores hidden prototype.
10997 Local<Value> proto0 = o0->GetPrototype();
10998 CHECK(proto0->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010999 CHECK(proto0.As<v8::Object>()->Equals(context.local(), o1).FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000011000
11001 Local<Value> proto1 = o1->GetPrototype();
11002 CHECK(proto1->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011003 CHECK(proto1.As<v8::Object>()->Equals(context.local(), o2).FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000011004
11005 Local<Value> proto2 = o2->GetPrototype();
11006 CHECK(proto2->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011007 CHECK(proto2.As<v8::Object>()->Equals(context.local(), o3).FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000011008}
11009
11010
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011011// Getting property names of an object with a prototype chain that
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011012// triggers dictionary elements in GetOwnPropertyNames() shouldn't
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011013// crash the runtime.
11014THREADED_TEST(Regress91517) {
11015 i::FLAG_allow_natives_syntax = true;
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011016 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011017 v8::Isolate* isolate = context->GetIsolate();
11018 v8::HandleScope handle_scope(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011019
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011020 Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011021 t1->SetHiddenPrototype(true);
11022 t1->InstanceTemplate()->Set(v8_str("foo"), v8_num(1));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011023 Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011024 t2->SetHiddenPrototype(true);
11025 t2->InstanceTemplate()->Set(v8_str("fuz1"), v8_num(2));
Ben Murdoch097c5b22016-05-18 11:27:45 +010011026 t2->InstanceTemplate()->Set(v8_str("objects"),
11027 v8::ObjectTemplate::New(isolate));
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011028 t2->InstanceTemplate()->Set(v8_str("fuz2"), v8_num(2));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011029 Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011030 t3->SetHiddenPrototype(true);
11031 t3->InstanceTemplate()->Set(v8_str("boo"), v8_num(3));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011032 Local<v8::FunctionTemplate> t4 = v8::FunctionTemplate::New(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011033 t4->InstanceTemplate()->Set(v8_str("baz"), v8_num(4));
11034
11035 // Force dictionary-based properties.
11036 i::ScopedVector<char> name_buf(1024);
11037 for (int i = 1; i <= 1000; i++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011038 i::SNPrintF(name_buf, "sdf%d", i);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011039 t2->InstanceTemplate()->Set(v8_str(name_buf.start()), v8_num(2));
11040 }
11041
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011042 Local<v8::Object> o1 = t1->GetFunction(context.local())
11043 .ToLocalChecked()
11044 ->NewInstance(context.local())
11045 .ToLocalChecked();
11046 Local<v8::Object> o2 = t2->GetFunction(context.local())
11047 .ToLocalChecked()
11048 ->NewInstance(context.local())
11049 .ToLocalChecked();
11050 Local<v8::Object> o3 = t3->GetFunction(context.local())
11051 .ToLocalChecked()
11052 ->NewInstance(context.local())
11053 .ToLocalChecked();
11054 Local<v8::Object> o4 = t4->GetFunction(context.local())
11055 .ToLocalChecked()
11056 ->NewInstance(context.local())
11057 .ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011058
11059 // Create prototype chain of hidden prototypes.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011060 CHECK(o4->SetPrototype(context.local(), o3).FromJust());
11061 CHECK(o3->SetPrototype(context.local(), o2).FromJust());
11062 CHECK(o2->SetPrototype(context.local(), o1).FromJust());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011063
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011064 // Call the runtime version of GetOwnPropertyNames() on the natively
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011065 // created object through JavaScript.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011066 CHECK(context->Global()->Set(context.local(), v8_str("obj"), o4).FromJust());
11067 // PROPERTY_FILTER_NONE = 0
11068 CompileRun("var names = %GetOwnPropertyKeys(obj, 0);");
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011069
11070 ExpectInt32("names.length", 1006);
11071 ExpectTrue("names.indexOf(\"baz\") >= 0");
11072 ExpectTrue("names.indexOf(\"boo\") >= 0");
11073 ExpectTrue("names.indexOf(\"foo\") >= 0");
11074 ExpectTrue("names.indexOf(\"fuz1\") >= 0");
Ben Murdoch097c5b22016-05-18 11:27:45 +010011075 ExpectTrue("names.indexOf(\"objects\") >= 0");
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011076 ExpectTrue("names.indexOf(\"fuz2\") >= 0");
11077 ExpectFalse("names[1005] == undefined");
11078}
11079
11080
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011081// Getting property names of an object with a hidden and inherited
11082// prototype should not duplicate the accessor properties inherited.
11083THREADED_TEST(Regress269562) {
11084 i::FLAG_allow_natives_syntax = true;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000011085 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011086 v8::HandleScope handle_scope(context->GetIsolate());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000011087
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011088 Local<v8::FunctionTemplate> t1 =
11089 v8::FunctionTemplate::New(context->GetIsolate());
11090 t1->SetHiddenPrototype(true);
11091
11092 Local<v8::ObjectTemplate> i1 = t1->InstanceTemplate();
11093 i1->SetAccessor(v8_str("foo"),
11094 SimpleAccessorGetter, SimpleAccessorSetter);
11095 i1->SetAccessor(v8_str("bar"),
11096 SimpleAccessorGetter, SimpleAccessorSetter);
11097 i1->SetAccessor(v8_str("baz"),
11098 SimpleAccessorGetter, SimpleAccessorSetter);
11099 i1->Set(v8_str("n1"), v8_num(1));
11100 i1->Set(v8_str("n2"), v8_num(2));
11101
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011102 Local<v8::Object> o1 = t1->GetFunction(context.local())
11103 .ToLocalChecked()
11104 ->NewInstance(context.local())
11105 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011106 Local<v8::FunctionTemplate> t2 =
11107 v8::FunctionTemplate::New(context->GetIsolate());
11108 t2->SetHiddenPrototype(true);
11109
11110 // Inherit from t1 and mark prototype as hidden.
11111 t2->Inherit(t1);
11112 t2->InstanceTemplate()->Set(v8_str("mine"), v8_num(4));
11113
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011114 Local<v8::Object> o2 = t2->GetFunction(context.local())
11115 .ToLocalChecked()
11116 ->NewInstance(context.local())
11117 .ToLocalChecked();
11118 CHECK(o2->SetPrototype(context.local(), o1).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011119
11120 v8::Local<v8::Symbol> sym =
11121 v8::Symbol::New(context->GetIsolate(), v8_str("s1"));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011122 CHECK(o1->Set(context.local(), sym, v8_num(3)).FromJust());
11123 o1->SetPrivate(context.local(),
11124 v8::Private::New(context->GetIsolate(), v8_str("h1")),
11125 v8::Integer::New(context->GetIsolate(), 2013))
11126 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011127
11128 // Call the runtime version of GetOwnPropertyNames() on
11129 // the natively created object through JavaScript.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011130 CHECK(context->Global()->Set(context.local(), v8_str("obj"), o2).FromJust());
11131 CHECK(context->Global()->Set(context.local(), v8_str("sym"), sym).FromJust());
11132 // PROPERTY_FILTER_NONE = 0
11133 CompileRun("var names = %GetOwnPropertyKeys(obj, 0);");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011134
11135 ExpectInt32("names.length", 7);
11136 ExpectTrue("names.indexOf(\"foo\") >= 0");
11137 ExpectTrue("names.indexOf(\"bar\") >= 0");
11138 ExpectTrue("names.indexOf(\"baz\") >= 0");
11139 ExpectTrue("names.indexOf(\"n1\") >= 0");
11140 ExpectTrue("names.indexOf(\"n2\") >= 0");
11141 ExpectTrue("names.indexOf(sym) >= 0");
11142 ExpectTrue("names.indexOf(\"mine\") >= 0");
11143}
11144
11145
11146THREADED_TEST(FunctionReadOnlyPrototype) {
11147 LocalContext context;
11148 v8::Isolate* isolate = context->GetIsolate();
11149 v8::HandleScope handle_scope(isolate);
11150
11151 Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
11152 t1->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(isolate, 42));
Ben Murdoch69a99ed2011-11-30 16:03:39 +000011153 t1->ReadOnlyPrototype();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011154 CHECK(context->Global()
11155 ->Set(context.local(), v8_str("func1"),
11156 t1->GetFunction(context.local()).ToLocalChecked())
11157 .FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000011158 // Configured value of ReadOnly flag.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011159 CHECK(
11160 CompileRun(
11161 "(function() {"
11162 " descriptor = Object.getOwnPropertyDescriptor(func1, 'prototype');"
11163 " return (descriptor['writable'] == false);"
11164 "})()")
11165 ->BooleanValue(context.local())
11166 .FromJust());
11167 CHECK_EQ(
11168 42,
11169 CompileRun("func1.prototype.x")->Int32Value(context.local()).FromJust());
11170 CHECK_EQ(42, CompileRun("func1.prototype = {}; func1.prototype.x")
11171 ->Int32Value(context.local())
11172 .FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000011173
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011174 Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
11175 t2->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(isolate, 42));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011176 CHECK(context->Global()
11177 ->Set(context.local(), v8_str("func2"),
11178 t2->GetFunction(context.local()).ToLocalChecked())
11179 .FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000011180 // Default value of ReadOnly flag.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011181 CHECK(
11182 CompileRun(
11183 "(function() {"
11184 " descriptor = Object.getOwnPropertyDescriptor(func2, 'prototype');"
11185 " return (descriptor['writable'] == true);"
11186 "})()")
11187 ->BooleanValue(context.local())
11188 .FromJust());
11189 CHECK_EQ(
11190 42,
11191 CompileRun("func2.prototype.x")->Int32Value(context.local()).FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000011192}
11193
11194
Andrei Popescu402d9372010-02-26 13:31:12 +000011195THREADED_TEST(SetPrototypeThrows) {
Andrei Popescu402d9372010-02-26 13:31:12 +000011196 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011197 v8::Isolate* isolate = context->GetIsolate();
11198 v8::HandleScope handle_scope(isolate);
Andrei Popescu402d9372010-02-26 13:31:12 +000011199
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011200 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
Andrei Popescu402d9372010-02-26 13:31:12 +000011201
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011202 Local<v8::Object> o0 = t->GetFunction(context.local())
11203 .ToLocalChecked()
11204 ->NewInstance(context.local())
11205 .ToLocalChecked();
11206 Local<v8::Object> o1 = t->GetFunction(context.local())
11207 .ToLocalChecked()
11208 ->NewInstance(context.local())
11209 .ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000011210
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011211 CHECK(o0->SetPrototype(context.local(), o1).FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000011212 // If setting the prototype leads to the cycle, SetPrototype should
11213 // return false and keep VM in sane state.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011214 v8::TryCatch try_catch(isolate);
11215 CHECK(o1->SetPrototype(context.local(), o0).IsNothing());
Andrei Popescu402d9372010-02-26 13:31:12 +000011216 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011217 CHECK(!CcTest::i_isolate()->has_pending_exception());
Andrei Popescu402d9372010-02-26 13:31:12 +000011218
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011219 CHECK_EQ(42, CompileRun("function f() { return 42; }; f()")
11220 ->Int32Value(context.local())
11221 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000011222}
11223
11224
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011225THREADED_TEST(FunctionRemovePrototype) {
Steve Blocka7e24c12009-10-30 11:49:00 +000011226 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011227 v8::Isolate* isolate = context->GetIsolate();
11228 v8::HandleScope handle_scope(isolate);
11229
11230 Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
11231 t1->RemovePrototype();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011232 Local<v8::Function> fun = t1->GetFunction(context.local()).ToLocalChecked();
Ben Murdochc5610432016-08-08 18:44:38 +010011233 CHECK(!fun->IsConstructor());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011234 CHECK(context->Global()->Set(context.local(), v8_str("fun"), fun).FromJust());
11235 CHECK(!CompileRun("'prototype' in fun")
11236 ->BooleanValue(context.local())
11237 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011238
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011239 v8::TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011240 CompileRun("new fun()");
11241 CHECK(try_catch.HasCaught());
11242
11243 try_catch.Reset();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011244 CHECK(fun->NewInstance(context.local()).IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011245 CHECK(try_catch.HasCaught());
11246}
11247
11248
11249THREADED_TEST(GetterSetterExceptions) {
11250 LocalContext context;
11251 v8::Isolate* isolate = context->GetIsolate();
11252 v8::HandleScope handle_scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000011253 CompileRun(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011254 "function Foo() { };"
11255 "function Throw() { throw 5; };"
11256 "var x = { };"
11257 "x.__defineSetter__('set', Throw);"
11258 "x.__defineGetter__('get', Throw);");
11259 Local<v8::Object> x = Local<v8::Object>::Cast(
11260 context->Global()->Get(context.local(), v8_str("x")).ToLocalChecked());
11261 v8::TryCatch try_catch(isolate);
11262 CHECK(x->Set(context.local(), v8_str("set"), v8::Integer::New(isolate, 8))
11263 .IsNothing());
11264 CHECK(x->Get(context.local(), v8_str("get")).IsEmpty());
11265 CHECK(x->Set(context.local(), v8_str("set"), v8::Integer::New(isolate, 8))
11266 .IsNothing());
11267 CHECK(x->Get(context.local(), v8_str("get")).IsEmpty());
11268 CHECK(x->Set(context.local(), v8_str("set"), v8::Integer::New(isolate, 8))
11269 .IsNothing());
11270 CHECK(x->Get(context.local(), v8_str("get")).IsEmpty());
11271 CHECK(x->Set(context.local(), v8_str("set"), v8::Integer::New(isolate, 8))
11272 .IsNothing());
11273 CHECK(x->Get(context.local(), v8_str("get")).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +000011274}
11275
11276
11277THREADED_TEST(Constructor) {
Steve Blocka7e24c12009-10-30 11:49:00 +000011278 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011279 v8::Isolate* isolate = context->GetIsolate();
11280 v8::HandleScope handle_scope(isolate);
11281 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000011282 templ->SetClassName(v8_str("Fun"));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011283 Local<Function> cons = templ->GetFunction(context.local()).ToLocalChecked();
11284 CHECK(
11285 context->Global()->Set(context.local(), v8_str("Fun"), cons).FromJust());
11286 Local<v8::Object> inst = cons->NewInstance(context.local()).ToLocalChecked();
11287 i::Handle<i::JSReceiver> obj(v8::Utils::OpenHandle(*inst));
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011288 CHECK(obj->IsJSObject());
Steve Blocka7e24c12009-10-30 11:49:00 +000011289 Local<Value> value = CompileRun("(new Fun()).constructor === Fun");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011290 CHECK(value->BooleanValue(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011291}
11292
Ben Murdoch257744e2011-11-30 15:57:28 +000011293
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011294static void ConstructorCallback(
11295 const v8::FunctionCallbackInfo<v8::Value>& args) {
Ben Murdoch257744e2011-11-30 15:57:28 +000011296 ApiTestFuzzer::Fuzz();
11297 Local<Object> This;
11298
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011299 v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
Ben Murdoch257744e2011-11-30 15:57:28 +000011300 if (args.IsConstructCall()) {
11301 Local<Object> Holder = args.Holder();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011302 This = Object::New(args.GetIsolate());
Ben Murdoch257744e2011-11-30 15:57:28 +000011303 Local<Value> proto = Holder->GetPrototype();
11304 if (proto->IsObject()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011305 This->SetPrototype(context, proto).FromJust();
Ben Murdoch257744e2011-11-30 15:57:28 +000011306 }
11307 } else {
11308 This = args.This();
11309 }
11310
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011311 This->Set(context, v8_str("a"), args[0]).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011312 args.GetReturnValue().Set(This);
Ben Murdoch257744e2011-11-30 15:57:28 +000011313}
11314
11315
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011316static void FakeConstructorCallback(
11317 const v8::FunctionCallbackInfo<v8::Value>& args) {
Ben Murdoch257744e2011-11-30 15:57:28 +000011318 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011319 args.GetReturnValue().Set(args[0]);
Ben Murdoch257744e2011-11-30 15:57:28 +000011320}
11321
11322
11323THREADED_TEST(ConstructorForObject) {
Ben Murdoch257744e2011-11-30 15:57:28 +000011324 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011325 v8::Isolate* isolate = context->GetIsolate();
11326 v8::HandleScope handle_scope(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011327
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011328 {
11329 Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011330 instance_template->SetCallAsFunctionHandler(ConstructorCallback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011331 Local<Object> instance =
11332 instance_template->NewInstance(context.local()).ToLocalChecked();
11333 CHECK(context->Global()
11334 ->Set(context.local(), v8_str("obj"), instance)
11335 .FromJust());
11336 v8::TryCatch try_catch(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011337 Local<Value> value;
11338 CHECK(!try_catch.HasCaught());
11339
11340 // Call the Object's constructor with a 32-bit signed integer.
11341 value = CompileRun("(function() { var o = new obj(28); return o.a; })()");
11342 CHECK(!try_catch.HasCaught());
11343 CHECK(value->IsInt32());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011344 CHECK_EQ(28, value->Int32Value(context.local()).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000011345
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011346 Local<Value> args1[] = {v8_num(28)};
11347 Local<Value> value_obj1 =
11348 instance->CallAsConstructor(context.local(), 1, args1).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011349 CHECK(value_obj1->IsObject());
11350 Local<Object> object1 = Local<Object>::Cast(value_obj1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011351 value = object1->Get(context.local(), v8_str("a")).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011352 CHECK(value->IsInt32());
11353 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011354 CHECK_EQ(28, value->Int32Value(context.local()).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000011355
11356 // Call the Object's constructor with a String.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011357 value =
11358 CompileRun("(function() { var o = new obj('tipli'); return o.a; })()");
Ben Murdoch257744e2011-11-30 15:57:28 +000011359 CHECK(!try_catch.HasCaught());
11360 CHECK(value->IsString());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011361 String::Utf8Value string_value1(
11362 value->ToString(context.local()).ToLocalChecked());
11363 CHECK_EQ(0, strcmp("tipli", *string_value1));
Ben Murdoch257744e2011-11-30 15:57:28 +000011364
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011365 Local<Value> args2[] = {v8_str("tipli")};
11366 Local<Value> value_obj2 =
11367 instance->CallAsConstructor(context.local(), 1, args2).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011368 CHECK(value_obj2->IsObject());
11369 Local<Object> object2 = Local<Object>::Cast(value_obj2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011370 value = object2->Get(context.local(), v8_str("a")).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011371 CHECK(!try_catch.HasCaught());
11372 CHECK(value->IsString());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011373 String::Utf8Value string_value2(
11374 value->ToString(context.local()).ToLocalChecked());
11375 CHECK_EQ(0, strcmp("tipli", *string_value2));
Ben Murdoch257744e2011-11-30 15:57:28 +000011376
11377 // Call the Object's constructor with a Boolean.
11378 value = CompileRun("(function() { var o = new obj(true); return o.a; })()");
11379 CHECK(!try_catch.HasCaught());
11380 CHECK(value->IsBoolean());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011381 CHECK_EQ(true, value->BooleanValue(context.local()).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000011382
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011383 Local<Value> args3[] = {v8::True(isolate)};
11384 Local<Value> value_obj3 =
11385 instance->CallAsConstructor(context.local(), 1, args3).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011386 CHECK(value_obj3->IsObject());
11387 Local<Object> object3 = Local<Object>::Cast(value_obj3);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011388 value = object3->Get(context.local(), v8_str("a")).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011389 CHECK(!try_catch.HasCaught());
11390 CHECK(value->IsBoolean());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011391 CHECK_EQ(true, value->BooleanValue(context.local()).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000011392
11393 // Call the Object's constructor with undefined.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011394 Local<Value> args4[] = {v8::Undefined(isolate)};
11395 Local<Value> value_obj4 =
11396 instance->CallAsConstructor(context.local(), 1, args4).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011397 CHECK(value_obj4->IsObject());
11398 Local<Object> object4 = Local<Object>::Cast(value_obj4);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011399 value = object4->Get(context.local(), v8_str("a")).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011400 CHECK(!try_catch.HasCaught());
11401 CHECK(value->IsUndefined());
11402
11403 // Call the Object's constructor with null.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011404 Local<Value> args5[] = {v8::Null(isolate)};
11405 Local<Value> value_obj5 =
11406 instance->CallAsConstructor(context.local(), 1, args5).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011407 CHECK(value_obj5->IsObject());
11408 Local<Object> object5 = Local<Object>::Cast(value_obj5);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011409 value = object5->Get(context.local(), v8_str("a")).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011410 CHECK(!try_catch.HasCaught());
11411 CHECK(value->IsNull());
11412 }
11413
11414 // Check exception handling when there is no constructor set for the Object.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011415 {
11416 Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
11417 Local<Object> instance =
11418 instance_template->NewInstance(context.local()).ToLocalChecked();
11419 CHECK(context->Global()
11420 ->Set(context.local(), v8_str("obj2"), instance)
11421 .FromJust());
11422 v8::TryCatch try_catch(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011423 Local<Value> value;
11424 CHECK(!try_catch.HasCaught());
11425
11426 value = CompileRun("new obj2(28)");
11427 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011428 String::Utf8Value exception_value1(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011429 CHECK_EQ(0,
11430 strcmp("TypeError: obj2 is not a constructor", *exception_value1));
Ben Murdoch257744e2011-11-30 15:57:28 +000011431 try_catch.Reset();
11432
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011433 Local<Value> args[] = {v8_num(29)};
11434 CHECK(instance->CallAsConstructor(context.local(), 1, args).IsEmpty());
Ben Murdoch257744e2011-11-30 15:57:28 +000011435 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011436 String::Utf8Value exception_value2(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011437 CHECK_EQ(
11438 0, strcmp("TypeError: object is not a constructor", *exception_value2));
Ben Murdoch257744e2011-11-30 15:57:28 +000011439 try_catch.Reset();
11440 }
11441
11442 // Check the case when constructor throws exception.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011443 {
11444 Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011445 instance_template->SetCallAsFunctionHandler(ThrowValue);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011446 Local<Object> instance =
11447 instance_template->NewInstance(context.local()).ToLocalChecked();
11448 CHECK(context->Global()
11449 ->Set(context.local(), v8_str("obj3"), instance)
11450 .FromJust());
11451 v8::TryCatch try_catch(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011452 Local<Value> value;
11453 CHECK(!try_catch.HasCaught());
11454
11455 value = CompileRun("new obj3(22)");
11456 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011457 String::Utf8Value exception_value1(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011458 CHECK_EQ(0, strcmp("22", *exception_value1));
Ben Murdoch257744e2011-11-30 15:57:28 +000011459 try_catch.Reset();
11460
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011461 Local<Value> args[] = {v8_num(23)};
11462 CHECK(instance->CallAsConstructor(context.local(), 1, args).IsEmpty());
Ben Murdoch257744e2011-11-30 15:57:28 +000011463 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011464 String::Utf8Value exception_value2(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011465 CHECK_EQ(0, strcmp("23", *exception_value2));
Ben Murdoch257744e2011-11-30 15:57:28 +000011466 try_catch.Reset();
11467 }
11468
11469 // Check whether constructor returns with an object or non-object.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011470 {
11471 Local<FunctionTemplate> function_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011472 FunctionTemplate::New(isolate, FakeConstructorCallback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011473 Local<Function> function =
11474 function_template->GetFunction(context.local()).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011475 Local<Object> instance1 = function;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011476 CHECK(context->Global()
11477 ->Set(context.local(), v8_str("obj4"), instance1)
11478 .FromJust());
11479 v8::TryCatch try_catch(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011480 Local<Value> value;
11481 CHECK(!try_catch.HasCaught());
11482
11483 CHECK(instance1->IsObject());
11484 CHECK(instance1->IsFunction());
11485
11486 value = CompileRun("new obj4(28)");
11487 CHECK(!try_catch.HasCaught());
11488 CHECK(value->IsObject());
11489
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011490 Local<Value> args1[] = {v8_num(28)};
11491 value = instance1->CallAsConstructor(context.local(), 1, args1)
11492 .ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011493 CHECK(!try_catch.HasCaught());
11494 CHECK(value->IsObject());
11495
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011496 Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011497 instance_template->SetCallAsFunctionHandler(FakeConstructorCallback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011498 Local<Object> instance2 =
11499 instance_template->NewInstance(context.local()).ToLocalChecked();
11500 CHECK(context->Global()
11501 ->Set(context.local(), v8_str("obj5"), instance2)
11502 .FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000011503 CHECK(!try_catch.HasCaught());
11504
11505 CHECK(instance2->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011506 CHECK(instance2->IsFunction());
Ben Murdoch257744e2011-11-30 15:57:28 +000011507
11508 value = CompileRun("new obj5(28)");
11509 CHECK(!try_catch.HasCaught());
11510 CHECK(!value->IsObject());
11511
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011512 Local<Value> args2[] = {v8_num(28)};
11513 value = instance2->CallAsConstructor(context.local(), 1, args2)
11514 .ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011515 CHECK(!try_catch.HasCaught());
11516 CHECK(!value->IsObject());
11517 }
11518}
11519
11520
Steve Blocka7e24c12009-10-30 11:49:00 +000011521THREADED_TEST(FunctionDescriptorException) {
Steve Blocka7e24c12009-10-30 11:49:00 +000011522 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011523 v8::Isolate* isolate = context->GetIsolate();
11524 v8::HandleScope handle_scope(isolate);
11525 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000011526 templ->SetClassName(v8_str("Fun"));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011527 Local<Function> cons = templ->GetFunction(context.local()).ToLocalChecked();
11528 CHECK(
11529 context->Global()->Set(context.local(), v8_str("Fun"), cons).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011530 Local<Value> value = CompileRun(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011531 "function test() {"
11532 " try {"
11533 " (new Fun()).blah()"
11534 " } catch (e) {"
11535 " var str = String(e);"
11536 // " if (str.indexOf('TypeError') == -1) return 1;"
11537 // " if (str.indexOf('[object Fun]') != -1) return 2;"
11538 // " if (str.indexOf('#<Fun>') == -1) return 3;"
11539 " return 0;"
11540 " }"
11541 " return 4;"
11542 "}"
11543 "test();");
11544 CHECK_EQ(0, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011545}
11546
11547
11548THREADED_TEST(EvalAliasedDynamic) {
Steve Blocka7e24c12009-10-30 11:49:00 +000011549 LocalContext current;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011550 v8::HandleScope scope(current->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000011551
11552 // Tests where aliased eval can only be resolved dynamically.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011553 Local<Script> script = v8_compile(
11554 "function f(x) { "
11555 " var foo = 2;"
11556 " with (x) { return eval('foo'); }"
11557 "}"
11558 "foo = 0;"
11559 "result1 = f(new Object());"
11560 "result2 = f(this);"
11561 "var x = new Object();"
11562 "x.eval = function(x) { return 1; };"
11563 "result3 = f(x);");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011564 script->Run(current.local()).ToLocalChecked();
11565 CHECK_EQ(2, current->Global()
11566 ->Get(current.local(), v8_str("result1"))
11567 .ToLocalChecked()
11568 ->Int32Value(current.local())
11569 .FromJust());
11570 CHECK_EQ(0, current->Global()
11571 ->Get(current.local(), v8_str("result2"))
11572 .ToLocalChecked()
11573 ->Int32Value(current.local())
11574 .FromJust());
11575 CHECK_EQ(1, current->Global()
11576 ->Get(current.local(), v8_str("result3"))
11577 .ToLocalChecked()
11578 ->Int32Value(current.local())
11579 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011580
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011581 v8::TryCatch try_catch(current->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011582 script = v8_compile(
11583 "function f(x) { "
11584 " var bar = 2;"
11585 " with (x) { return eval('bar'); }"
11586 "}"
11587 "result4 = f(this)");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011588 script->Run(current.local()).ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011589 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011590 CHECK_EQ(2, current->Global()
11591 ->Get(current.local(), v8_str("result4"))
11592 .ToLocalChecked()
11593 ->Int32Value(current.local())
11594 .FromJust());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011595
Steve Blocka7e24c12009-10-30 11:49:00 +000011596 try_catch.Reset();
11597}
11598
11599
11600THREADED_TEST(CrossEval) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011601 v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000011602 LocalContext other;
11603 LocalContext current;
11604
11605 Local<String> token = v8_str("<security token>");
11606 other->SetSecurityToken(token);
11607 current->SetSecurityToken(token);
11608
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011609 // Set up reference from current to other.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011610 CHECK(current->Global()
11611 ->Set(current.local(), v8_str("other"), other->Global())
11612 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011613
11614 // Check that new variables are introduced in other context.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011615 Local<Script> script = v8_compile("other.eval('var foo = 1234')");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011616 script->Run(current.local()).ToLocalChecked();
11617 Local<Value> foo =
11618 other->Global()->Get(current.local(), v8_str("foo")).ToLocalChecked();
11619 CHECK_EQ(1234, foo->Int32Value(other.local()).FromJust());
11620 CHECK(!current->Global()->Has(current.local(), v8_str("foo")).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011621
11622 // Check that writing to non-existing properties introduces them in
11623 // the other context.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011624 script = v8_compile("other.eval('na = 1234')");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011625 script->Run(current.local()).ToLocalChecked();
11626 CHECK_EQ(1234, other->Global()
11627 ->Get(current.local(), v8_str("na"))
11628 .ToLocalChecked()
11629 ->Int32Value(other.local())
11630 .FromJust());
11631 CHECK(!current->Global()->Has(current.local(), v8_str("na")).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011632
11633 // Check that global variables in current context are not visible in other
11634 // context.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011635 v8::TryCatch try_catch(CcTest::isolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011636 script = v8_compile("var bar = 42; other.eval('bar');");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011637 CHECK(script->Run(current.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +000011638 CHECK(try_catch.HasCaught());
11639 try_catch.Reset();
11640
11641 // Check that local variables in current context are not visible in other
11642 // context.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011643 script = v8_compile(
11644 "(function() { "
11645 " var baz = 87;"
11646 " return other.eval('baz');"
11647 "})();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011648 CHECK(script->Run(current.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +000011649 CHECK(try_catch.HasCaught());
11650 try_catch.Reset();
11651
11652 // Check that global variables in the other environment are visible
11653 // when evaluting code.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011654 CHECK(other->Global()
11655 ->Set(other.local(), v8_str("bis"), v8_num(1234))
11656 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011657 script = v8_compile("other.eval('bis')");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011658 CHECK_EQ(1234, script->Run(current.local())
11659 .ToLocalChecked()
11660 ->Int32Value(current.local())
11661 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011662 CHECK(!try_catch.HasCaught());
11663
11664 // Check that the 'this' pointer points to the global object evaluating
11665 // code.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011666 CHECK(other->Global()
11667 ->Set(current.local(), v8_str("t"), other->Global())
11668 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011669 script = v8_compile("other.eval('this == t')");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011670 Local<Value> result = script->Run(current.local()).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000011671 CHECK(result->IsTrue());
11672 CHECK(!try_catch.HasCaught());
11673
11674 // Check that variables introduced in with-statement are not visible in
11675 // other context.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011676 script = v8_compile("with({x:2}){other.eval('x')}");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011677 CHECK(script->Run(current.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +000011678 CHECK(try_catch.HasCaught());
11679 try_catch.Reset();
11680
11681 // Check that you cannot use 'eval.call' with another object than the
11682 // current global object.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011683 script = v8_compile("other.y = 1; eval.call(other, 'y')");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011684 CHECK(script->Run(current.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +000011685 CHECK(try_catch.HasCaught());
11686}
11687
11688
11689// Test that calling eval in a context which has been detached from
Emily Bernierd0a1eb72015-03-24 16:35:39 -040011690// its global proxy works.
Steve Blocka7e24c12009-10-30 11:49:00 +000011691THREADED_TEST(EvalInDetachedGlobal) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011692 v8::Isolate* isolate = CcTest::isolate();
11693 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000011694
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011695 v8::Local<Context> context0 = Context::New(isolate);
11696 v8::Local<Context> context1 = Context::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000011697
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011698 // Set up function in context0 that uses eval from context0.
Steve Blocka7e24c12009-10-30 11:49:00 +000011699 context0->Enter();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011700 v8::Local<v8::Value> fun = CompileRun(
11701 "var x = 42;"
11702 "(function() {"
11703 " var e = eval;"
11704 " return function(s) { return e(s); }"
11705 "})()");
Steve Blocka7e24c12009-10-30 11:49:00 +000011706 context0->Exit();
11707
11708 // Put the function into context1 and call it before and after
11709 // detaching the global. Before detaching, the call succeeds and
11710 // after detaching and exception is thrown.
11711 context1->Enter();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011712 CHECK(context1->Global()->Set(context1, v8_str("fun"), fun).FromJust());
11713 v8::Local<v8::Value> x_value = CompileRun("fun('x')");
11714 CHECK_EQ(42, x_value->Int32Value(context1).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011715 context0->DetachGlobal();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011716 v8::TryCatch catcher(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000011717 x_value = CompileRun("fun('x')");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011718 CHECK_EQ(42, x_value->Int32Value(context1).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011719 context1->Exit();
Steve Blocka7e24c12009-10-30 11:49:00 +000011720}
11721
11722
11723THREADED_TEST(CrossLazyLoad) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011724 v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000011725 LocalContext other;
11726 LocalContext current;
11727
11728 Local<String> token = v8_str("<security token>");
11729 other->SetSecurityToken(token);
11730 current->SetSecurityToken(token);
11731
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011732 // Set up reference from current to other.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011733 CHECK(current->Global()
11734 ->Set(current.local(), v8_str("other"), other->Global())
11735 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011736
11737 // Trigger lazy loading in other context.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011738 Local<Script> script = v8_compile("other.eval('new Date(42)')");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011739 Local<Value> value = script->Run(current.local()).ToLocalChecked();
11740 CHECK_EQ(42.0, value->NumberValue(current.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011741}
11742
11743
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011744static void call_as_function(const v8::FunctionCallbackInfo<v8::Value>& args) {
Andrei Popescu402d9372010-02-26 13:31:12 +000011745 ApiTestFuzzer::Fuzz();
Steve Blocka7e24c12009-10-30 11:49:00 +000011746 if (args.IsConstructCall()) {
11747 if (args[0]->IsInt32()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011748 args.GetReturnValue().Set(
11749 v8_num(-args[0]
11750 ->Int32Value(args.GetIsolate()->GetCurrentContext())
11751 .FromJust()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011752 return;
Steve Blocka7e24c12009-10-30 11:49:00 +000011753 }
11754 }
11755
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011756 args.GetReturnValue().Set(args[0]);
11757}
11758
11759
11760static void ReturnThis(const v8::FunctionCallbackInfo<v8::Value>& args) {
11761 args.GetReturnValue().Set(args.This());
Steve Blocka7e24c12009-10-30 11:49:00 +000011762}
11763
11764
11765// Test that a call handler can be set for objects which will allow
11766// non-function objects created through the API to be called as
11767// functions.
11768THREADED_TEST(CallAsFunction) {
Steve Blocka7e24c12009-10-30 11:49:00 +000011769 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011770 v8::Isolate* isolate = context->GetIsolate();
11771 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000011772
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011773 {
11774 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011775 Local<ObjectTemplate> instance_template = t->InstanceTemplate();
11776 instance_template->SetCallAsFunctionHandler(call_as_function);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011777 Local<v8::Object> instance = t->GetFunction(context.local())
11778 .ToLocalChecked()
11779 ->NewInstance(context.local())
11780 .ToLocalChecked();
11781 CHECK(context->Global()
11782 ->Set(context.local(), v8_str("obj"), instance)
11783 .FromJust());
11784 v8::TryCatch try_catch(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011785 Local<Value> value;
11786 CHECK(!try_catch.HasCaught());
Steve Blocka7e24c12009-10-30 11:49:00 +000011787
Ben Murdoch257744e2011-11-30 15:57:28 +000011788 value = CompileRun("obj(42)");
11789 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011790 CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011791
Ben Murdoch257744e2011-11-30 15:57:28 +000011792 value = CompileRun("(function(o){return o(49)})(obj)");
11793 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011794 CHECK_EQ(49, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011795
Ben Murdoch257744e2011-11-30 15:57:28 +000011796 // test special case of call as function
11797 value = CompileRun("[obj]['0'](45)");
11798 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011799 CHECK_EQ(45, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011800
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011801 value = CompileRun(
11802 "obj.call = Function.prototype.call;"
11803 "obj.call(null, 87)");
Ben Murdoch257744e2011-11-30 15:57:28 +000011804 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011805 CHECK_EQ(87, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011806
Ben Murdoch257744e2011-11-30 15:57:28 +000011807 // Regression tests for bug #1116356: Calling call through call/apply
11808 // must work for non-function receivers.
11809 const char* apply_99 = "Function.prototype.call.apply(obj, [this, 99])";
11810 value = CompileRun(apply_99);
11811 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011812 CHECK_EQ(99, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011813
Ben Murdoch257744e2011-11-30 15:57:28 +000011814 const char* call_17 = "Function.prototype.call.call(obj, this, 17)";
11815 value = CompileRun(call_17);
11816 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011817 CHECK_EQ(17, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011818
Ben Murdoch257744e2011-11-30 15:57:28 +000011819 // Check that the call-as-function handler can be called through
11820 // new.
11821 value = CompileRun("new obj(43)");
11822 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011823 CHECK_EQ(-43, value->Int32Value(context.local()).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000011824
11825 // Check that the call-as-function handler can be called through
11826 // the API.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011827 v8::Local<Value> args[] = {v8_num(28)};
11828 value = instance->CallAsFunction(context.local(), instance, 1, args)
11829 .ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011830 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011831 CHECK_EQ(28, value->Int32Value(context.local()).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000011832 }
11833
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011834 {
11835 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011836 Local<ObjectTemplate> instance_template(t->InstanceTemplate());
11837 USE(instance_template);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011838 Local<v8::Object> instance = t->GetFunction(context.local())
11839 .ToLocalChecked()
11840 ->NewInstance(context.local())
11841 .ToLocalChecked();
11842 CHECK(context->Global()
11843 ->Set(context.local(), v8_str("obj2"), instance)
11844 .FromJust());
11845 v8::TryCatch try_catch(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011846 Local<Value> value;
11847 CHECK(!try_catch.HasCaught());
11848
11849 // Call an object without call-as-function handler through the JS
11850 value = CompileRun("obj2(28)");
11851 CHECK(value.IsEmpty());
11852 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011853 String::Utf8Value exception_value1(try_catch.Exception());
11854 // TODO(verwaest): Better message
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011855 CHECK_EQ(0, strcmp("TypeError: obj2 is not a function", *exception_value1));
Ben Murdoch257744e2011-11-30 15:57:28 +000011856 try_catch.Reset();
11857
11858 // Call an object without call-as-function handler through the API
11859 value = CompileRun("obj2(28)");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011860 v8::Local<Value> args[] = {v8_num(28)};
11861 CHECK(
11862 instance->CallAsFunction(context.local(), instance, 1, args).IsEmpty());
Ben Murdoch257744e2011-11-30 15:57:28 +000011863 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011864 String::Utf8Value exception_value2(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011865 CHECK_EQ(0,
11866 strcmp("TypeError: object is not a function", *exception_value2));
Ben Murdoch257744e2011-11-30 15:57:28 +000011867 try_catch.Reset();
11868 }
11869
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011870 {
11871 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011872 Local<ObjectTemplate> instance_template = t->InstanceTemplate();
11873 instance_template->SetCallAsFunctionHandler(ThrowValue);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011874 Local<v8::Object> instance = t->GetFunction(context.local())
11875 .ToLocalChecked()
11876 ->NewInstance(context.local())
11877 .ToLocalChecked();
11878 CHECK(context->Global()
11879 ->Set(context.local(), v8_str("obj3"), instance)
11880 .FromJust());
11881 v8::TryCatch try_catch(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011882 Local<Value> value;
11883 CHECK(!try_catch.HasCaught());
11884
11885 // Catch the exception which is thrown by call-as-function handler
11886 value = CompileRun("obj3(22)");
11887 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011888 String::Utf8Value exception_value1(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011889 CHECK_EQ(0, strcmp("22", *exception_value1));
Ben Murdoch257744e2011-11-30 15:57:28 +000011890 try_catch.Reset();
11891
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011892 v8::Local<Value> args[] = {v8_num(23)};
11893 CHECK(
11894 instance->CallAsFunction(context.local(), instance, 1, args).IsEmpty());
Ben Murdoch257744e2011-11-30 15:57:28 +000011895 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011896 String::Utf8Value exception_value2(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011897 CHECK_EQ(0, strcmp("23", *exception_value2));
Ben Murdoch257744e2011-11-30 15:57:28 +000011898 try_catch.Reset();
11899 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011900
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011901 {
11902 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011903 Local<ObjectTemplate> instance_template = t->InstanceTemplate();
11904 instance_template->SetCallAsFunctionHandler(ReturnThis);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011905 Local<v8::Object> instance = t->GetFunction(context.local())
11906 .ToLocalChecked()
11907 ->NewInstance(context.local())
11908 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011909
11910 Local<v8::Value> a1 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011911 instance->CallAsFunction(context.local(), v8::Undefined(isolate), 0,
11912 NULL)
11913 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011914 CHECK(a1->StrictEquals(instance));
11915 Local<v8::Value> a2 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011916 instance->CallAsFunction(context.local(), v8::Null(isolate), 0, NULL)
11917 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011918 CHECK(a2->StrictEquals(instance));
11919 Local<v8::Value> a3 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011920 instance->CallAsFunction(context.local(), v8_num(42), 0, NULL)
11921 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011922 CHECK(a3->StrictEquals(instance));
11923 Local<v8::Value> a4 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011924 instance->CallAsFunction(context.local(), v8_str("hello"), 0, NULL)
11925 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011926 CHECK(a4->StrictEquals(instance));
11927 Local<v8::Value> a5 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011928 instance->CallAsFunction(context.local(), v8::True(isolate), 0, NULL)
11929 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011930 CHECK(a5->StrictEquals(instance));
11931 }
11932
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011933 {
11934 CompileRun(
11935 "function ReturnThisSloppy() {"
11936 " return this;"
11937 "}"
11938 "function ReturnThisStrict() {"
11939 " 'use strict';"
11940 " return this;"
11941 "}");
11942 Local<Function> ReturnThisSloppy = Local<Function>::Cast(
11943 context->Global()
11944 ->Get(context.local(), v8_str("ReturnThisSloppy"))
11945 .ToLocalChecked());
11946 Local<Function> ReturnThisStrict = Local<Function>::Cast(
11947 context->Global()
11948 ->Get(context.local(), v8_str("ReturnThisStrict"))
11949 .ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011950
11951 Local<v8::Value> a1 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011952 ReturnThisSloppy->CallAsFunction(context.local(),
11953 v8::Undefined(isolate), 0, NULL)
11954 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011955 CHECK(a1->StrictEquals(context->Global()));
11956 Local<v8::Value> a2 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011957 ReturnThisSloppy->CallAsFunction(context.local(), v8::Null(isolate), 0,
11958 NULL)
11959 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011960 CHECK(a2->StrictEquals(context->Global()));
11961 Local<v8::Value> a3 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011962 ReturnThisSloppy->CallAsFunction(context.local(), v8_num(42), 0, NULL)
11963 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011964 CHECK(a3->IsNumberObject());
11965 CHECK_EQ(42.0, a3.As<v8::NumberObject>()->ValueOf());
11966 Local<v8::Value> a4 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011967 ReturnThisSloppy->CallAsFunction(context.local(), v8_str("hello"), 0,
11968 NULL)
11969 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011970 CHECK(a4->IsStringObject());
11971 CHECK(a4.As<v8::StringObject>()->ValueOf()->StrictEquals(v8_str("hello")));
11972 Local<v8::Value> a5 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011973 ReturnThisSloppy->CallAsFunction(context.local(), v8::True(isolate), 0,
11974 NULL)
11975 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011976 CHECK(a5->IsBooleanObject());
11977 CHECK(a5.As<v8::BooleanObject>()->ValueOf());
11978
11979 Local<v8::Value> a6 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011980 ReturnThisStrict->CallAsFunction(context.local(),
11981 v8::Undefined(isolate), 0, NULL)
11982 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011983 CHECK(a6->IsUndefined());
11984 Local<v8::Value> a7 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011985 ReturnThisStrict->CallAsFunction(context.local(), v8::Null(isolate), 0,
11986 NULL)
11987 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011988 CHECK(a7->IsNull());
11989 Local<v8::Value> a8 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011990 ReturnThisStrict->CallAsFunction(context.local(), v8_num(42), 0, NULL)
11991 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011992 CHECK(a8->StrictEquals(v8_num(42)));
11993 Local<v8::Value> a9 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011994 ReturnThisStrict->CallAsFunction(context.local(), v8_str("hello"), 0,
11995 NULL)
11996 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011997 CHECK(a9->StrictEquals(v8_str("hello")));
11998 Local<v8::Value> a10 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011999 ReturnThisStrict->CallAsFunction(context.local(), v8::True(isolate), 0,
12000 NULL)
12001 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012002 CHECK(a10->StrictEquals(v8::True(isolate)));
12003 }
Ben Murdoch257744e2011-11-30 15:57:28 +000012004}
12005
12006
12007// Check whether a non-function object is callable.
12008THREADED_TEST(CallableObject) {
Ben Murdoch257744e2011-11-30 15:57:28 +000012009 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012010 v8::Isolate* isolate = context->GetIsolate();
12011 v8::HandleScope scope(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000012012
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012013 {
12014 Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000012015 instance_template->SetCallAsFunctionHandler(call_as_function);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012016 Local<Object> instance =
12017 instance_template->NewInstance(context.local()).ToLocalChecked();
12018 v8::TryCatch try_catch(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000012019
12020 CHECK(instance->IsCallable());
12021 CHECK(!try_catch.HasCaught());
12022 }
12023
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012024 {
12025 Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
12026 Local<Object> instance =
12027 instance_template->NewInstance(context.local()).ToLocalChecked();
12028 v8::TryCatch try_catch(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000012029
12030 CHECK(!instance->IsCallable());
12031 CHECK(!try_catch.HasCaught());
12032 }
12033
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012034 {
12035 Local<FunctionTemplate> function_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012036 FunctionTemplate::New(isolate, call_as_function);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012037 Local<Function> function =
12038 function_template->GetFunction(context.local()).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000012039 Local<Object> instance = function;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012040 v8::TryCatch try_catch(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000012041
12042 CHECK(instance->IsCallable());
12043 CHECK(!try_catch.HasCaught());
12044 }
12045
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012046 {
12047 Local<FunctionTemplate> function_template = FunctionTemplate::New(isolate);
12048 Local<Function> function =
12049 function_template->GetFunction(context.local()).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000012050 Local<Object> instance = function;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012051 v8::TryCatch try_catch(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000012052
12053 CHECK(instance->IsCallable());
12054 CHECK(!try_catch.HasCaught());
12055 }
Steve Blocka7e24c12009-10-30 11:49:00 +000012056}
12057
12058
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012059THREADED_TEST(Regress567998) {
12060 LocalContext env;
12061 v8::HandleScope scope(env->GetIsolate());
12062
12063 Local<v8::FunctionTemplate> desc =
12064 v8::FunctionTemplate::New(env->GetIsolate());
12065 desc->InstanceTemplate()->MarkAsUndetectable(); // undetectable
12066 desc->InstanceTemplate()->SetCallAsFunctionHandler(ReturnThis); // callable
12067
12068 Local<v8::Object> obj = desc->GetFunction(env.local())
12069 .ToLocalChecked()
12070 ->NewInstance(env.local())
12071 .ToLocalChecked();
12072 CHECK(
12073 env->Global()->Set(env.local(), v8_str("undetectable"), obj).FromJust());
12074
12075 ExpectString("undetectable.toString()", "[object Object]");
12076 ExpectString("typeof undetectable", "undefined");
12077 ExpectString("typeof(undetectable)", "undefined");
12078 ExpectBoolean("typeof undetectable == 'undefined'", true);
12079 ExpectBoolean("typeof undetectable == 'object'", false);
12080 ExpectBoolean("if (undetectable) { true; } else { false; }", false);
12081 ExpectBoolean("!undetectable", true);
12082
12083 ExpectObject("true&&undetectable", obj);
12084 ExpectBoolean("false&&undetectable", false);
12085 ExpectBoolean("true||undetectable", true);
12086 ExpectObject("false||undetectable", obj);
12087
12088 ExpectObject("undetectable&&true", obj);
12089 ExpectObject("undetectable&&false", obj);
12090 ExpectBoolean("undetectable||true", true);
12091 ExpectBoolean("undetectable||false", false);
12092
12093 ExpectBoolean("undetectable==null", true);
12094 ExpectBoolean("null==undetectable", true);
12095 ExpectBoolean("undetectable==undefined", true);
12096 ExpectBoolean("undefined==undetectable", true);
12097 ExpectBoolean("undetectable==undetectable", true);
12098
12099 ExpectBoolean("undetectable===null", false);
12100 ExpectBoolean("null===undetectable", false);
12101 ExpectBoolean("undetectable===undefined", false);
12102 ExpectBoolean("undefined===undetectable", false);
12103 ExpectBoolean("undetectable===undetectable", true);
12104}
12105
12106
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012107static int Recurse(v8::Isolate* isolate, int depth, int iterations) {
12108 v8::HandleScope scope(isolate);
12109 if (depth == 0) return v8::HandleScope::NumberOfHandles(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000012110 for (int i = 0; i < iterations; i++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012111 Local<v8::Number> n(v8::Integer::New(isolate, 42));
Steve Blocka7e24c12009-10-30 11:49:00 +000012112 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012113 return Recurse(isolate, depth - 1, iterations);
Steve Blocka7e24c12009-10-30 11:49:00 +000012114}
12115
12116
12117THREADED_TEST(HandleIteration) {
12118 static const int kIterations = 500;
12119 static const int kNesting = 200;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012120 LocalContext context;
12121 v8::Isolate* isolate = context->GetIsolate();
12122 v8::HandleScope scope0(isolate);
12123 CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
Steve Blocka7e24c12009-10-30 11:49:00 +000012124 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012125 v8::HandleScope scope1(isolate);
12126 CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
Steve Blocka7e24c12009-10-30 11:49:00 +000012127 for (int i = 0; i < kIterations; i++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012128 Local<v8::Number> n(v8::Integer::New(CcTest::isolate(), 42));
12129 CHECK_EQ(i + 1, v8::HandleScope::NumberOfHandles(isolate));
Steve Blocka7e24c12009-10-30 11:49:00 +000012130 }
12131
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012132 CHECK_EQ(kIterations, v8::HandleScope::NumberOfHandles(isolate));
Steve Blocka7e24c12009-10-30 11:49:00 +000012133 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012134 v8::HandleScope scope2(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000012135 for (int j = 0; j < kIterations; j++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012136 Local<v8::Number> n(v8::Integer::New(CcTest::isolate(), 42));
12137 CHECK_EQ(j + 1 + kIterations,
12138 v8::HandleScope::NumberOfHandles(isolate));
Steve Blocka7e24c12009-10-30 11:49:00 +000012139 }
12140 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012141 CHECK_EQ(kIterations, v8::HandleScope::NumberOfHandles(isolate));
Steve Blocka7e24c12009-10-30 11:49:00 +000012142 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012143 CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
12144 CHECK_EQ(kNesting * kIterations, Recurse(isolate, kNesting, kIterations));
Steve Blocka7e24c12009-10-30 11:49:00 +000012145}
12146
12147
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012148static void InterceptorCallICFastApi(
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012149 Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
Andrei Popescu402d9372010-02-26 13:31:12 +000012150 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012151 CheckReturnValue(info, FUNCTION_ADDR(InterceptorCallICFastApi));
12152 int* call_count =
12153 reinterpret_cast<int*>(v8::External::Cast(*info.Data())->Value());
Andrei Popescu402d9372010-02-26 13:31:12 +000012154 ++(*call_count);
12155 if ((*call_count) % 20 == 0) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012156 CcTest::heap()->CollectAllGarbage();
Andrei Popescu402d9372010-02-26 13:31:12 +000012157 }
Andrei Popescu402d9372010-02-26 13:31:12 +000012158}
12159
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012160static void FastApiCallback_TrivialSignature(
12161 const v8::FunctionCallbackInfo<v8::Value>& args) {
Andrei Popescu402d9372010-02-26 13:31:12 +000012162 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012163 CheckReturnValue(args, FUNCTION_ADDR(FastApiCallback_TrivialSignature));
12164 v8::Isolate* isolate = CcTest::isolate();
12165 CHECK_EQ(isolate, args.GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012166 CHECK(args.This()
12167 ->Equals(isolate->GetCurrentContext(), args.Holder())
12168 .FromJust());
12169 CHECK(args.Data()
12170 ->Equals(isolate->GetCurrentContext(), v8_str("method_data"))
12171 .FromJust());
12172 args.GetReturnValue().Set(
12173 args[0]->Int32Value(isolate->GetCurrentContext()).FromJust() + 1);
Andrei Popescu402d9372010-02-26 13:31:12 +000012174}
12175
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012176static void FastApiCallback_SimpleSignature(
12177 const v8::FunctionCallbackInfo<v8::Value>& args) {
Andrei Popescu402d9372010-02-26 13:31:12 +000012178 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012179 CheckReturnValue(args, FUNCTION_ADDR(FastApiCallback_SimpleSignature));
12180 v8::Isolate* isolate = CcTest::isolate();
12181 CHECK_EQ(isolate, args.GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012182 CHECK(args.This()
12183 ->GetPrototype()
12184 ->Equals(isolate->GetCurrentContext(), args.Holder())
12185 .FromJust());
12186 CHECK(args.Data()
12187 ->Equals(isolate->GetCurrentContext(), v8_str("method_data"))
12188 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000012189 // Note, we're using HasRealNamedProperty instead of Has to avoid
12190 // invoking the interceptor again.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012191 CHECK(args.Holder()
12192 ->HasRealNamedProperty(isolate->GetCurrentContext(), v8_str("foo"))
12193 .FromJust());
12194 args.GetReturnValue().Set(
12195 args[0]->Int32Value(isolate->GetCurrentContext()).FromJust() + 1);
Andrei Popescu402d9372010-02-26 13:31:12 +000012196}
12197
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012198
Andrei Popescu402d9372010-02-26 13:31:12 +000012199// Helper to maximize the odds of object moving.
12200static void GenerateSomeGarbage() {
12201 CompileRun(
12202 "var garbage;"
12203 "for (var i = 0; i < 1000; i++) {"
12204 " garbage = [1/i, \"garbage\" + i, garbage, {foo: garbage}];"
12205 "}"
12206 "garbage = undefined;");
12207}
12208
Ben Murdoche0cee9b2011-05-25 10:26:03 +010012209
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012210void DirectApiCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Block1e0659c2011-05-24 12:43:12 +010012211 static int count = 0;
12212 if (count++ % 3 == 0) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012213 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012214 // This should move the stub
Steve Block1e0659c2011-05-24 12:43:12 +010012215 GenerateSomeGarbage(); // This should ensure the old stub memory is flushed
12216 }
Steve Block1e0659c2011-05-24 12:43:12 +010012217}
12218
12219
12220THREADED_TEST(CallICFastApi_DirectCall_GCMoveStub) {
Steve Block1e0659c2011-05-24 12:43:12 +010012221 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012222 v8::Isolate* isolate = context->GetIsolate();
12223 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012224 v8::Local<v8::ObjectTemplate> nativeobject_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012225 v8::ObjectTemplate::New(isolate);
12226 nativeobject_templ->Set(isolate, "callback",
12227 v8::FunctionTemplate::New(isolate,
12228 DirectApiCallback));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012229 v8::Local<v8::Object> nativeobject_obj =
12230 nativeobject_templ->NewInstance(context.local()).ToLocalChecked();
12231 CHECK(context->Global()
12232 ->Set(context.local(), v8_str("nativeobject"), nativeobject_obj)
12233 .FromJust());
Steve Block1e0659c2011-05-24 12:43:12 +010012234 // call the api function multiple times to ensure direct call stub creation.
12235 CompileRun(
12236 "function f() {"
12237 " for (var i = 1; i <= 30; i++) {"
12238 " nativeobject.callback();"
12239 " }"
12240 "}"
12241 "f();");
12242}
12243
12244
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012245void ThrowingDirectApiCallback(
12246 const v8::FunctionCallbackInfo<v8::Value>& args) {
12247 args.GetIsolate()->ThrowException(v8_str("g"));
Steve Block1e0659c2011-05-24 12:43:12 +010012248}
12249
12250
12251THREADED_TEST(CallICFastApi_DirectCall_Throw) {
Steve Block1e0659c2011-05-24 12:43:12 +010012252 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012253 v8::Isolate* isolate = context->GetIsolate();
12254 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012255 v8::Local<v8::ObjectTemplate> nativeobject_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012256 v8::ObjectTemplate::New(isolate);
12257 nativeobject_templ->Set(isolate, "callback",
12258 v8::FunctionTemplate::New(isolate,
12259 ThrowingDirectApiCallback));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012260 v8::Local<v8::Object> nativeobject_obj =
12261 nativeobject_templ->NewInstance(context.local()).ToLocalChecked();
12262 CHECK(context->Global()
12263 ->Set(context.local(), v8_str("nativeobject"), nativeobject_obj)
12264 .FromJust());
Steve Block1e0659c2011-05-24 12:43:12 +010012265 // call the api function multiple times to ensure direct call stub creation.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012266 v8::Local<Value> result = CompileRun(
Steve Block1e0659c2011-05-24 12:43:12 +010012267 "var result = '';"
12268 "function f() {"
12269 " for (var i = 1; i <= 5; i++) {"
12270 " try { nativeobject.callback(); } catch (e) { result += e; }"
12271 " }"
12272 "}"
12273 "f(); result;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012274 CHECK(v8_str("ggggg")->Equals(context.local(), result).FromJust());
Steve Block1e0659c2011-05-24 12:43:12 +010012275}
12276
12277
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012278static int p_getter_count_3;
12279
12280
12281static Local<Value> DoDirectGetter() {
12282 if (++p_getter_count_3 % 3 == 0) {
12283 CcTest::heap()->CollectAllGarbage();
Ben Murdoche0cee9b2011-05-25 10:26:03 +010012284 GenerateSomeGarbage();
12285 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012286 return v8_str("Direct Getter Result");
12287}
12288
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012289
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012290static void DirectGetterCallback(
12291 Local<String> name,
12292 const v8::PropertyCallbackInfo<v8::Value>& info) {
12293 CheckReturnValue(info, FUNCTION_ADDR(DirectGetterCallback));
12294 info.GetReturnValue().Set(DoDirectGetter());
Ben Murdoche0cee9b2011-05-25 10:26:03 +010012295}
12296
12297
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012298template<typename Accessor>
12299static void LoadICFastApi_DirectCall_GCMoveStub(Accessor accessor) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +010012300 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012301 v8::Isolate* isolate = context->GetIsolate();
12302 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012303 v8::Local<v8::ObjectTemplate> obj = v8::ObjectTemplate::New(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012304 obj->SetAccessor(v8_str("p1"), accessor);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012305 CHECK(context->Global()
12306 ->Set(context.local(), v8_str("o1"),
12307 obj->NewInstance(context.local()).ToLocalChecked())
12308 .FromJust());
12309 p_getter_count_3 = 0;
12310 v8::Local<v8::Value> result = CompileRun(
Ben Murdoche0cee9b2011-05-25 10:26:03 +010012311 "function f() {"
12312 " for (var i = 0; i < 30; i++) o1.p1;"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012313 " return o1.p1"
Ben Murdoche0cee9b2011-05-25 10:26:03 +010012314 "}"
12315 "f();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012316 CHECK(v8_str("Direct Getter Result")
12317 ->Equals(context.local(), result)
12318 .FromJust());
12319 CHECK_EQ(31, p_getter_count_3);
Ben Murdoche0cee9b2011-05-25 10:26:03 +010012320}
12321
12322
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012323THREADED_PROFILED_TEST(LoadICFastApi_DirectCall_GCMoveStub) {
12324 LoadICFastApi_DirectCall_GCMoveStub(DirectGetterCallback);
12325}
12326
12327
12328void ThrowingDirectGetterCallback(
12329 Local<String> name,
12330 const v8::PropertyCallbackInfo<v8::Value>& info) {
12331 info.GetIsolate()->ThrowException(v8_str("g"));
Ben Murdoche0cee9b2011-05-25 10:26:03 +010012332}
12333
12334
12335THREADED_TEST(LoadICFastApi_DirectCall_Throw) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +010012336 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012337 v8::Isolate* isolate = context->GetIsolate();
12338 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012339 v8::Local<v8::ObjectTemplate> obj = v8::ObjectTemplate::New(isolate);
Ben Murdoche0cee9b2011-05-25 10:26:03 +010012340 obj->SetAccessor(v8_str("p1"), ThrowingDirectGetterCallback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012341 CHECK(context->Global()
12342 ->Set(context.local(), v8_str("o1"),
12343 obj->NewInstance(context.local()).ToLocalChecked())
12344 .FromJust());
12345 v8::Local<Value> result = CompileRun(
Ben Murdoche0cee9b2011-05-25 10:26:03 +010012346 "var result = '';"
12347 "for (var i = 0; i < 5; i++) {"
12348 " try { o1.p1; } catch (e) { result += e; }"
12349 "}"
12350 "result;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012351 CHECK(v8_str("ggggg")->Equals(context.local(), result).FromJust());
Ben Murdoche0cee9b2011-05-25 10:26:03 +010012352}
12353
12354
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012355THREADED_PROFILED_TEST(InterceptorCallICFastApi_TrivialSignature) {
Andrei Popescu402d9372010-02-26 13:31:12 +000012356 int interceptor_call_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012357 v8::Isolate* isolate = CcTest::isolate();
12358 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012359 v8::Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012360 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012361 v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
12362 isolate, FastApiCallback_TrivialSignature, v8_str("method_data"),
12363 v8::Local<v8::Signature>());
12364 v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
Andrei Popescu402d9372010-02-26 13:31:12 +000012365 proto_templ->Set(v8_str("method"), method_templ);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012366 v8::Local<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012367 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012368 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012369 v8::External::New(isolate, &interceptor_call_count)));
Andrei Popescu402d9372010-02-26 13:31:12 +000012370 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012371 v8::Local<v8::Function> fun =
12372 fun_templ->GetFunction(context.local()).ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000012373 GenerateSomeGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012374 CHECK(context->Global()
12375 ->Set(context.local(), v8_str("o"),
12376 fun->NewInstance(context.local()).ToLocalChecked())
12377 .FromJust());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012378 CompileRun(
Andrei Popescu402d9372010-02-26 13:31:12 +000012379 "var result = 0;"
12380 "for (var i = 0; i < 100; i++) {"
12381 " result = o.method(41);"
Ben Murdochc7cc0282012-03-05 14:35:55 +000012382 "}");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012383 CHECK_EQ(42, context->Global()
12384 ->Get(context.local(), v8_str("result"))
12385 .ToLocalChecked()
12386 ->Int32Value(context.local())
12387 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000012388 CHECK_EQ(100, interceptor_call_count);
12389}
12390
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012391
12392THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature) {
Andrei Popescu402d9372010-02-26 13:31:12 +000012393 int interceptor_call_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012394 v8::Isolate* isolate = CcTest::isolate();
12395 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012396 v8::Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012397 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012398 v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012399 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12400 v8::Signature::New(isolate, fun_templ));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012401 v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
Andrei Popescu402d9372010-02-26 13:31:12 +000012402 proto_templ->Set(v8_str("method"), method_templ);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012403 fun_templ->SetHiddenPrototype(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012404 v8::Local<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012405 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012406 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012407 v8::External::New(isolate, &interceptor_call_count)));
Andrei Popescu402d9372010-02-26 13:31:12 +000012408 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012409 v8::Local<v8::Function> fun =
12410 fun_templ->GetFunction(context.local()).ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000012411 GenerateSomeGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012412 CHECK(context->Global()
12413 ->Set(context.local(), v8_str("o"),
12414 fun->NewInstance(context.local()).ToLocalChecked())
12415 .FromJust());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012416 CompileRun(
Andrei Popescu402d9372010-02-26 13:31:12 +000012417 "o.foo = 17;"
12418 "var receiver = {};"
12419 "receiver.__proto__ = o;"
12420 "var result = 0;"
12421 "for (var i = 0; i < 100; i++) {"
12422 " result = receiver.method(41);"
Ben Murdochc7cc0282012-03-05 14:35:55 +000012423 "}");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012424 CHECK_EQ(42, context->Global()
12425 ->Get(context.local(), v8_str("result"))
12426 .ToLocalChecked()
12427 ->Int32Value(context.local())
12428 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000012429 CHECK_EQ(100, interceptor_call_count);
12430}
12431
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012432
12433THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss1) {
Andrei Popescu402d9372010-02-26 13:31:12 +000012434 int interceptor_call_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012435 v8::Isolate* isolate = CcTest::isolate();
12436 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012437 v8::Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012438 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012439 v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012440 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12441 v8::Signature::New(isolate, fun_templ));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012442 v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
Andrei Popescu402d9372010-02-26 13:31:12 +000012443 proto_templ->Set(v8_str("method"), method_templ);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012444 fun_templ->SetHiddenPrototype(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012445 v8::Local<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012446 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012447 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012448 v8::External::New(isolate, &interceptor_call_count)));
Andrei Popescu402d9372010-02-26 13:31:12 +000012449 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012450 v8::Local<v8::Function> fun =
12451 fun_templ->GetFunction(context.local()).ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000012452 GenerateSomeGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012453 CHECK(context->Global()
12454 ->Set(context.local(), v8_str("o"),
12455 fun->NewInstance(context.local()).ToLocalChecked())
12456 .FromJust());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012457 CompileRun(
Andrei Popescu402d9372010-02-26 13:31:12 +000012458 "o.foo = 17;"
12459 "var receiver = {};"
12460 "receiver.__proto__ = o;"
12461 "var result = 0;"
12462 "var saved_result = 0;"
12463 "for (var i = 0; i < 100; i++) {"
12464 " result = receiver.method(41);"
12465 " if (i == 50) {"
12466 " saved_result = result;"
12467 " receiver = {method: function(x) { return x - 1 }};"
12468 " }"
Ben Murdochc7cc0282012-03-05 14:35:55 +000012469 "}");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012470 CHECK_EQ(40, context->Global()
12471 ->Get(context.local(), v8_str("result"))
12472 .ToLocalChecked()
12473 ->Int32Value(context.local())
12474 .FromJust());
12475 CHECK_EQ(42, context->Global()
12476 ->Get(context.local(), v8_str("saved_result"))
12477 .ToLocalChecked()
12478 ->Int32Value(context.local())
12479 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000012480 CHECK_GE(interceptor_call_count, 50);
12481}
12482
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012483
12484THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss2) {
Andrei Popescu402d9372010-02-26 13:31:12 +000012485 int interceptor_call_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012486 v8::Isolate* isolate = CcTest::isolate();
12487 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012488 v8::Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012489 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012490 v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012491 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12492 v8::Signature::New(isolate, fun_templ));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012493 v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
Andrei Popescu402d9372010-02-26 13:31:12 +000012494 proto_templ->Set(v8_str("method"), method_templ);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012495 fun_templ->SetHiddenPrototype(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012496 v8::Local<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012497 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012498 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012499 v8::External::New(isolate, &interceptor_call_count)));
Andrei Popescu402d9372010-02-26 13:31:12 +000012500 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012501 v8::Local<v8::Function> fun =
12502 fun_templ->GetFunction(context.local()).ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000012503 GenerateSomeGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012504 CHECK(context->Global()
12505 ->Set(context.local(), v8_str("o"),
12506 fun->NewInstance(context.local()).ToLocalChecked())
12507 .FromJust());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012508 CompileRun(
Andrei Popescu402d9372010-02-26 13:31:12 +000012509 "o.foo = 17;"
12510 "var receiver = {};"
12511 "receiver.__proto__ = o;"
12512 "var result = 0;"
12513 "var saved_result = 0;"
12514 "for (var i = 0; i < 100; i++) {"
12515 " result = receiver.method(41);"
12516 " if (i == 50) {"
12517 " saved_result = result;"
12518 " o.method = function(x) { return x - 1 };"
12519 " }"
Ben Murdochc7cc0282012-03-05 14:35:55 +000012520 "}");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012521 CHECK_EQ(40, context->Global()
12522 ->Get(context.local(), v8_str("result"))
12523 .ToLocalChecked()
12524 ->Int32Value(context.local())
12525 .FromJust());
12526 CHECK_EQ(42, context->Global()
12527 ->Get(context.local(), v8_str("saved_result"))
12528 .ToLocalChecked()
12529 ->Int32Value(context.local())
12530 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000012531 CHECK_GE(interceptor_call_count, 50);
12532}
12533
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012534
12535THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss3) {
Steve Block6ded16b2010-05-10 14:33:55 +010012536 int interceptor_call_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012537 v8::Isolate* isolate = CcTest::isolate();
12538 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012539 v8::Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012540 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012541 v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012542 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12543 v8::Signature::New(isolate, fun_templ));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012544 v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
Steve Block6ded16b2010-05-10 14:33:55 +010012545 proto_templ->Set(v8_str("method"), method_templ);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012546 fun_templ->SetHiddenPrototype(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012547 v8::Local<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012548 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012549 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012550 v8::External::New(isolate, &interceptor_call_count)));
Steve Block6ded16b2010-05-10 14:33:55 +010012551 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012552 v8::Local<v8::Function> fun =
12553 fun_templ->GetFunction(context.local()).ToLocalChecked();
Steve Block6ded16b2010-05-10 14:33:55 +010012554 GenerateSomeGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012555 CHECK(context->Global()
12556 ->Set(context.local(), v8_str("o"),
12557 fun->NewInstance(context.local()).ToLocalChecked())
12558 .FromJust());
12559 v8::TryCatch try_catch(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012560 CompileRun(
Steve Block6ded16b2010-05-10 14:33:55 +010012561 "o.foo = 17;"
12562 "var receiver = {};"
12563 "receiver.__proto__ = o;"
12564 "var result = 0;"
12565 "var saved_result = 0;"
12566 "for (var i = 0; i < 100; i++) {"
12567 " result = receiver.method(41);"
12568 " if (i == 50) {"
12569 " saved_result = result;"
12570 " receiver = 333;"
12571 " }"
Ben Murdochc7cc0282012-03-05 14:35:55 +000012572 "}");
Steve Block6ded16b2010-05-10 14:33:55 +010012573 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012574 // TODO(verwaest): Adjust message.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012575 CHECK(
12576 v8_str("TypeError: receiver.method is not a function")
12577 ->Equals(
12578 context.local(),
12579 try_catch.Exception()->ToString(context.local()).ToLocalChecked())
12580 .FromJust());
12581 CHECK_EQ(42, context->Global()
12582 ->Get(context.local(), v8_str("saved_result"))
12583 .ToLocalChecked()
12584 ->Int32Value(context.local())
12585 .FromJust());
Steve Block6ded16b2010-05-10 14:33:55 +010012586 CHECK_GE(interceptor_call_count, 50);
12587}
12588
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012589
12590THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_TypeError) {
Andrei Popescu402d9372010-02-26 13:31:12 +000012591 int interceptor_call_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012592 v8::Isolate* isolate = CcTest::isolate();
12593 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012594 v8::Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012595 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012596 v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012597 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12598 v8::Signature::New(isolate, fun_templ));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012599 v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
Andrei Popescu402d9372010-02-26 13:31:12 +000012600 proto_templ->Set(v8_str("method"), method_templ);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012601 fun_templ->SetHiddenPrototype(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012602 v8::Local<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012603 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012604 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012605 v8::External::New(isolate, &interceptor_call_count)));
Andrei Popescu402d9372010-02-26 13:31:12 +000012606 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012607 v8::Local<v8::Function> fun =
12608 fun_templ->GetFunction(context.local()).ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000012609 GenerateSomeGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012610 CHECK(context->Global()
12611 ->Set(context.local(), v8_str("o"),
12612 fun->NewInstance(context.local()).ToLocalChecked())
12613 .FromJust());
12614 v8::TryCatch try_catch(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012615 CompileRun(
Andrei Popescu402d9372010-02-26 13:31:12 +000012616 "o.foo = 17;"
12617 "var receiver = {};"
12618 "receiver.__proto__ = o;"
12619 "var result = 0;"
12620 "var saved_result = 0;"
12621 "for (var i = 0; i < 100; i++) {"
12622 " result = receiver.method(41);"
12623 " if (i == 50) {"
12624 " saved_result = result;"
12625 " receiver = {method: receiver.method};"
12626 " }"
Ben Murdochc7cc0282012-03-05 14:35:55 +000012627 "}");
Andrei Popescu402d9372010-02-26 13:31:12 +000012628 CHECK(try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012629 CHECK(
12630 v8_str("TypeError: Illegal invocation")
12631 ->Equals(
12632 context.local(),
12633 try_catch.Exception()->ToString(context.local()).ToLocalChecked())
12634 .FromJust());
12635 CHECK_EQ(42, context->Global()
12636 ->Get(context.local(), v8_str("saved_result"))
12637 .ToLocalChecked()
12638 ->Int32Value(context.local())
12639 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000012640 CHECK_GE(interceptor_call_count, 50);
12641}
12642
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012643
12644THREADED_PROFILED_TEST(CallICFastApi_TrivialSignature) {
12645 v8::Isolate* isolate = CcTest::isolate();
12646 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012647 v8::Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012648 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012649 v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
12650 isolate, FastApiCallback_TrivialSignature, v8_str("method_data"),
12651 v8::Local<v8::Signature>());
12652 v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
Andrei Popescu402d9372010-02-26 13:31:12 +000012653 proto_templ->Set(v8_str("method"), method_templ);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012654 v8::Local<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012655 USE(templ);
Andrei Popescu402d9372010-02-26 13:31:12 +000012656 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012657 v8::Local<v8::Function> fun =
12658 fun_templ->GetFunction(context.local()).ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000012659 GenerateSomeGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012660 CHECK(context->Global()
12661 ->Set(context.local(), v8_str("o"),
12662 fun->NewInstance(context.local()).ToLocalChecked())
12663 .FromJust());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012664 CompileRun(
Andrei Popescu402d9372010-02-26 13:31:12 +000012665 "var result = 0;"
12666 "for (var i = 0; i < 100; i++) {"
12667 " result = o.method(41);"
Ben Murdochc7cc0282012-03-05 14:35:55 +000012668 "}");
Andrei Popescu402d9372010-02-26 13:31:12 +000012669
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012670 CHECK_EQ(42, context->Global()
12671 ->Get(context.local(), v8_str("result"))
12672 .ToLocalChecked()
12673 ->Int32Value(context.local())
12674 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000012675}
12676
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012677
12678THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature) {
12679 v8::Isolate* isolate = CcTest::isolate();
12680 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012681 v8::Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012682 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012683 v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012684 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12685 v8::Signature::New(isolate, fun_templ));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012686 v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
Andrei Popescu402d9372010-02-26 13:31:12 +000012687 proto_templ->Set(v8_str("method"), method_templ);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012688 fun_templ->SetHiddenPrototype(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012689 v8::Local<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012690 CHECK(!templ.IsEmpty());
Andrei Popescu402d9372010-02-26 13:31:12 +000012691 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012692 v8::Local<v8::Function> fun =
12693 fun_templ->GetFunction(context.local()).ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000012694 GenerateSomeGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012695 CHECK(context->Global()
12696 ->Set(context.local(), v8_str("o"),
12697 fun->NewInstance(context.local()).ToLocalChecked())
12698 .FromJust());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012699 CompileRun(
Andrei Popescu402d9372010-02-26 13:31:12 +000012700 "o.foo = 17;"
12701 "var receiver = {};"
12702 "receiver.__proto__ = o;"
12703 "var result = 0;"
12704 "for (var i = 0; i < 100; i++) {"
12705 " result = receiver.method(41);"
Ben Murdochc7cc0282012-03-05 14:35:55 +000012706 "}");
Andrei Popescu402d9372010-02-26 13:31:12 +000012707
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012708 CHECK_EQ(42, context->Global()
12709 ->Get(context.local(), v8_str("result"))
12710 .ToLocalChecked()
12711 ->Int32Value(context.local())
12712 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000012713}
12714
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012715
12716THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_Miss1) {
12717 v8::Isolate* isolate = CcTest::isolate();
12718 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012719 v8::Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012720 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012721 v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012722 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12723 v8::Signature::New(isolate, fun_templ));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012724 v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
Andrei Popescu402d9372010-02-26 13:31:12 +000012725 proto_templ->Set(v8_str("method"), method_templ);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012726 fun_templ->SetHiddenPrototype(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012727 v8::Local<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012728 CHECK(!templ.IsEmpty());
Andrei Popescu402d9372010-02-26 13:31:12 +000012729 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012730 v8::Local<v8::Function> fun =
12731 fun_templ->GetFunction(context.local()).ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000012732 GenerateSomeGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012733 CHECK(context->Global()
12734 ->Set(context.local(), v8_str("o"),
12735 fun->NewInstance(context.local()).ToLocalChecked())
12736 .FromJust());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012737 CompileRun(
Andrei Popescu402d9372010-02-26 13:31:12 +000012738 "o.foo = 17;"
12739 "var receiver = {};"
12740 "receiver.__proto__ = o;"
12741 "var result = 0;"
12742 "var saved_result = 0;"
12743 "for (var i = 0; i < 100; i++) {"
12744 " result = receiver.method(41);"
12745 " if (i == 50) {"
12746 " saved_result = result;"
12747 " receiver = {method: function(x) { return x - 1 }};"
12748 " }"
Ben Murdochc7cc0282012-03-05 14:35:55 +000012749 "}");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012750 CHECK_EQ(40, context->Global()
12751 ->Get(context.local(), v8_str("result"))
12752 .ToLocalChecked()
12753 ->Int32Value(context.local())
12754 .FromJust());
12755 CHECK_EQ(42, context->Global()
12756 ->Get(context.local(), v8_str("saved_result"))
12757 .ToLocalChecked()
12758 ->Int32Value(context.local())
12759 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000012760}
12761
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012762
12763THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_Miss2) {
12764 v8::Isolate* isolate = CcTest::isolate();
12765 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012766 v8::Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012767 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012768 v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012769 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12770 v8::Signature::New(isolate, fun_templ));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012771 v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
Steve Block6ded16b2010-05-10 14:33:55 +010012772 proto_templ->Set(v8_str("method"), method_templ);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012773 fun_templ->SetHiddenPrototype(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012774 v8::Local<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012775 CHECK(!templ.IsEmpty());
Steve Block6ded16b2010-05-10 14:33:55 +010012776 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012777 v8::Local<v8::Function> fun =
12778 fun_templ->GetFunction(context.local()).ToLocalChecked();
Steve Block6ded16b2010-05-10 14:33:55 +010012779 GenerateSomeGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012780 CHECK(context->Global()
12781 ->Set(context.local(), v8_str("o"),
12782 fun->NewInstance(context.local()).ToLocalChecked())
12783 .FromJust());
12784 v8::TryCatch try_catch(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012785 CompileRun(
Steve Block6ded16b2010-05-10 14:33:55 +010012786 "o.foo = 17;"
12787 "var receiver = {};"
12788 "receiver.__proto__ = o;"
12789 "var result = 0;"
12790 "var saved_result = 0;"
12791 "for (var i = 0; i < 100; i++) {"
12792 " result = receiver.method(41);"
12793 " if (i == 50) {"
12794 " saved_result = result;"
12795 " receiver = 333;"
12796 " }"
Ben Murdochc7cc0282012-03-05 14:35:55 +000012797 "}");
Steve Block6ded16b2010-05-10 14:33:55 +010012798 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012799 // TODO(verwaest): Adjust message.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012800 CHECK(
12801 v8_str("TypeError: receiver.method is not a function")
12802 ->Equals(
12803 context.local(),
12804 try_catch.Exception()->ToString(context.local()).ToLocalChecked())
12805 .FromJust());
12806 CHECK_EQ(42, context->Global()
12807 ->Get(context.local(), v8_str("saved_result"))
12808 .ToLocalChecked()
12809 ->Int32Value(context.local())
12810 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012811}
12812
12813
12814THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_TypeError) {
12815 v8::Isolate* isolate = CcTest::isolate();
12816 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012817 v8::Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012818 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012819 v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012820 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12821 v8::Signature::New(isolate, fun_templ));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012822 v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012823 proto_templ->Set(v8_str("method"), method_templ);
12824 fun_templ->SetHiddenPrototype(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012825 v8::Local<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012826 CHECK(!templ.IsEmpty());
12827 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012828 v8::Local<v8::Function> fun =
12829 fun_templ->GetFunction(context.local()).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012830 GenerateSomeGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012831 CHECK(context->Global()
12832 ->Set(context.local(), v8_str("o"),
12833 fun->NewInstance(context.local()).ToLocalChecked())
12834 .FromJust());
12835 v8::TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012836 CompileRun(
12837 "o.foo = 17;"
12838 "var receiver = {};"
12839 "receiver.__proto__ = o;"
12840 "var result = 0;"
12841 "var saved_result = 0;"
12842 "for (var i = 0; i < 100; i++) {"
12843 " result = receiver.method(41);"
12844 " if (i == 50) {"
12845 " saved_result = result;"
12846 " receiver = Object.create(receiver);"
12847 " }"
12848 "}");
12849 CHECK(try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012850 CHECK(
12851 v8_str("TypeError: Illegal invocation")
12852 ->Equals(
12853 context.local(),
12854 try_catch.Exception()->ToString(context.local()).ToLocalChecked())
12855 .FromJust());
12856 CHECK_EQ(42, context->Global()
12857 ->Get(context.local(), v8_str("saved_result"))
12858 .ToLocalChecked()
12859 ->Int32Value(context.local())
12860 .FromJust());
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +010012861}
12862
12863
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012864static void ThrowingGetter(Local<String> name,
12865 const v8::PropertyCallbackInfo<v8::Value>& info) {
Ben Murdoch8b112d22011-06-08 16:22:53 +010012866 ApiTestFuzzer::Fuzz();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012867 info.GetIsolate()->ThrowException(Local<Value>());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012868 info.GetReturnValue().SetUndefined();
Ben Murdoch8b112d22011-06-08 16:22:53 +010012869}
12870
12871
12872THREADED_TEST(VariousGetPropertiesAndThrowingCallbacks) {
Ben Murdoch8b112d22011-06-08 16:22:53 +010012873 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012874 HandleScope scope(context->GetIsolate());
Ben Murdoch8b112d22011-06-08 16:22:53 +010012875
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012876 Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
Ben Murdoch8b112d22011-06-08 16:22:53 +010012877 Local<ObjectTemplate> instance_templ = templ->InstanceTemplate();
12878 instance_templ->SetAccessor(v8_str("f"), ThrowingGetter);
12879
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012880 Local<Object> instance = templ->GetFunction(context.local())
12881 .ToLocalChecked()
12882 ->NewInstance(context.local())
12883 .ToLocalChecked();
Ben Murdoch8b112d22011-06-08 16:22:53 +010012884
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012885 Local<Object> another = Object::New(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012886 CHECK(another->SetPrototype(context.local(), instance).FromJust());
Ben Murdoch8b112d22011-06-08 16:22:53 +010012887
12888 Local<Object> with_js_getter = CompileRun(
12889 "o = {};\n"
12890 "o.__defineGetter__('f', function() { throw undefined; });\n"
12891 "o\n").As<Object>();
12892 CHECK(!with_js_getter.IsEmpty());
12893
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012894 TryCatch try_catch(context->GetIsolate());
Ben Murdoch8b112d22011-06-08 16:22:53 +010012895
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012896 v8::MaybeLocal<Value> result =
12897 instance->GetRealNamedProperty(context.local(), v8_str("f"));
Ben Murdoch8b112d22011-06-08 16:22:53 +010012898 CHECK(try_catch.HasCaught());
12899 try_catch.Reset();
12900 CHECK(result.IsEmpty());
12901
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012902 Maybe<PropertyAttribute> attr =
12903 instance->GetRealNamedPropertyAttributes(context.local(), v8_str("f"));
12904 CHECK(!try_catch.HasCaught());
12905 CHECK(Just(None) == attr);
12906
12907 result = another->GetRealNamedProperty(context.local(), v8_str("f"));
Ben Murdoch8b112d22011-06-08 16:22:53 +010012908 CHECK(try_catch.HasCaught());
12909 try_catch.Reset();
12910 CHECK(result.IsEmpty());
12911
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012912 attr = another->GetRealNamedPropertyAttributes(context.local(), v8_str("f"));
12913 CHECK(!try_catch.HasCaught());
12914 CHECK(Just(None) == attr);
12915
12916 result = another->GetRealNamedPropertyInPrototypeChain(context.local(),
12917 v8_str("f"));
Ben Murdoch8b112d22011-06-08 16:22:53 +010012918 CHECK(try_catch.HasCaught());
12919 try_catch.Reset();
12920 CHECK(result.IsEmpty());
12921
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012922 attr = another->GetRealNamedPropertyAttributesInPrototypeChain(
12923 context.local(), v8_str("f"));
12924 CHECK(!try_catch.HasCaught());
12925 CHECK(Just(None) == attr);
12926
12927 result = another->Get(context.local(), v8_str("f"));
Ben Murdoch8b112d22011-06-08 16:22:53 +010012928 CHECK(try_catch.HasCaught());
12929 try_catch.Reset();
12930 CHECK(result.IsEmpty());
12931
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012932 result = with_js_getter->GetRealNamedProperty(context.local(), v8_str("f"));
Ben Murdoch8b112d22011-06-08 16:22:53 +010012933 CHECK(try_catch.HasCaught());
12934 try_catch.Reset();
12935 CHECK(result.IsEmpty());
12936
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012937 attr = with_js_getter->GetRealNamedPropertyAttributes(context.local(),
12938 v8_str("f"));
12939 CHECK(!try_catch.HasCaught());
12940 CHECK(Just(None) == attr);
12941
12942 result = with_js_getter->Get(context.local(), v8_str("f"));
Ben Murdoch8b112d22011-06-08 16:22:53 +010012943 CHECK(try_catch.HasCaught());
12944 try_catch.Reset();
12945 CHECK(result.IsEmpty());
Ben Murdochda12d292016-06-02 14:46:10 +010012946
12947 Local<Object> target = CompileRun("({})").As<Object>();
12948 Local<Object> handler = CompileRun("({})").As<Object>();
12949 Local<v8::Proxy> proxy =
12950 v8::Proxy::New(context.local(), target, handler).ToLocalChecked();
12951
12952 result = target->GetRealNamedProperty(context.local(), v8_str("f"));
12953 CHECK(!try_catch.HasCaught());
12954 CHECK(result.IsEmpty());
12955
12956 result = proxy->GetRealNamedProperty(context.local(), v8_str("f"));
12957 CHECK(!try_catch.HasCaught());
12958 CHECK(result.IsEmpty());
Ben Murdoch8b112d22011-06-08 16:22:53 +010012959}
12960
12961
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012962static void ThrowingCallbackWithTryCatch(
12963 const v8::FunctionCallbackInfo<v8::Value>& args) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012964 TryCatch try_catch(args.GetIsolate());
Ben Murdoch8b112d22011-06-08 16:22:53 +010012965 // Verboseness is important: it triggers message delivery which can call into
12966 // external code.
12967 try_catch.SetVerbose(true);
12968 CompileRun("throw 'from JS';");
12969 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012970 CHECK(!CcTest::i_isolate()->has_pending_exception());
12971 CHECK(!CcTest::i_isolate()->has_scheduled_exception());
Ben Murdoch8b112d22011-06-08 16:22:53 +010012972}
12973
12974
12975static int call_depth;
12976
12977
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012978static void WithTryCatch(Local<Message> message, Local<Value> data) {
12979 TryCatch try_catch(CcTest::isolate());
Ben Murdoch8b112d22011-06-08 16:22:53 +010012980}
12981
12982
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012983static void ThrowFromJS(Local<Message> message, Local<Value> data) {
Ben Murdoch8b112d22011-06-08 16:22:53 +010012984 if (--call_depth) CompileRun("throw 'ThrowInJS';");
12985}
12986
12987
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012988static void ThrowViaApi(Local<Message> message, Local<Value> data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012989 if (--call_depth) CcTest::isolate()->ThrowException(v8_str("ThrowViaApi"));
Ben Murdoch8b112d22011-06-08 16:22:53 +010012990}
12991
12992
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012993static void WebKitLike(Local<Message> message, Local<Value> data) {
12994 Local<String> errorMessageString = message->Get();
Ben Murdoch8b112d22011-06-08 16:22:53 +010012995 CHECK(!errorMessageString.IsEmpty());
12996 message->GetStackTrace();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012997 message->GetScriptOrigin().ResourceName();
Ben Murdoch8b112d22011-06-08 16:22:53 +010012998}
12999
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013000
Ben Murdoch8b112d22011-06-08 16:22:53 +010013001THREADED_TEST(ExceptionsDoNotPropagatePastTryCatch) {
Ben Murdoch8b112d22011-06-08 16:22:53 +010013002 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013003 v8::Isolate* isolate = context->GetIsolate();
13004 HandleScope scope(isolate);
Ben Murdoch8b112d22011-06-08 16:22:53 +010013005
13006 Local<Function> func =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013007 FunctionTemplate::New(isolate, ThrowingCallbackWithTryCatch)
13008 ->GetFunction(context.local())
13009 .ToLocalChecked();
13010 CHECK(
13011 context->Global()->Set(context.local(), v8_str("func"), func).FromJust());
Ben Murdoch8b112d22011-06-08 16:22:53 +010013012
13013 MessageCallback callbacks[] =
13014 { NULL, WebKitLike, ThrowViaApi, ThrowFromJS, WithTryCatch };
13015 for (unsigned i = 0; i < sizeof(callbacks)/sizeof(callbacks[0]); i++) {
13016 MessageCallback callback = callbacks[i];
13017 if (callback != NULL) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013018 isolate->AddMessageListener(callback);
Ben Murdoch8b112d22011-06-08 16:22:53 +010013019 }
Ben Murdoch257744e2011-11-30 15:57:28 +000013020 // Some small number to control number of times message handler should
13021 // throw an exception.
Ben Murdoch8b112d22011-06-08 16:22:53 +010013022 call_depth = 5;
13023 ExpectFalse(
13024 "var thrown = false;\n"
13025 "try { func(); } catch(e) { thrown = true; }\n"
13026 "thrown\n");
13027 if (callback != NULL) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013028 isolate->RemoveMessageListeners(callback);
Ben Murdoch8b112d22011-06-08 16:22:53 +010013029 }
13030 }
13031}
13032
13033
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013034static void ParentGetter(Local<String> name,
13035 const v8::PropertyCallbackInfo<v8::Value>& info) {
Steve Blocka7e24c12009-10-30 11:49:00 +000013036 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013037 info.GetReturnValue().Set(v8_num(1));
Steve Blocka7e24c12009-10-30 11:49:00 +000013038}
13039
13040
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013041static void ChildGetter(Local<String> name,
13042 const v8::PropertyCallbackInfo<v8::Value>& info) {
Steve Blocka7e24c12009-10-30 11:49:00 +000013043 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013044 info.GetReturnValue().Set(v8_num(42));
Steve Blocka7e24c12009-10-30 11:49:00 +000013045}
13046
13047
13048THREADED_TEST(Overriding) {
Steve Blocka7e24c12009-10-30 11:49:00 +000013049 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013050 v8::Isolate* isolate = context->GetIsolate();
13051 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000013052
13053 // Parent template.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013054 Local<v8::FunctionTemplate> parent_templ = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000013055 Local<ObjectTemplate> parent_instance_templ =
13056 parent_templ->InstanceTemplate();
13057 parent_instance_templ->SetAccessor(v8_str("f"), ParentGetter);
13058
13059 // Template that inherits from the parent template.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013060 Local<v8::FunctionTemplate> child_templ = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000013061 Local<ObjectTemplate> child_instance_templ =
13062 child_templ->InstanceTemplate();
13063 child_templ->Inherit(parent_templ);
13064 // Override 'f'. The child version of 'f' should get called for child
13065 // instances.
13066 child_instance_templ->SetAccessor(v8_str("f"), ChildGetter);
13067 // Add 'g' twice. The 'g' added last should get called for instances.
13068 child_instance_templ->SetAccessor(v8_str("g"), ParentGetter);
13069 child_instance_templ->SetAccessor(v8_str("g"), ChildGetter);
13070
13071 // Add 'h' as an accessor to the proto template with ReadOnly attributes
13072 // so 'h' can be shadowed on the instance object.
13073 Local<ObjectTemplate> child_proto_templ = child_templ->PrototypeTemplate();
13074 child_proto_templ->SetAccessor(v8_str("h"), ParentGetter, 0,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013075 v8::Local<Value>(), v8::DEFAULT, v8::ReadOnly);
Steve Blocka7e24c12009-10-30 11:49:00 +000013076
13077 // Add 'i' as an accessor to the instance template with ReadOnly attributes
13078 // but the attribute does not have effect because it is duplicated with
13079 // NULL setter.
13080 child_instance_templ->SetAccessor(v8_str("i"), ChildGetter, 0,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013081 v8::Local<Value>(), v8::DEFAULT,
13082 v8::ReadOnly);
Steve Blocka7e24c12009-10-30 11:49:00 +000013083
13084
13085 // Instantiate the child template.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013086 Local<v8::Object> instance = child_templ->GetFunction(context.local())
13087 .ToLocalChecked()
13088 ->NewInstance(context.local())
13089 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000013090
13091 // Check that the child function overrides the parent one.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013092 CHECK(context->Global()
13093 ->Set(context.local(), v8_str("o"), instance)
13094 .FromJust());
13095 Local<Value> value = v8_compile("o.f")->Run(context.local()).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000013096 // Check that the 'g' that was added last is hit.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013097 CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
13098 value = v8_compile("o.g")->Run(context.local()).ToLocalChecked();
13099 CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013100
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013101 // Check that 'h' cannot be shadowed.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013102 value = v8_compile("o.h = 3; o.h")->Run(context.local()).ToLocalChecked();
13103 CHECK_EQ(1, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013104
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013105 // Check that 'i' cannot be shadowed or changed.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013106 value = v8_compile("o.i = 3; o.i")->Run(context.local()).ToLocalChecked();
13107 CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013108}
13109
13110
Ben Murdoch097c5b22016-05-18 11:27:45 +010013111static void ShouldThrowOnErrorGetter(
13112 Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
13113 ApiTestFuzzer::Fuzz();
13114 v8::Isolate* isolate = info.GetIsolate();
13115 Local<Boolean> should_throw_on_error =
13116 Boolean::New(isolate, info.ShouldThrowOnError());
13117 info.GetReturnValue().Set(should_throw_on_error);
13118}
13119
13120
13121template <typename T>
13122static void ShouldThrowOnErrorSetter(Local<Name> name, Local<v8::Value> value,
13123 const v8::PropertyCallbackInfo<T>& info) {
13124 ApiTestFuzzer::Fuzz();
13125 v8::Isolate* isolate = info.GetIsolate();
13126 auto context = isolate->GetCurrentContext();
13127 Local<Boolean> should_throw_on_error_value =
13128 Boolean::New(isolate, info.ShouldThrowOnError());
13129 CHECK(context->Global()
13130 ->Set(isolate->GetCurrentContext(), v8_str("should_throw_setter"),
13131 should_throw_on_error_value)
13132 .FromJust());
13133}
13134
13135
13136THREADED_TEST(AccessorShouldThrowOnError) {
Ben Murdoch097c5b22016-05-18 11:27:45 +010013137 LocalContext context;
13138 v8::Isolate* isolate = context->GetIsolate();
13139 v8::HandleScope scope(isolate);
13140 Local<Object> global = context->Global();
13141
13142 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
13143 Local<ObjectTemplate> instance_templ = templ->InstanceTemplate();
13144 instance_templ->SetAccessor(v8_str("f"), ShouldThrowOnErrorGetter,
13145 ShouldThrowOnErrorSetter<void>);
13146
13147 Local<v8::Object> instance = templ->GetFunction(context.local())
13148 .ToLocalChecked()
13149 ->NewInstance(context.local())
13150 .ToLocalChecked();
13151
13152 CHECK(global->Set(context.local(), v8_str("o"), instance).FromJust());
13153
13154 // SLOPPY mode
13155 Local<Value> value = v8_compile("o.f")->Run(context.local()).ToLocalChecked();
13156 CHECK(value->IsFalse());
13157 v8_compile("o.f = 153")->Run(context.local()).ToLocalChecked();
13158 value = global->Get(context.local(), v8_str("should_throw_setter"))
13159 .ToLocalChecked();
13160 CHECK(value->IsFalse());
13161
13162 // STRICT mode
13163 value = v8_compile("'use strict';o.f")->Run(context.local()).ToLocalChecked();
13164 CHECK(value->IsFalse());
13165 v8_compile("'use strict'; o.f = 153")->Run(context.local()).ToLocalChecked();
13166 value = global->Get(context.local(), v8_str("should_throw_setter"))
13167 .ToLocalChecked();
13168 CHECK(value->IsTrue());
Ben Murdoch097c5b22016-05-18 11:27:45 +010013169}
13170
13171
13172static void ShouldThrowOnErrorQuery(
13173 Local<Name> name, const v8::PropertyCallbackInfo<v8::Integer>& info) {
13174 ApiTestFuzzer::Fuzz();
13175 v8::Isolate* isolate = info.GetIsolate();
13176 info.GetReturnValue().Set(v8::None);
13177
13178 auto context = isolate->GetCurrentContext();
13179 Local<Boolean> should_throw_on_error_value =
13180 Boolean::New(isolate, info.ShouldThrowOnError());
13181 CHECK(context->Global()
13182 ->Set(isolate->GetCurrentContext(), v8_str("should_throw_query"),
13183 should_throw_on_error_value)
13184 .FromJust());
13185}
13186
13187
13188static void ShouldThrowOnErrorDeleter(
13189 Local<Name> name, const v8::PropertyCallbackInfo<v8::Boolean>& info) {
13190 ApiTestFuzzer::Fuzz();
13191 v8::Isolate* isolate = info.GetIsolate();
13192 info.GetReturnValue().Set(v8::True(isolate));
13193
13194 auto context = isolate->GetCurrentContext();
13195 Local<Boolean> should_throw_on_error_value =
13196 Boolean::New(isolate, info.ShouldThrowOnError());
13197 CHECK(context->Global()
13198 ->Set(isolate->GetCurrentContext(), v8_str("should_throw_deleter"),
13199 should_throw_on_error_value)
13200 .FromJust());
13201}
13202
13203
13204static void ShouldThrowOnErrorPropertyEnumerator(
13205 const v8::PropertyCallbackInfo<v8::Array>& info) {
13206 ApiTestFuzzer::Fuzz();
13207 v8::Isolate* isolate = info.GetIsolate();
13208 Local<v8::Array> names = v8::Array::New(isolate, 1);
13209 CHECK(names->Set(isolate->GetCurrentContext(), names, v8_num(1)).FromJust());
13210 info.GetReturnValue().Set(names);
13211
13212 auto context = isolate->GetCurrentContext();
13213 Local<Boolean> should_throw_on_error_value =
13214 Boolean::New(isolate, info.ShouldThrowOnError());
13215 CHECK(context->Global()
13216 ->Set(isolate->GetCurrentContext(),
13217 v8_str("should_throw_enumerator"),
13218 should_throw_on_error_value)
13219 .FromJust());
13220}
13221
13222
13223THREADED_TEST(InterceptorShouldThrowOnError) {
Ben Murdoch097c5b22016-05-18 11:27:45 +010013224 LocalContext context;
13225 v8::Isolate* isolate = context->GetIsolate();
13226 v8::HandleScope scope(isolate);
13227 Local<Object> global = context->Global();
13228
13229 auto interceptor_templ = v8::ObjectTemplate::New(isolate);
13230 v8::NamedPropertyHandlerConfiguration handler(
13231 ShouldThrowOnErrorGetter, ShouldThrowOnErrorSetter<Value>,
13232 ShouldThrowOnErrorQuery, ShouldThrowOnErrorDeleter,
13233 ShouldThrowOnErrorPropertyEnumerator);
13234 interceptor_templ->SetHandler(handler);
13235
13236 Local<v8::Object> instance =
13237 interceptor_templ->NewInstance(context.local()).ToLocalChecked();
13238
13239 CHECK(global->Set(context.local(), v8_str("o"), instance).FromJust());
13240
13241 // SLOPPY mode
13242 Local<Value> value = v8_compile("o.f")->Run(context.local()).ToLocalChecked();
13243 CHECK(value->IsFalse());
13244 v8_compile("o.f = 153")->Run(context.local()).ToLocalChecked();
13245 value = global->Get(context.local(), v8_str("should_throw_setter"))
13246 .ToLocalChecked();
13247 CHECK(value->IsFalse());
13248
13249 v8_compile("delete o.f")->Run(context.local()).ToLocalChecked();
13250 value = global->Get(context.local(), v8_str("should_throw_deleter"))
13251 .ToLocalChecked();
13252 CHECK(value->IsFalse());
13253
13254 v8_compile("Object.getOwnPropertyNames(o)")
13255 ->Run(context.local())
13256 .ToLocalChecked();
13257 value = global->Get(context.local(), v8_str("should_throw_enumerator"))
13258 .ToLocalChecked();
13259 CHECK(value->IsFalse());
13260
13261 // STRICT mode
13262 value = v8_compile("'use strict';o.f")->Run(context.local()).ToLocalChecked();
13263 CHECK(value->IsFalse());
13264 v8_compile("'use strict'; o.f = 153")->Run(context.local()).ToLocalChecked();
13265 value = global->Get(context.local(), v8_str("should_throw_setter"))
13266 .ToLocalChecked();
13267 CHECK(value->IsTrue());
13268
13269 v8_compile("'use strict'; delete o.f")->Run(context.local()).ToLocalChecked();
13270 value = global->Get(context.local(), v8_str("should_throw_deleter"))
13271 .ToLocalChecked();
13272 CHECK(value->IsTrue());
13273
13274 v8_compile("'use strict'; Object.getOwnPropertyNames(o)")
13275 ->Run(context.local())
13276 .ToLocalChecked();
13277 value = global->Get(context.local(), v8_str("should_throw_enumerator"))
13278 .ToLocalChecked();
13279 CHECK(value->IsFalse());
Ben Murdoch097c5b22016-05-18 11:27:45 +010013280}
13281
13282
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013283static void IsConstructHandler(
13284 const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +000013285 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013286 args.GetReturnValue().Set(args.IsConstructCall());
Steve Blocka7e24c12009-10-30 11:49:00 +000013287}
13288
13289
13290THREADED_TEST(IsConstructCall) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013291 v8::Isolate* isolate = CcTest::isolate();
13292 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000013293
13294 // Function template with call handler.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013295 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000013296 templ->SetCallHandler(IsConstructHandler);
13297
13298 LocalContext context;
13299
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013300 CHECK(context->Global()
13301 ->Set(context.local(), v8_str("f"),
13302 templ->GetFunction(context.local()).ToLocalChecked())
13303 .FromJust());
13304 Local<Value> value = v8_compile("f()")->Run(context.local()).ToLocalChecked();
13305 CHECK(!value->BooleanValue(context.local()).FromJust());
13306 value = v8_compile("new f()")->Run(context.local()).ToLocalChecked();
13307 CHECK(value->BooleanValue(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013308}
13309
Ben Murdochc5610432016-08-08 18:44:38 +010013310static void NewTargetHandler(const v8::FunctionCallbackInfo<v8::Value>& args) {
13311 ApiTestFuzzer::Fuzz();
13312 args.GetReturnValue().Set(args.NewTarget());
13313}
13314
13315THREADED_TEST(NewTargetHandler) {
13316 v8::Isolate* isolate = CcTest::isolate();
13317 v8::HandleScope scope(isolate);
13318
13319 // Function template with call handler.
13320 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
13321 templ->SetCallHandler(NewTargetHandler);
13322
13323 LocalContext context;
13324
13325 Local<Function> function =
13326 templ->GetFunction(context.local()).ToLocalChecked();
13327 CHECK(context->Global()
13328 ->Set(context.local(), v8_str("f"), function)
13329 .FromJust());
13330 Local<Value> value = CompileRun("f()");
13331 CHECK(value->IsUndefined());
13332 value = CompileRun("new f()");
13333 CHECK(value->IsFunction());
13334 CHECK(value == function);
13335 Local<Value> subclass = CompileRun("var g = class extends f { }; g");
13336 CHECK(subclass->IsFunction());
13337 value = CompileRun("new g()");
13338 CHECK(value->IsFunction());
13339 CHECK(value == subclass);
13340 value = CompileRun("Reflect.construct(f, [], Array)");
13341 CHECK(value->IsFunction());
13342 CHECK(value ==
13343 context->Global()
13344 ->Get(context.local(), v8_str("Array"))
13345 .ToLocalChecked());
13346}
Steve Blocka7e24c12009-10-30 11:49:00 +000013347
13348THREADED_TEST(ObjectProtoToString) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013349 v8::Isolate* isolate = CcTest::isolate();
13350 v8::HandleScope scope(isolate);
13351 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000013352 templ->SetClassName(v8_str("MyClass"));
13353
13354 LocalContext context;
13355
13356 Local<String> customized_tostring = v8_str("customized toString");
13357
13358 // Replace Object.prototype.toString
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013359 v8_compile(
13360 "Object.prototype.toString = function() {"
13361 " return 'customized toString';"
13362 "}")
13363 ->Run(context.local())
13364 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000013365
13366 // Normal ToString call should call replaced Object.prototype.toString
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013367 Local<v8::Object> instance = templ->GetFunction(context.local())
13368 .ToLocalChecked()
13369 ->NewInstance(context.local())
13370 .ToLocalChecked();
13371 Local<String> value = instance->ToString(context.local()).ToLocalChecked();
13372 CHECK(value->IsString() &&
13373 value->Equals(context.local(), customized_tostring).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013374
13375 // ObjectProtoToString should not call replace toString function.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013376 value = instance->ObjectProtoToString(context.local()).ToLocalChecked();
13377 CHECK(value->IsString() &&
13378 value->Equals(context.local(), v8_str("[object MyClass]")).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013379
13380 // Check global
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013381 value =
13382 context->Global()->ObjectProtoToString(context.local()).ToLocalChecked();
13383 CHECK(value->IsString() &&
13384 value->Equals(context.local(), v8_str("[object global]")).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013385
13386 // Check ordinary object
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013387 Local<Value> object =
13388 v8_compile("new Object()")->Run(context.local()).ToLocalChecked();
13389 value = object.As<v8::Object>()
13390 ->ObjectProtoToString(context.local())
13391 .ToLocalChecked();
13392 CHECK(value->IsString() &&
13393 value->Equals(context.local(), v8_str("[object Object]")).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013394}
13395
13396
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013397TEST(ObjectProtoToStringES6) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -080013398 LocalContext context;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013399 v8::Isolate* isolate = CcTest::isolate();
13400 v8::HandleScope scope(isolate);
13401 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
13402 templ->SetClassName(v8_str("MyClass"));
13403
13404 Local<String> customized_tostring = v8_str("customized toString");
13405
13406 // Replace Object.prototype.toString
13407 CompileRun(
13408 "Object.prototype.toString = function() {"
13409 " return 'customized toString';"
13410 "}");
13411
13412 // Normal ToString call should call replaced Object.prototype.toString
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013413 Local<v8::Object> instance = templ->GetFunction(context.local())
13414 .ToLocalChecked()
13415 ->NewInstance(context.local())
13416 .ToLocalChecked();
13417 Local<String> value = instance->ToString(context.local()).ToLocalChecked();
13418 CHECK(value->IsString() &&
13419 value->Equals(context.local(), customized_tostring).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013420
13421 // ObjectProtoToString should not call replace toString function.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013422 value = instance->ObjectProtoToString(context.local()).ToLocalChecked();
13423 CHECK(value->IsString() &&
13424 value->Equals(context.local(), v8_str("[object MyClass]")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013425
13426 // Check global
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013427 value =
13428 context->Global()->ObjectProtoToString(context.local()).ToLocalChecked();
13429 CHECK(value->IsString() &&
13430 value->Equals(context.local(), v8_str("[object global]")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013431
13432 // Check ordinary object
13433 Local<Value> object = CompileRun("new Object()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013434 value = object.As<v8::Object>()
13435 ->ObjectProtoToString(context.local())
13436 .ToLocalChecked();
13437 CHECK(value->IsString() &&
13438 value->Equals(context.local(), v8_str("[object Object]")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013439
13440 // Check that ES6 semantics using @@toStringTag work
13441 Local<v8::Symbol> toStringTag = v8::Symbol::GetToStringTag(isolate);
13442
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013443#define TEST_TOSTRINGTAG(type, tag, expected) \
13444 do { \
13445 object = CompileRun("new " #type "()"); \
13446 CHECK(object.As<v8::Object>() \
13447 ->Set(context.local(), toStringTag, v8_str(#tag)) \
13448 .FromJust()); \
13449 value = object.As<v8::Object>() \
13450 ->ObjectProtoToString(context.local()) \
13451 .ToLocalChecked(); \
13452 CHECK(value->IsString() && \
13453 value->Equals(context.local(), v8_str("[object " #expected "]")) \
13454 .FromJust()); \
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013455 } while (0)
13456
13457 TEST_TOSTRINGTAG(Array, Object, Object);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013458 TEST_TOSTRINGTAG(Object, Arguments, Arguments);
13459 TEST_TOSTRINGTAG(Object, Array, Array);
13460 TEST_TOSTRINGTAG(Object, Boolean, Boolean);
13461 TEST_TOSTRINGTAG(Object, Date, Date);
13462 TEST_TOSTRINGTAG(Object, Error, Error);
13463 TEST_TOSTRINGTAG(Object, Function, Function);
13464 TEST_TOSTRINGTAG(Object, Number, Number);
13465 TEST_TOSTRINGTAG(Object, RegExp, RegExp);
13466 TEST_TOSTRINGTAG(Object, String, String);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013467 TEST_TOSTRINGTAG(Object, Foo, Foo);
13468
13469#undef TEST_TOSTRINGTAG
13470
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013471 Local<v8::RegExp> valueRegExp =
13472 v8::RegExp::New(context.local(), v8_str("^$"), v8::RegExp::kNone)
13473 .ToLocalChecked();
13474 Local<Value> valueNumber = v8_num(123);
13475 Local<v8::Symbol> valueSymbol = v8_symbol("TestSymbol");
13476 Local<v8::Function> valueFunction =
13477 CompileRun("(function fn() {})").As<v8::Function>();
13478 Local<v8::Object> valueObject = v8::Object::New(v8::Isolate::GetCurrent());
13479 Local<v8::Primitive> valueNull = v8::Null(v8::Isolate::GetCurrent());
13480 Local<v8::Primitive> valueUndef = v8::Undefined(v8::Isolate::GetCurrent());
13481
13482#define TEST_TOSTRINGTAG(type, tagValue, expected) \
13483 do { \
13484 object = CompileRun("new " #type "()"); \
13485 CHECK(object.As<v8::Object>() \
13486 ->Set(context.local(), toStringTag, tagValue) \
13487 .FromJust()); \
13488 value = object.As<v8::Object>() \
13489 ->ObjectProtoToString(context.local()) \
13490 .ToLocalChecked(); \
13491 CHECK(value->IsString() && \
13492 value->Equals(context.local(), v8_str("[object " #expected "]")) \
13493 .FromJust()); \
13494 } while (0)
13495
13496#define TEST_TOSTRINGTAG_TYPES(tagValue) \
13497 TEST_TOSTRINGTAG(Array, tagValue, Array); \
13498 TEST_TOSTRINGTAG(Object, tagValue, Object); \
13499 TEST_TOSTRINGTAG(Function, tagValue, Function); \
13500 TEST_TOSTRINGTAG(Date, tagValue, Date); \
13501 TEST_TOSTRINGTAG(RegExp, tagValue, RegExp); \
13502 TEST_TOSTRINGTAG(Error, tagValue, Error); \
13503
13504 // Test non-String-valued @@toStringTag
13505 TEST_TOSTRINGTAG_TYPES(valueRegExp);
13506 TEST_TOSTRINGTAG_TYPES(valueNumber);
13507 TEST_TOSTRINGTAG_TYPES(valueSymbol);
13508 TEST_TOSTRINGTAG_TYPES(valueFunction);
13509 TEST_TOSTRINGTAG_TYPES(valueObject);
13510 TEST_TOSTRINGTAG_TYPES(valueNull);
13511 TEST_TOSTRINGTAG_TYPES(valueUndef);
13512
13513#undef TEST_TOSTRINGTAG
13514#undef TEST_TOSTRINGTAG_TYPES
13515
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013516 // @@toStringTag getter throws
13517 Local<Value> obj = v8::Object::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013518 obj.As<v8::Object>()
13519 ->SetAccessor(context.local(), toStringTag, ThrowingSymbolAccessorGetter)
13520 .FromJust();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013521 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013522 TryCatch try_catch(isolate);
13523 CHECK(obj.As<v8::Object>()->ObjectProtoToString(context.local()).IsEmpty());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013524 CHECK(try_catch.HasCaught());
13525 }
13526
13527 // @@toStringTag getter does not throw
13528 obj = v8::Object::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013529 obj.As<v8::Object>()
13530 ->SetAccessor(context.local(), toStringTag,
13531 SymbolAccessorGetterReturnsDefault, 0, v8_str("Test"))
13532 .FromJust();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013533 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013534 TryCatch try_catch(isolate);
13535 value = obj.As<v8::Object>()
13536 ->ObjectProtoToString(context.local())
13537 .ToLocalChecked();
13538 CHECK(value->IsString() &&
13539 value->Equals(context.local(), v8_str("[object Test]")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013540 CHECK(!try_catch.HasCaught());
13541 }
13542
13543 // JS @@toStringTag value
13544 obj = CompileRun("obj = {}; obj[Symbol.toStringTag] = 'Test'; obj");
13545 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013546 TryCatch try_catch(isolate);
13547 value = obj.As<v8::Object>()
13548 ->ObjectProtoToString(context.local())
13549 .ToLocalChecked();
13550 CHECK(value->IsString() &&
13551 value->Equals(context.local(), v8_str("[object Test]")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013552 CHECK(!try_catch.HasCaught());
13553 }
13554
13555 // JS @@toStringTag getter throws
13556 obj = CompileRun(
13557 "obj = {}; Object.defineProperty(obj, Symbol.toStringTag, {"
13558 " get: function() { throw 'Test'; }"
13559 "}); obj");
13560 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013561 TryCatch try_catch(isolate);
13562 CHECK(obj.As<v8::Object>()->ObjectProtoToString(context.local()).IsEmpty());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013563 CHECK(try_catch.HasCaught());
13564 }
13565
13566 // JS @@toStringTag getter does not throw
13567 obj = CompileRun(
13568 "obj = {}; Object.defineProperty(obj, Symbol.toStringTag, {"
13569 " get: function() { return 'Test'; }"
13570 "}); obj");
13571 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013572 TryCatch try_catch(isolate);
13573 value = obj.As<v8::Object>()
13574 ->ObjectProtoToString(context.local())
13575 .ToLocalChecked();
13576 CHECK(value->IsString() &&
13577 value->Equals(context.local(), v8_str("[object Test]")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013578 CHECK(!try_catch.HasCaught());
13579 }
13580}
13581
13582
13583THREADED_TEST(ObjectGetConstructorName) {
13584 v8::Isolate* isolate = CcTest::isolate();
13585 LocalContext context;
13586 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013587 v8_compile(
13588 "function Parent() {};"
13589 "function Child() {};"
13590 "Child.prototype = new Parent();"
13591 "Child.prototype.constructor = Child;"
Ben Murdochda12d292016-06-02 14:46:10 +010013592 "var outer = { inner: (0, function() { }) };"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013593 "var p = new Parent();"
13594 "var c = new Child();"
13595 "var x = new outer.inner();"
13596 "var proto = Child.prototype;")
13597 ->Run(context.local())
13598 .ToLocalChecked();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -080013599
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013600 Local<v8::Value> p =
13601 context->Global()->Get(context.local(), v8_str("p")).ToLocalChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013602 CHECK(p->IsObject() &&
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013603 p->ToObject(context.local())
13604 .ToLocalChecked()
13605 ->GetConstructorName()
13606 ->Equals(context.local(), v8_str("Parent"))
13607 .FromJust());
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -080013608
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013609 Local<v8::Value> c =
13610 context->Global()->Get(context.local(), v8_str("c")).ToLocalChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013611 CHECK(c->IsObject() &&
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013612 c->ToObject(context.local())
13613 .ToLocalChecked()
13614 ->GetConstructorName()
13615 ->Equals(context.local(), v8_str("Child"))
13616 .FromJust());
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -080013617
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013618 Local<v8::Value> x =
13619 context->Global()->Get(context.local(), v8_str("x")).ToLocalChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013620 CHECK(x->IsObject() &&
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013621 x->ToObject(context.local())
13622 .ToLocalChecked()
13623 ->GetConstructorName()
13624 ->Equals(context.local(), v8_str("outer.inner"))
13625 .FromJust());
13626
13627 Local<v8::Value> child_prototype =
13628 context->Global()->Get(context.local(), v8_str("proto")).ToLocalChecked();
13629 CHECK(child_prototype->IsObject() &&
13630 child_prototype->ToObject(context.local())
13631 .ToLocalChecked()
13632 ->GetConstructorName()
13633 ->Equals(context.local(), v8_str("Parent"))
13634 .FromJust());
13635}
13636
13637
13638THREADED_TEST(SubclassGetConstructorName) {
13639 v8::Isolate* isolate = CcTest::isolate();
13640 LocalContext context;
13641 v8::HandleScope scope(isolate);
13642 v8_compile(
13643 "\"use strict\";"
13644 "class Parent {}"
13645 "class Child extends Parent {}"
13646 "var p = new Parent();"
13647 "var c = new Child();")
13648 ->Run(context.local())
13649 .ToLocalChecked();
13650
13651 Local<v8::Value> p =
13652 context->Global()->Get(context.local(), v8_str("p")).ToLocalChecked();
13653 CHECK(p->IsObject() &&
13654 p->ToObject(context.local())
13655 .ToLocalChecked()
13656 ->GetConstructorName()
13657 ->Equals(context.local(), v8_str("Parent"))
13658 .FromJust());
13659
13660 Local<v8::Value> c =
13661 context->Global()->Get(context.local(), v8_str("c")).ToLocalChecked();
13662 CHECK(c->IsObject() &&
13663 c->ToObject(context.local())
13664 .ToLocalChecked()
13665 ->GetConstructorName()
13666 ->Equals(context.local(), v8_str("Child"))
13667 .FromJust());
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -080013668}
13669
13670
Steve Blocka7e24c12009-10-30 11:49:00 +000013671bool ApiTestFuzzer::fuzzing_ = false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013672v8::base::Semaphore ApiTestFuzzer::all_tests_done_(0);
Steve Blocka7e24c12009-10-30 11:49:00 +000013673int ApiTestFuzzer::active_tests_;
13674int ApiTestFuzzer::tests_being_run_;
13675int ApiTestFuzzer::current_;
13676
13677
13678// We are in a callback and want to switch to another thread (if we
13679// are currently running the thread fuzzing test).
13680void ApiTestFuzzer::Fuzz() {
13681 if (!fuzzing_) return;
13682 ApiTestFuzzer* test = RegisterThreadedTest::nth(current_)->fuzzer_;
13683 test->ContextSwitch();
13684}
13685
13686
13687// Let the next thread go. Since it is also waiting on the V8 lock it may
13688// not start immediately.
13689bool ApiTestFuzzer::NextThread() {
13690 int test_position = GetNextTestNumber();
Steve Blockd0582a62009-12-15 09:54:21 +000013691 const char* test_name = RegisterThreadedTest::nth(current_)->name();
Steve Blocka7e24c12009-10-30 11:49:00 +000013692 if (test_position == current_) {
Steve Blockd0582a62009-12-15 09:54:21 +000013693 if (kLogThreading)
13694 printf("Stay with %s\n", test_name);
Steve Blocka7e24c12009-10-30 11:49:00 +000013695 return false;
13696 }
Steve Blockd0582a62009-12-15 09:54:21 +000013697 if (kLogThreading) {
13698 printf("Switch from %s to %s\n",
13699 test_name,
13700 RegisterThreadedTest::nth(test_position)->name());
13701 }
Steve Blocka7e24c12009-10-30 11:49:00 +000013702 current_ = test_position;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013703 RegisterThreadedTest::nth(current_)->fuzzer_->gate_.Signal();
Steve Blocka7e24c12009-10-30 11:49:00 +000013704 return true;
13705}
13706
13707
13708void ApiTestFuzzer::Run() {
13709 // When it is our turn...
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013710 gate_.Wait();
Steve Blocka7e24c12009-10-30 11:49:00 +000013711 {
13712 // ... get the V8 lock and start running the test.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013713 v8::Locker locker(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000013714 CallTest();
13715 }
13716 // This test finished.
13717 active_ = false;
13718 active_tests_--;
13719 // If it was the last then signal that fact.
13720 if (active_tests_ == 0) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013721 all_tests_done_.Signal();
Steve Blocka7e24c12009-10-30 11:49:00 +000013722 } else {
13723 // Otherwise select a new test and start that.
13724 NextThread();
13725 }
13726}
13727
13728
13729static unsigned linear_congruential_generator;
13730
13731
Ben Murdoch3ef787d2012-04-12 10:51:47 +010013732void ApiTestFuzzer::SetUp(PartOfTest part) {
Steve Blocka7e24c12009-10-30 11:49:00 +000013733 linear_congruential_generator = i::FLAG_testing_prng_seed;
13734 fuzzing_ = true;
Ben Murdoch257744e2011-11-30 15:57:28 +000013735 int count = RegisterThreadedTest::count();
13736 int start = count * part / (LAST_PART + 1);
13737 int end = (count * (part + 1) / (LAST_PART + 1)) - 1;
13738 active_tests_ = tests_being_run_ = end - start + 1;
Steve Blocka7e24c12009-10-30 11:49:00 +000013739 for (int i = 0; i < tests_being_run_; i++) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000013740 RegisterThreadedTest::nth(i)->fuzzer_ = new ApiTestFuzzer(i + start);
Steve Blocka7e24c12009-10-30 11:49:00 +000013741 }
13742 for (int i = 0; i < active_tests_; i++) {
13743 RegisterThreadedTest::nth(i)->fuzzer_->Start();
13744 }
13745}
13746
13747
13748static void CallTestNumber(int test_number) {
13749 (RegisterThreadedTest::nth(test_number)->callback())();
13750}
13751
13752
13753void ApiTestFuzzer::RunAllTests() {
13754 // Set off the first test.
13755 current_ = -1;
13756 NextThread();
13757 // Wait till they are all done.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013758 all_tests_done_.Wait();
Steve Blocka7e24c12009-10-30 11:49:00 +000013759}
13760
13761
13762int ApiTestFuzzer::GetNextTestNumber() {
13763 int next_test;
13764 do {
13765 next_test = (linear_congruential_generator >> 16) % tests_being_run_;
13766 linear_congruential_generator *= 1664525u;
13767 linear_congruential_generator += 1013904223u;
13768 } while (!RegisterThreadedTest::nth(next_test)->fuzzer_->active_);
13769 return next_test;
13770}
13771
13772
13773void ApiTestFuzzer::ContextSwitch() {
13774 // If the new thread is the same as the current thread there is nothing to do.
13775 if (NextThread()) {
13776 // Now it can start.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013777 v8::Unlocker unlocker(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000013778 // Wait till someone starts us again.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013779 gate_.Wait();
Steve Blocka7e24c12009-10-30 11:49:00 +000013780 // And we're off.
13781 }
13782}
13783
13784
13785void ApiTestFuzzer::TearDown() {
13786 fuzzing_ = false;
13787 for (int i = 0; i < RegisterThreadedTest::count(); i++) {
13788 ApiTestFuzzer *fuzzer = RegisterThreadedTest::nth(i)->fuzzer_;
13789 if (fuzzer != NULL) fuzzer->Join();
13790 }
13791}
13792
13793
13794// Lets not be needlessly self-referential.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013795TEST(Threading1) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010013796 ApiTestFuzzer::SetUp(ApiTestFuzzer::FIRST_PART);
Steve Blocka7e24c12009-10-30 11:49:00 +000013797 ApiTestFuzzer::RunAllTests();
13798 ApiTestFuzzer::TearDown();
13799}
13800
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013801
Steve Blocka7e24c12009-10-30 11:49:00 +000013802TEST(Threading2) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010013803 ApiTestFuzzer::SetUp(ApiTestFuzzer::SECOND_PART);
Steve Blocka7e24c12009-10-30 11:49:00 +000013804 ApiTestFuzzer::RunAllTests();
13805 ApiTestFuzzer::TearDown();
13806}
13807
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013808
Ben Murdoch257744e2011-11-30 15:57:28 +000013809TEST(Threading3) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010013810 ApiTestFuzzer::SetUp(ApiTestFuzzer::THIRD_PART);
Ben Murdoch257744e2011-11-30 15:57:28 +000013811 ApiTestFuzzer::RunAllTests();
13812 ApiTestFuzzer::TearDown();
13813}
13814
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013815
Ben Murdoch257744e2011-11-30 15:57:28 +000013816TEST(Threading4) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010013817 ApiTestFuzzer::SetUp(ApiTestFuzzer::FOURTH_PART);
Ben Murdoch257744e2011-11-30 15:57:28 +000013818 ApiTestFuzzer::RunAllTests();
13819 ApiTestFuzzer::TearDown();
13820}
Steve Blocka7e24c12009-10-30 11:49:00 +000013821
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013822
Steve Blocka7e24c12009-10-30 11:49:00 +000013823void ApiTestFuzzer::CallTest() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013824 v8::Isolate::Scope scope(CcTest::isolate());
Steve Blockd0582a62009-12-15 09:54:21 +000013825 if (kLogThreading)
13826 printf("Start test %d\n", test_number_);
Steve Blocka7e24c12009-10-30 11:49:00 +000013827 CallTestNumber(test_number_);
Steve Blockd0582a62009-12-15 09:54:21 +000013828 if (kLogThreading)
13829 printf("End test %d\n", test_number_);
Steve Blocka7e24c12009-10-30 11:49:00 +000013830}
13831
13832
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013833static void ThrowInJS(const v8::FunctionCallbackInfo<v8::Value>& args) {
13834 v8::Isolate* isolate = args.GetIsolate();
13835 CHECK(v8::Locker::IsLocked(isolate));
Steve Blocka7e24c12009-10-30 11:49:00 +000013836 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013837 v8::Unlocker unlocker(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000013838 const char* code = "throw 7;";
13839 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013840 v8::Locker nested_locker(isolate);
13841 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013842 v8::Local<Value> exception;
13843 {
13844 v8::TryCatch try_catch(isolate);
13845 v8::Local<Value> value = CompileRun(code);
Steve Blocka7e24c12009-10-30 11:49:00 +000013846 CHECK(value.IsEmpty());
13847 CHECK(try_catch.HasCaught());
13848 // Make sure to wrap the exception in a new handle because
13849 // the handle returned from the TryCatch is destroyed
13850 // when the TryCatch is destroyed.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013851 exception = Local<Value>::New(isolate, try_catch.Exception());
Steve Blocka7e24c12009-10-30 11:49:00 +000013852 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013853 args.GetIsolate()->ThrowException(exception);
Steve Blocka7e24c12009-10-30 11:49:00 +000013854 }
13855}
13856
13857
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013858static void ThrowInJSNoCatch(const v8::FunctionCallbackInfo<v8::Value>& args) {
13859 CHECK(v8::Locker::IsLocked(CcTest::isolate()));
Steve Blocka7e24c12009-10-30 11:49:00 +000013860 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013861 v8::Unlocker unlocker(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000013862 const char* code = "throw 7;";
13863 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013864 v8::Locker nested_locker(CcTest::isolate());
13865 v8::HandleScope scope(args.GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013866 v8::Local<Value> value = CompileRun(code);
Steve Blocka7e24c12009-10-30 11:49:00 +000013867 CHECK(value.IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013868 args.GetReturnValue().Set(v8_str("foo"));
Steve Blocka7e24c12009-10-30 11:49:00 +000013869 }
13870}
13871
13872
13873// These are locking tests that don't need to be run again
13874// as part of the locking aggregation tests.
13875TEST(NestedLockers) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013876 v8::Isolate* isolate = CcTest::isolate();
13877 v8::Locker locker(isolate);
13878 CHECK(v8::Locker::IsLocked(isolate));
Steve Blocka7e24c12009-10-30 11:49:00 +000013879 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013880 v8::HandleScope scope(env->GetIsolate());
13881 Local<v8::FunctionTemplate> fun_templ =
13882 v8::FunctionTemplate::New(isolate, ThrowInJS);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013883 Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
13884 CHECK(env->Global()->Set(env.local(), v8_str("throw_in_js"), fun).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013885 Local<Script> script = v8_compile("(function () {"
13886 " try {"
13887 " throw_in_js();"
13888 " return 42;"
13889 " } catch (e) {"
13890 " return e * 13;"
13891 " }"
13892 "})();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013893 CHECK_EQ(91, script->Run(env.local())
13894 .ToLocalChecked()
13895 ->Int32Value(env.local())
13896 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013897}
13898
13899
13900// These are locking tests that don't need to be run again
13901// as part of the locking aggregation tests.
13902TEST(NestedLockersNoTryCatch) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013903 v8::Locker locker(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000013904 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013905 v8::HandleScope scope(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000013906 Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013907 v8::FunctionTemplate::New(env->GetIsolate(), ThrowInJSNoCatch);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013908 Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
13909 CHECK(env->Global()->Set(env.local(), v8_str("throw_in_js"), fun).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013910 Local<Script> script = v8_compile("(function () {"
13911 " try {"
13912 " throw_in_js();"
13913 " return 42;"
13914 " } catch (e) {"
13915 " return e * 13;"
13916 " }"
13917 "})();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013918 CHECK_EQ(91, script->Run(env.local())
13919 .ToLocalChecked()
13920 ->Int32Value(env.local())
13921 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013922}
13923
13924
13925THREADED_TEST(RecursiveLocking) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013926 v8::Locker locker(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000013927 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013928 v8::Locker locker2(CcTest::isolate());
13929 CHECK(v8::Locker::IsLocked(CcTest::isolate()));
Steve Blocka7e24c12009-10-30 11:49:00 +000013930 }
13931}
13932
13933
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013934static void UnlockForAMoment(const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +000013935 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013936 v8::Unlocker unlocker(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000013937}
13938
13939
13940THREADED_TEST(LockUnlockLock) {
13941 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013942 v8::Locker locker(CcTest::isolate());
13943 v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000013944 LocalContext env;
13945 Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013946 v8::FunctionTemplate::New(CcTest::isolate(), UnlockForAMoment);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013947 Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
13948 CHECK(env->Global()
13949 ->Set(env.local(), v8_str("unlock_for_a_moment"), fun)
13950 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013951 Local<Script> script = v8_compile("(function () {"
13952 " unlock_for_a_moment();"
13953 " return 42;"
13954 "})();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013955 CHECK_EQ(42, script->Run(env.local())
13956 .ToLocalChecked()
13957 ->Int32Value(env.local())
13958 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013959 }
13960 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013961 v8::Locker locker(CcTest::isolate());
13962 v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000013963 LocalContext env;
13964 Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013965 v8::FunctionTemplate::New(CcTest::isolate(), UnlockForAMoment);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013966 Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
13967 CHECK(env->Global()
13968 ->Set(env.local(), v8_str("unlock_for_a_moment"), fun)
13969 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013970 Local<Script> script = v8_compile("(function () {"
13971 " unlock_for_a_moment();"
13972 " return 42;"
13973 "})();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013974 CHECK_EQ(42, script->Run(env.local())
13975 .ToLocalChecked()
13976 ->Int32Value(env.local())
13977 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013978 }
13979}
13980
13981
Leon Clarked91b9f72010-01-27 17:25:45 +000013982static int GetGlobalObjectsCount() {
Leon Clarkeeab96aa2010-01-27 16:31:12 +000013983 int count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013984 i::HeapIterator it(CcTest::heap());
Leon Clarked91b9f72010-01-27 17:25:45 +000013985 for (i::HeapObject* object = it.next(); object != NULL; object = it.next())
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013986 if (object->IsJSGlobalObject()) {
13987 i::JSGlobalObject* g = i::JSGlobalObject::cast(object);
13988 // Skip dummy global object.
13989 if (i::GlobalDictionary::cast(g->properties())->NumberOfElements() != 0) {
13990 count++;
13991 }
13992 }
Leon Clarked91b9f72010-01-27 17:25:45 +000013993 return count;
13994}
13995
13996
Ben Murdochf87a2032010-10-22 12:50:53 +010013997static void CheckSurvivingGlobalObjectsCount(int expected) {
Steve Blocka7e24c12009-10-30 11:49:00 +000013998 // We need to collect all garbage twice to be sure that everything
13999 // has been collected. This is because inline caches are cleared in
14000 // the first garbage collection but some of the maps have already
14001 // been marked at that point. Therefore some of the maps are not
14002 // collected until the second garbage collection.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014003 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014004 CcTest::heap()->CollectAllGarbage(i::Heap::kMakeHeapIterableMask);
Leon Clarked91b9f72010-01-27 17:25:45 +000014005 int count = GetGlobalObjectsCount();
Steve Blocka7e24c12009-10-30 11:49:00 +000014006#ifdef DEBUG
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014007 if (count != expected) CcTest::heap()->TracePathToGlobal();
Steve Blocka7e24c12009-10-30 11:49:00 +000014008#endif
Ben Murdochf87a2032010-10-22 12:50:53 +010014009 CHECK_EQ(expected, count);
Steve Blocka7e24c12009-10-30 11:49:00 +000014010}
14011
14012
14013TEST(DontLeakGlobalObjects) {
14014 // Regression test for issues 1139850 and 1174891.
14015
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014016 i::FLAG_expose_gc = true;
Steve Blocka7e24c12009-10-30 11:49:00 +000014017 v8::V8::Initialize();
14018
Steve Blocka7e24c12009-10-30 11:49:00 +000014019 for (int i = 0; i < 5; i++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014020 { v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000014021 LocalContext context;
14022 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014023 CcTest::isolate()->ContextDisposedNotification();
Ben Murdochf87a2032010-10-22 12:50:53 +010014024 CheckSurvivingGlobalObjectsCount(0);
Steve Blocka7e24c12009-10-30 11:49:00 +000014025
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014026 { v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000014027 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014028 v8_compile("Date")->Run(context.local()).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000014029 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014030 CcTest::isolate()->ContextDisposedNotification();
Ben Murdochf87a2032010-10-22 12:50:53 +010014031 CheckSurvivingGlobalObjectsCount(0);
Steve Blocka7e24c12009-10-30 11:49:00 +000014032
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014033 { v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000014034 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014035 v8_compile("/aaa/")->Run(context.local()).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000014036 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014037 CcTest::isolate()->ContextDisposedNotification();
Ben Murdochf87a2032010-10-22 12:50:53 +010014038 CheckSurvivingGlobalObjectsCount(0);
Steve Blocka7e24c12009-10-30 11:49:00 +000014039
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014040 { v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000014041 const char* extension_list[] = { "v8/gc" };
14042 v8::ExtensionConfiguration extensions(1, extension_list);
14043 LocalContext context(&extensions);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014044 v8_compile("gc();")->Run(context.local()).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000014045 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014046 CcTest::isolate()->ContextDisposedNotification();
Ben Murdochf87a2032010-10-22 12:50:53 +010014047 CheckSurvivingGlobalObjectsCount(0);
Steve Blocka7e24c12009-10-30 11:49:00 +000014048 }
14049}
14050
14051
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014052TEST(CopyablePersistent) {
14053 LocalContext context;
14054 v8::Isolate* isolate = context->GetIsolate();
14055 i::GlobalHandles* globals =
14056 reinterpret_cast<i::Isolate*>(isolate)->global_handles();
14057 int initial_handles = globals->global_handles_count();
14058 typedef v8::Persistent<v8::Object, v8::CopyablePersistentTraits<v8::Object> >
14059 CopyableObject;
14060 {
14061 CopyableObject handle1;
14062 {
14063 v8::HandleScope scope(isolate);
14064 handle1.Reset(isolate, v8::Object::New(isolate));
14065 }
14066 CHECK_EQ(initial_handles + 1, globals->global_handles_count());
14067 CopyableObject handle2;
14068 handle2 = handle1;
14069 CHECK(handle1 == handle2);
14070 CHECK_EQ(initial_handles + 2, globals->global_handles_count());
14071 CopyableObject handle3(handle2);
14072 CHECK(handle1 == handle3);
14073 CHECK_EQ(initial_handles + 3, globals->global_handles_count());
14074 }
14075 // Verify autodispose
14076 CHECK_EQ(initial_handles, globals->global_handles_count());
14077}
14078
14079
14080static void WeakApiCallback(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014081 const v8::WeakCallbackInfo<Persistent<v8::Object>>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014082 data.GetParameter()->Reset();
14083 delete data.GetParameter();
14084}
14085
14086
14087TEST(WeakCallbackApi) {
14088 LocalContext context;
14089 v8::Isolate* isolate = context->GetIsolate();
14090 i::GlobalHandles* globals =
14091 reinterpret_cast<i::Isolate*>(isolate)->global_handles();
14092 int initial_handles = globals->global_handles_count();
14093 {
14094 v8::HandleScope scope(isolate);
14095 v8::Local<v8::Object> obj = v8::Object::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014096 CHECK(
14097 obj->Set(context.local(), v8_str("key"), v8::Integer::New(isolate, 231))
14098 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014099 v8::Persistent<v8::Object>* handle =
14100 new v8::Persistent<v8::Object>(isolate, obj);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014101 handle->SetWeak<v8::Persistent<v8::Object>>(
14102 handle, WeakApiCallback, v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014103 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014104 reinterpret_cast<i::Isolate*>(isolate)->heap()->CollectAllGarbage(
14105 i::Heap::kAbortIncrementalMarkingMask);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014106 // Verify disposed.
14107 CHECK_EQ(initial_handles, globals->global_handles_count());
14108}
14109
14110
Steve Blocka7e24c12009-10-30 11:49:00 +000014111v8::Persistent<v8::Object> some_object;
14112v8::Persistent<v8::Object> bad_handle;
14113
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014114
14115void NewPersistentHandleCallback2(
14116 const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014117 v8::HandleScope scope(data.GetIsolate());
14118 bad_handle.Reset(data.GetIsolate(), some_object);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014119}
14120
14121
14122void NewPersistentHandleCallback1(
14123 const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014124 data.GetParameter()->Reset();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014125 data.SetSecondPassCallback(NewPersistentHandleCallback2);
Steve Blocka7e24c12009-10-30 11:49:00 +000014126}
14127
14128
14129THREADED_TEST(NewPersistentHandleFromWeakCallback) {
14130 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014131 v8::Isolate* isolate = context->GetIsolate();
Steve Blocka7e24c12009-10-30 11:49:00 +000014132
14133 v8::Persistent<v8::Object> handle1, handle2;
14134 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014135 v8::HandleScope scope(isolate);
14136 some_object.Reset(isolate, v8::Object::New(isolate));
14137 handle1.Reset(isolate, v8::Object::New(isolate));
14138 handle2.Reset(isolate, v8::Object::New(isolate));
Steve Blocka7e24c12009-10-30 11:49:00 +000014139 }
14140 // Note: order is implementation dependent alas: currently
14141 // global handle nodes are processed by PostGarbageCollectionProcessing
14142 // in reverse allocation order, so if second allocated handle is deleted,
14143 // weak callback of the first handle would be able to 'reallocate' it.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014144 handle1.SetWeak(&handle1, NewPersistentHandleCallback1,
14145 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014146 handle2.Reset();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014147 CcTest::heap()->CollectAllGarbage();
Steve Blocka7e24c12009-10-30 11:49:00 +000014148}
14149
14150
14151v8::Persistent<v8::Object> to_be_disposed;
14152
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014153
14154void DisposeAndForceGcCallback2(
14155 const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014156 to_be_disposed.Reset();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014157 CcTest::heap()->CollectAllGarbage();
14158}
14159
14160
14161void DisposeAndForceGcCallback1(
14162 const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014163 data.GetParameter()->Reset();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014164 data.SetSecondPassCallback(DisposeAndForceGcCallback2);
Steve Blocka7e24c12009-10-30 11:49:00 +000014165}
14166
14167
14168THREADED_TEST(DoNotUseDeletedNodesInSecondLevelGc) {
14169 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014170 v8::Isolate* isolate = context->GetIsolate();
Steve Blocka7e24c12009-10-30 11:49:00 +000014171
14172 v8::Persistent<v8::Object> handle1, handle2;
14173 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014174 v8::HandleScope scope(isolate);
14175 handle1.Reset(isolate, v8::Object::New(isolate));
14176 handle2.Reset(isolate, v8::Object::New(isolate));
Steve Blocka7e24c12009-10-30 11:49:00 +000014177 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014178 handle1.SetWeak(&handle1, DisposeAndForceGcCallback1,
14179 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014180 to_be_disposed.Reset(isolate, handle2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014181 CcTest::heap()->CollectAllGarbage();
Steve Blocka7e24c12009-10-30 11:49:00 +000014182}
14183
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014184void DisposingCallback(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014185 const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014186 data.GetParameter()->Reset();
Steve Blockd0582a62009-12-15 09:54:21 +000014187}
14188
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014189void HandleCreatingCallback2(
14190 const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014191 v8::HandleScope scope(data.GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014192 v8::Global<v8::Object>(data.GetIsolate(), v8::Object::New(data.GetIsolate()));
14193}
14194
14195
14196void HandleCreatingCallback1(
14197 const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014198 data.GetParameter()->Reset();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014199 data.SetSecondPassCallback(HandleCreatingCallback2);
Steve Blockd0582a62009-12-15 09:54:21 +000014200}
14201
14202
14203THREADED_TEST(NoGlobalHandlesOrphaningDueToWeakCallback) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014204 v8::Locker locker(CcTest::isolate());
Steve Blockd0582a62009-12-15 09:54:21 +000014205 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014206 v8::Isolate* isolate = context->GetIsolate();
Steve Blockd0582a62009-12-15 09:54:21 +000014207
14208 v8::Persistent<v8::Object> handle1, handle2, handle3;
14209 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014210 v8::HandleScope scope(isolate);
14211 handle3.Reset(isolate, v8::Object::New(isolate));
14212 handle2.Reset(isolate, v8::Object::New(isolate));
14213 handle1.Reset(isolate, v8::Object::New(isolate));
Steve Blockd0582a62009-12-15 09:54:21 +000014214 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014215 handle2.SetWeak(&handle2, DisposingCallback,
14216 v8::WeakCallbackType::kParameter);
14217 handle3.SetWeak(&handle3, HandleCreatingCallback1,
14218 v8::WeakCallbackType::kParameter);
14219 CcTest::heap()->CollectAllGarbage();
14220 EmptyMessageQueues(isolate);
Steve Blockd0582a62009-12-15 09:54:21 +000014221}
14222
Steve Blocka7e24c12009-10-30 11:49:00 +000014223
14224THREADED_TEST(CheckForCrossContextObjectLiterals) {
14225 v8::V8::Initialize();
14226
14227 const int nof = 2;
14228 const char* sources[nof] = {
14229 "try { [ 2, 3, 4 ].forEach(5); } catch(e) { e.toString(); }",
14230 "Object()"
14231 };
14232
14233 for (int i = 0; i < nof; i++) {
14234 const char* source = sources[i];
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014235 { v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000014236 LocalContext context;
14237 CompileRun(source);
14238 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014239 { v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000014240 LocalContext context;
14241 CompileRun(source);
14242 }
14243 }
14244}
14245
14246
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014247static v8::Local<Value> NestedScope(v8::Local<Context> env) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014248 v8::EscapableHandleScope inner(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000014249 env->Enter();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014250 v8::Local<Value> three = v8_num(3);
14251 v8::Local<Value> value = inner.Escape(three);
Steve Blocka7e24c12009-10-30 11:49:00 +000014252 env->Exit();
14253 return value;
14254}
14255
14256
14257THREADED_TEST(NestedHandleScopeAndContexts) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014258 v8::Isolate* isolate = CcTest::isolate();
14259 v8::HandleScope outer(isolate);
14260 v8::Local<Context> env = Context::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000014261 env->Enter();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014262 v8::Local<Value> value = NestedScope(env);
14263 v8::Local<String> str(value->ToString(env).ToLocalChecked());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010014264 CHECK(!str.IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +000014265 env->Exit();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014266}
14267
14268
14269static bool MatchPointers(void* key1, void* key2) {
14270 return key1 == key2;
14271}
14272
14273
14274struct SymbolInfo {
14275 size_t id;
14276 size_t size;
14277 std::string name;
14278};
14279
14280
14281class SetFunctionEntryHookTest {
14282 public:
14283 SetFunctionEntryHookTest() {
14284 CHECK(instance_ == NULL);
14285 instance_ = this;
14286 }
14287 ~SetFunctionEntryHookTest() {
14288 CHECK(instance_ == this);
14289 instance_ = NULL;
14290 }
14291 void Reset() {
14292 symbols_.clear();
14293 symbol_locations_.clear();
14294 invocations_.clear();
14295 }
14296 void RunTest();
14297 void OnJitEvent(const v8::JitCodeEvent* event);
14298 static void JitEvent(const v8::JitCodeEvent* event) {
14299 CHECK(instance_ != NULL);
14300 instance_->OnJitEvent(event);
14301 }
14302
14303 void OnEntryHook(uintptr_t function,
14304 uintptr_t return_addr_location);
14305 static void EntryHook(uintptr_t function,
14306 uintptr_t return_addr_location) {
14307 CHECK(instance_ != NULL);
14308 instance_->OnEntryHook(function, return_addr_location);
14309 }
14310
14311 static void RuntimeCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
14312 CHECK(instance_ != NULL);
14313 args.GetReturnValue().Set(v8_num(42));
14314 }
14315 void RunLoopInNewEnv(v8::Isolate* isolate);
14316
14317 // Records addr as location of symbol.
14318 void InsertSymbolAt(i::Address addr, SymbolInfo* symbol);
14319
14320 // Finds the symbol containing addr
14321 SymbolInfo* FindSymbolForAddr(i::Address addr);
14322 // Returns the number of invocations where the caller name contains
14323 // \p caller_name and the function name contains \p function_name.
14324 int CountInvocations(const char* caller_name,
14325 const char* function_name);
14326
14327 i::Handle<i::JSFunction> foo_func_;
14328 i::Handle<i::JSFunction> bar_func_;
14329
14330 typedef std::map<size_t, SymbolInfo> SymbolMap;
14331 typedef std::map<i::Address, SymbolInfo*> SymbolLocationMap;
14332 typedef std::map<std::pair<SymbolInfo*, SymbolInfo*>, int> InvocationMap;
14333 SymbolMap symbols_;
14334 SymbolLocationMap symbol_locations_;
14335 InvocationMap invocations_;
14336
14337 static SetFunctionEntryHookTest* instance_;
14338};
14339SetFunctionEntryHookTest* SetFunctionEntryHookTest::instance_ = NULL;
14340
14341
14342// Returns true if addr is in the range [start, start+len).
14343static bool Overlaps(i::Address start, size_t len, i::Address addr) {
14344 if (start <= addr && start + len > addr)
14345 return true;
14346
14347 return false;
14348}
14349
14350void SetFunctionEntryHookTest::InsertSymbolAt(i::Address addr,
14351 SymbolInfo* symbol) {
14352 // Insert the symbol at the new location.
14353 SymbolLocationMap::iterator it =
14354 symbol_locations_.insert(std::make_pair(addr, symbol)).first;
14355 // Now erase symbols to the left and right that overlap this one.
14356 while (it != symbol_locations_.begin()) {
14357 SymbolLocationMap::iterator left = it;
14358 --left;
14359 if (!Overlaps(left->first, left->second->size, addr))
14360 break;
14361 symbol_locations_.erase(left);
14362 }
14363
14364 // Now erase symbols to the left and right that overlap this one.
14365 while (true) {
14366 SymbolLocationMap::iterator right = it;
14367 ++right;
14368 if (right == symbol_locations_.end())
14369 break;
14370 if (!Overlaps(addr, symbol->size, right->first))
14371 break;
14372 symbol_locations_.erase(right);
14373 }
14374}
14375
14376
14377void SetFunctionEntryHookTest::OnJitEvent(const v8::JitCodeEvent* event) {
14378 switch (event->type) {
14379 case v8::JitCodeEvent::CODE_ADDED: {
14380 CHECK(event->code_start != NULL);
14381 CHECK_NE(0, static_cast<int>(event->code_len));
14382 CHECK(event->name.str != NULL);
14383 size_t symbol_id = symbols_.size();
14384
14385 // Record the new symbol.
14386 SymbolInfo& info = symbols_[symbol_id];
14387 info.id = symbol_id;
14388 info.size = event->code_len;
14389 info.name.assign(event->name.str, event->name.str + event->name.len);
14390
14391 // And record it's location.
14392 InsertSymbolAt(reinterpret_cast<i::Address>(event->code_start), &info);
14393 }
14394 break;
14395
14396 case v8::JitCodeEvent::CODE_MOVED: {
14397 // We would like to never see code move that we haven't seen before,
14398 // but the code creation event does not happen until the line endings
14399 // have been calculated (this is so that we can report the line in the
14400 // script at which the function source is found, see
14401 // Compiler::RecordFunctionCompilation) and the line endings
14402 // calculations can cause a GC, which can move the newly created code
14403 // before its existence can be logged.
14404 SymbolLocationMap::iterator it(
14405 symbol_locations_.find(
14406 reinterpret_cast<i::Address>(event->code_start)));
14407 if (it != symbol_locations_.end()) {
14408 // Found a symbol at this location, move it.
14409 SymbolInfo* info = it->second;
14410 symbol_locations_.erase(it);
14411 InsertSymbolAt(reinterpret_cast<i::Address>(event->new_code_start),
14412 info);
14413 }
14414 }
14415 default:
14416 break;
14417 }
14418}
14419
14420void SetFunctionEntryHookTest::OnEntryHook(
14421 uintptr_t function, uintptr_t return_addr_location) {
14422 // Get the function's code object.
14423 i::Code* function_code = i::Code::GetCodeFromTargetAddress(
14424 reinterpret_cast<i::Address>(function));
14425 CHECK(function_code != NULL);
14426
14427 // Then try and look up the caller's code object.
14428 i::Address caller = *reinterpret_cast<i::Address*>(return_addr_location);
14429
14430 // Count the invocation.
14431 SymbolInfo* caller_symbol = FindSymbolForAddr(caller);
14432 SymbolInfo* function_symbol =
14433 FindSymbolForAddr(reinterpret_cast<i::Address>(function));
14434 ++invocations_[std::make_pair(caller_symbol, function_symbol)];
14435
14436 if (!bar_func_.is_null() && function_code == bar_func_->code()) {
14437 // Check that we have a symbol for the "bar" function at the right location.
14438 SymbolLocationMap::iterator it(
14439 symbol_locations_.find(function_code->instruction_start()));
14440 CHECK(it != symbol_locations_.end());
14441 }
14442
14443 if (!foo_func_.is_null() && function_code == foo_func_->code()) {
14444 // Check that we have a symbol for "foo" at the right location.
14445 SymbolLocationMap::iterator it(
14446 symbol_locations_.find(function_code->instruction_start()));
14447 CHECK(it != symbol_locations_.end());
14448 }
14449}
14450
14451
14452SymbolInfo* SetFunctionEntryHookTest::FindSymbolForAddr(i::Address addr) {
14453 SymbolLocationMap::iterator it(symbol_locations_.lower_bound(addr));
14454 // Do we have a direct hit on a symbol?
14455 if (it != symbol_locations_.end()) {
14456 if (it->first == addr)
14457 return it->second;
14458 }
14459
14460 // If not a direct hit, it'll have to be the previous symbol.
14461 if (it == symbol_locations_.begin())
14462 return NULL;
14463
14464 --it;
14465 size_t offs = addr - it->first;
14466 if (offs < it->second->size)
14467 return it->second;
14468
14469 return NULL;
14470}
14471
14472
14473int SetFunctionEntryHookTest::CountInvocations(
14474 const char* caller_name, const char* function_name) {
14475 InvocationMap::iterator it(invocations_.begin());
14476 int invocations = 0;
14477 for (; it != invocations_.end(); ++it) {
14478 SymbolInfo* caller = it->first.first;
14479 SymbolInfo* function = it->first.second;
14480
14481 // Filter out non-matching functions.
14482 if (function_name != NULL) {
14483 if (function->name.find(function_name) == std::string::npos)
14484 continue;
14485 }
14486
14487 // Filter out non-matching callers.
14488 if (caller_name != NULL) {
14489 if (caller == NULL)
14490 continue;
14491 if (caller->name.find(caller_name) == std::string::npos)
14492 continue;
14493 }
14494
14495 // It matches add the invocation count to the tally.
14496 invocations += it->second;
14497 }
14498
14499 return invocations;
14500}
14501
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014502void SetFunctionEntryHookTest::RunLoopInNewEnv(v8::Isolate* isolate) {
14503 v8::HandleScope outer(isolate);
14504 v8::Local<Context> env = Context::New(isolate);
14505 env->Enter();
14506
14507 Local<ObjectTemplate> t = ObjectTemplate::New(isolate);
14508 t->Set(v8_str("asdf"), v8::FunctionTemplate::New(isolate, RuntimeCallback));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014509 CHECK(env->Global()
14510 ->Set(env, v8_str("obj"), t->NewInstance(env).ToLocalChecked())
14511 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014512
14513 const char* script =
14514 "function bar() {\n"
14515 " var sum = 0;\n"
14516 " for (i = 0; i < 100; ++i)\n"
14517 " sum = foo(i);\n"
14518 " return sum;\n"
14519 "}\n"
14520 "function foo(i) { return i * i; }\n"
14521 "// Invoke on the runtime function.\n"
14522 "obj.asdf()";
14523 CompileRun(script);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014524 bar_func_ = i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(
14525 *env->Global()->Get(env, v8_str("bar")).ToLocalChecked()));
14526 CHECK(!bar_func_.is_null());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014527
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014528 foo_func_ = i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(
14529 *env->Global()->Get(env, v8_str("foo")).ToLocalChecked()));
14530 CHECK(!foo_func_.is_null());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014531
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014532 v8::Local<v8::Value> value = CompileRun("bar();");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014533 CHECK(value->IsNumber());
14534 CHECK_EQ(9801.0, v8::Number::Cast(*value)->Value());
14535
14536 // Test the optimized codegen path.
14537 value = CompileRun("%OptimizeFunctionOnNextCall(foo);"
14538 "bar();");
14539 CHECK(value->IsNumber());
14540 CHECK_EQ(9801.0, v8::Number::Cast(*value)->Value());
14541
14542 env->Exit();
14543}
14544
14545
14546void SetFunctionEntryHookTest::RunTest() {
14547 // Work in a new isolate throughout.
14548 v8::Isolate::CreateParams create_params;
14549 create_params.entry_hook = EntryHook;
14550 create_params.code_event_handler = JitEvent;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014551 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014552 v8::Isolate* isolate = v8::Isolate::New(create_params);
14553
14554 {
14555 v8::Isolate::Scope scope(isolate);
14556
14557 RunLoopInNewEnv(isolate);
14558
Ben Murdochc5610432016-08-08 18:44:38 +010014559 // Check the expected invocation counts.
14560 if (!i::FLAG_ignition) {
14561 CHECK_EQ(2, CountInvocations(NULL, "bar"));
14562 CHECK_EQ(200, CountInvocations("bar", "foo"));
14563 CHECK_EQ(200, CountInvocations(NULL, "foo"));
14564 } else {
14565 // For ignition we don't see the actual functions being called, instead
14566 // we see the IterpreterEntryTrampoline at least 102 times
14567 // (100 unoptimized calls to foo, and 2 calls to bar).
14568 CHECK_LE(102, CountInvocations(NULL, "InterpreterEntryTrampoline"));
14569 // We should also see the calls to the optimized function foo.
14570 CHECK_EQ(100, CountInvocations(NULL, "foo"));
14571 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014572
14573 // Verify that we have an entry hook on some specific stubs.
14574 CHECK_NE(0, CountInvocations(NULL, "CEntryStub"));
14575 CHECK_NE(0, CountInvocations(NULL, "JSEntryStub"));
14576 CHECK_NE(0, CountInvocations(NULL, "JSEntryTrampoline"));
14577 }
14578 isolate->Dispose();
14579
14580 Reset();
14581
14582 // Make sure a second isolate is unaffected by the previous entry hook.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014583 create_params = v8::Isolate::CreateParams();
14584 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
14585 isolate = v8::Isolate::New(create_params);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014586 {
14587 v8::Isolate::Scope scope(isolate);
14588
14589 // Reset the entry count to zero and set the entry hook.
14590 RunLoopInNewEnv(isolate);
14591
14592 // We should record no invocations in this isolate.
14593 CHECK_EQ(0, static_cast<int>(invocations_.size()));
14594 }
14595
14596 isolate->Dispose();
14597}
14598
14599
14600TEST(SetFunctionEntryHook) {
14601 // FunctionEntryHook does not work well with experimental natives.
14602 // Experimental natives are compiled during snapshot deserialization.
14603 // This test breaks because InstallGetter (function from snapshot that
14604 // only gets called from experimental natives) is compiled with entry hooks.
14605 i::FLAG_allow_natives_syntax = true;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014606 i::FLAG_turbo_inlining = false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014607 i::FLAG_use_inlining = false;
14608
14609 SetFunctionEntryHookTest test;
14610 test.RunTest();
14611}
14612
14613
14614static i::HashMap* code_map = NULL;
14615static i::HashMap* jitcode_line_info = NULL;
14616static int saw_bar = 0;
14617static int move_events = 0;
14618
14619
14620static bool FunctionNameIs(const char* expected,
14621 const v8::JitCodeEvent* event) {
14622 // Log lines for functions are of the general form:
Ben Murdochda12d292016-06-02 14:46:10 +010014623 // "LazyCompile:<type><function_name>" or Function:<type><function_name>,
14624 // where the type is one of "*", "~" or "".
14625 static const char* kPreamble;
14626 if (!i::FLAG_lazy || (i::FLAG_ignition && i::FLAG_ignition_eager)) {
14627 kPreamble = "Function:";
14628 } else {
14629 kPreamble = "LazyCompile:";
14630 }
14631 static size_t kPreambleLen = strlen(kPreamble);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014632
Ben Murdochda12d292016-06-02 14:46:10 +010014633 if (event->name.len < kPreambleLen ||
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014634 strncmp(kPreamble, event->name.str, kPreambleLen) != 0) {
14635 return false;
14636 }
14637
14638 const char* tail = event->name.str + kPreambleLen;
14639 size_t tail_len = event->name.len - kPreambleLen;
14640 size_t expected_len = strlen(expected);
14641 if (tail_len > 1 && (*tail == '*' || *tail == '~')) {
14642 --tail_len;
14643 ++tail;
14644 }
14645
14646 // Check for tails like 'bar :1'.
14647 if (tail_len > expected_len + 2 &&
14648 tail[expected_len] == ' ' &&
14649 tail[expected_len + 1] == ':' &&
14650 tail[expected_len + 2] &&
14651 !strncmp(tail, expected, expected_len)) {
14652 return true;
14653 }
14654
14655 if (tail_len != expected_len)
14656 return false;
14657
14658 return strncmp(tail, expected, expected_len) == 0;
14659}
14660
14661
14662static void event_handler(const v8::JitCodeEvent* event) {
14663 CHECK(event != NULL);
14664 CHECK(code_map != NULL);
14665 CHECK(jitcode_line_info != NULL);
14666
14667 class DummyJitCodeLineInfo {
14668 };
14669
14670 switch (event->type) {
14671 case v8::JitCodeEvent::CODE_ADDED: {
14672 CHECK(event->code_start != NULL);
14673 CHECK_NE(0, static_cast<int>(event->code_len));
14674 CHECK(event->name.str != NULL);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014675 i::HashMap::Entry* entry = code_map->LookupOrInsert(
14676 event->code_start, i::ComputePointerHash(event->code_start));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014677 entry->value = reinterpret_cast<void*>(event->code_len);
14678
14679 if (FunctionNameIs("bar", event)) {
14680 ++saw_bar;
14681 }
14682 }
14683 break;
14684
14685 case v8::JitCodeEvent::CODE_MOVED: {
14686 uint32_t hash = i::ComputePointerHash(event->code_start);
14687 // We would like to never see code move that we haven't seen before,
14688 // but the code creation event does not happen until the line endings
14689 // have been calculated (this is so that we can report the line in the
14690 // script at which the function source is found, see
14691 // Compiler::RecordFunctionCompilation) and the line endings
14692 // calculations can cause a GC, which can move the newly created code
14693 // before its existence can be logged.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014694 i::HashMap::Entry* entry = code_map->Lookup(event->code_start, hash);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014695 if (entry != NULL) {
14696 ++move_events;
14697
14698 CHECK_EQ(reinterpret_cast<void*>(event->code_len), entry->value);
14699 code_map->Remove(event->code_start, hash);
14700
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014701 entry = code_map->LookupOrInsert(
14702 event->new_code_start,
14703 i::ComputePointerHash(event->new_code_start));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014704 entry->value = reinterpret_cast<void*>(event->code_len);
14705 }
14706 }
14707 break;
14708
14709 case v8::JitCodeEvent::CODE_REMOVED:
14710 // Object/code removal events are currently not dispatched from the GC.
14711 CHECK(false);
14712 break;
14713
14714 // For CODE_START_LINE_INFO_RECORDING event, we will create one
14715 // DummyJitCodeLineInfo data structure pointed by event->user_dat. We
14716 // record it in jitcode_line_info.
14717 case v8::JitCodeEvent::CODE_START_LINE_INFO_RECORDING: {
14718 DummyJitCodeLineInfo* line_info = new DummyJitCodeLineInfo();
14719 v8::JitCodeEvent* temp_event = const_cast<v8::JitCodeEvent*>(event);
14720 temp_event->user_data = line_info;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014721 i::HashMap::Entry* entry = jitcode_line_info->LookupOrInsert(
14722 line_info, i::ComputePointerHash(line_info));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014723 entry->value = reinterpret_cast<void*>(line_info);
14724 }
14725 break;
14726 // For these two events, we will check whether the event->user_data
14727 // data structure is created before during CODE_START_LINE_INFO_RECORDING
14728 // event. And delete it in CODE_END_LINE_INFO_RECORDING event handling.
14729 case v8::JitCodeEvent::CODE_END_LINE_INFO_RECORDING: {
14730 CHECK(event->user_data != NULL);
14731 uint32_t hash = i::ComputePointerHash(event->user_data);
14732 i::HashMap::Entry* entry =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014733 jitcode_line_info->Lookup(event->user_data, hash);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014734 CHECK(entry != NULL);
14735 delete reinterpret_cast<DummyJitCodeLineInfo*>(event->user_data);
14736 }
14737 break;
14738
14739 case v8::JitCodeEvent::CODE_ADD_LINE_POS_INFO: {
14740 CHECK(event->user_data != NULL);
14741 uint32_t hash = i::ComputePointerHash(event->user_data);
14742 i::HashMap::Entry* entry =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014743 jitcode_line_info->Lookup(event->user_data, hash);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014744 CHECK(entry != NULL);
14745 }
14746 break;
14747
14748 default:
14749 // Impossible event.
14750 CHECK(false);
14751 break;
14752 }
14753}
14754
14755
14756UNINITIALIZED_TEST(SetJitCodeEventHandler) {
14757 i::FLAG_stress_compaction = true;
14758 i::FLAG_incremental_marking = false;
14759 if (i::FLAG_never_compact) return;
14760 const char* script =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014761 "function bar() {"
14762 " var sum = 0;"
14763 " for (i = 0; i < 10; ++i)"
14764 " sum = foo(i);"
14765 " return sum;"
14766 "}"
14767 "function foo(i) { return i; };"
14768 "bar();";
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014769
14770 // Run this test in a new isolate to make sure we don't
14771 // have remnants of state from other code.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014772 v8::Isolate::CreateParams create_params;
14773 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
14774 v8::Isolate* isolate = v8::Isolate::New(create_params);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014775 isolate->Enter();
14776 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
14777 i::Heap* heap = i_isolate->heap();
14778
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014779 // Start with a clean slate.
14780 heap->CollectAllAvailableGarbage("TestSetJitCodeEventHandler_Prepare");
14781
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014782 {
14783 v8::HandleScope scope(isolate);
14784 i::HashMap code(MatchPointers);
14785 code_map = &code;
14786
14787 i::HashMap lineinfo(MatchPointers);
14788 jitcode_line_info = &lineinfo;
14789
14790 saw_bar = 0;
14791 move_events = 0;
14792
14793 isolate->SetJitCodeEventHandler(v8::kJitCodeEventDefault, event_handler);
14794
14795 // Generate new code objects sparsely distributed across several
14796 // different fragmented code-space pages.
14797 const int kIterations = 10;
14798 for (int i = 0; i < kIterations; ++i) {
14799 LocalContext env(isolate);
14800 i::AlwaysAllocateScope always_allocate(i_isolate);
Ben Murdochda12d292016-06-02 14:46:10 +010014801 SimulateFullSpace(i::FLAG_ignition ? heap->old_space()
14802 : heap->code_space());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014803 CompileRun(script);
14804
14805 // Keep a strong reference to the code object in the handle scope.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014806 i::Handle<i::Code> bar_code(
14807 i::Handle<i::JSFunction>::cast(
14808 v8::Utils::OpenHandle(*env->Global()
14809 ->Get(env.local(), v8_str("bar"))
14810 .ToLocalChecked()))
14811 ->code());
14812 i::Handle<i::Code> foo_code(
14813 i::Handle<i::JSFunction>::cast(
14814 v8::Utils::OpenHandle(*env->Global()
14815 ->Get(env.local(), v8_str("foo"))
14816 .ToLocalChecked()))
14817 ->code());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014818
14819 // Clear the compilation cache to get more wastage.
14820 reinterpret_cast<i::Isolate*>(isolate)->compilation_cache()->Clear();
14821 }
14822
14823 // Force code movement.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014824 heap->CollectAllAvailableGarbage("TestSetJitCodeEventHandler_Move");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014825
14826 isolate->SetJitCodeEventHandler(v8::kJitCodeEventDefault, NULL);
14827
14828 CHECK_LE(kIterations, saw_bar);
14829 CHECK_LT(0, move_events);
14830
14831 code_map = NULL;
14832 jitcode_line_info = NULL;
14833 }
14834
14835 isolate->Exit();
14836 isolate->Dispose();
14837
14838 // Do this in a new isolate.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014839 isolate = v8::Isolate::New(create_params);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014840 isolate->Enter();
14841
14842 // Verify that we get callbacks for existing code objects when we
14843 // request enumeration of existing code.
14844 {
14845 v8::HandleScope scope(isolate);
14846 LocalContext env(isolate);
14847 CompileRun(script);
14848
14849 // Now get code through initial iteration.
14850 i::HashMap code(MatchPointers);
14851 code_map = &code;
14852
14853 i::HashMap lineinfo(MatchPointers);
14854 jitcode_line_info = &lineinfo;
14855
14856 isolate->SetJitCodeEventHandler(v8::kJitCodeEventEnumExisting,
14857 event_handler);
14858 isolate->SetJitCodeEventHandler(v8::kJitCodeEventDefault, NULL);
14859
14860 jitcode_line_info = NULL;
14861 // We expect that we got some events. Note that if we could get code removal
14862 // notifications, we could compare two collections, one created by listening
14863 // from the time of creation of an isolate, and the other by subscribing
14864 // with EnumExisting.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014865 CHECK_LT(0u, code.occupancy());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014866
14867 code_map = NULL;
14868 }
14869
14870 isolate->Exit();
14871 isolate->Dispose();
Steve Blocka7e24c12009-10-30 11:49:00 +000014872}
14873
14874
14875THREADED_TEST(ExternalAllocatedMemory) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014876 v8::Isolate* isolate = CcTest::isolate();
14877 v8::HandleScope outer(isolate);
14878 v8::Local<Context> env(Context::New(isolate));
Ben Murdoch3ef787d2012-04-12 10:51:47 +010014879 CHECK(!env.IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014880 const int64_t kSize = 1024*1024;
14881 int64_t baseline = isolate->AdjustAmountOfExternalAllocatedMemory(0);
14882 CHECK_EQ(baseline + kSize,
14883 isolate->AdjustAmountOfExternalAllocatedMemory(kSize));
14884 CHECK_EQ(baseline,
14885 isolate->AdjustAmountOfExternalAllocatedMemory(-kSize));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014886 const int64_t kTriggerGCSize =
14887 v8::internal::Internals::kExternalAllocationLimit + 1;
14888 CHECK_EQ(baseline + kTriggerGCSize,
14889 isolate->AdjustAmountOfExternalAllocatedMemory(kTriggerGCSize));
14890 CHECK_EQ(baseline,
14891 isolate->AdjustAmountOfExternalAllocatedMemory(-kTriggerGCSize));
14892}
14893
14894
14895TEST(Regress51719) {
14896 i::FLAG_incremental_marking = false;
14897 CcTest::InitializeVM();
14898
14899 const int64_t kTriggerGCSize =
14900 v8::internal::Internals::kExternalAllocationLimit + 1;
14901 v8::Isolate* isolate = CcTest::isolate();
14902 isolate->AdjustAmountOfExternalAllocatedMemory(kTriggerGCSize);
Steve Blocka7e24c12009-10-30 11:49:00 +000014903}
14904
14905
14906// Regression test for issue 54, object templates with internal fields
14907// but no accessors or interceptors did not get their internal field
14908// count set on instances.
14909THREADED_TEST(Regress54) {
Steve Blocka7e24c12009-10-30 11:49:00 +000014910 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014911 v8::Isolate* isolate = context->GetIsolate();
14912 v8::HandleScope outer(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000014913 static v8::Persistent<v8::ObjectTemplate> templ;
14914 if (templ.IsEmpty()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014915 v8::EscapableHandleScope inner(isolate);
14916 v8::Local<v8::ObjectTemplate> local = v8::ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000014917 local->SetInternalFieldCount(1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014918 templ.Reset(isolate, inner.Escape(local));
Steve Blocka7e24c12009-10-30 11:49:00 +000014919 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014920 v8::Local<v8::Object> result =
14921 v8::Local<v8::ObjectTemplate>::New(isolate, templ)
14922 ->NewInstance(context.local())
14923 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000014924 CHECK_EQ(1, result->InternalFieldCount());
14925}
14926
14927
14928// If part of the threaded tests, this test makes ThreadingTest fail
14929// on mac.
14930TEST(CatchStackOverflow) {
Steve Blocka7e24c12009-10-30 11:49:00 +000014931 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014932 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014933 v8::TryCatch try_catch(context->GetIsolate());
14934 v8::Local<v8::Value> result = CompileRun(
14935 "function f() {"
14936 " return f();"
14937 "}"
14938 ""
14939 "f();");
Steve Blocka7e24c12009-10-30 11:49:00 +000014940 CHECK(result.IsEmpty());
14941}
14942
14943
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014944static void CheckTryCatchSourceInfo(v8::Local<v8::Script> script,
Steve Blocka7e24c12009-10-30 11:49:00 +000014945 const char* resource_name,
14946 int line_offset) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014947 v8::HandleScope scope(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014948 v8::TryCatch try_catch(CcTest::isolate());
14949 v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
14950 CHECK(script->Run(context).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +000014951 CHECK(try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014952 v8::Local<v8::Message> message = try_catch.Message();
Steve Blocka7e24c12009-10-30 11:49:00 +000014953 CHECK(!message.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014954 CHECK_EQ(10 + line_offset, message->GetLineNumber(context).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000014955 CHECK_EQ(91, message->GetStartPosition());
14956 CHECK_EQ(92, message->GetEndPosition());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014957 CHECK_EQ(2, message->GetStartColumn(context).FromJust());
14958 CHECK_EQ(3, message->GetEndColumn(context).FromJust());
14959 v8::String::Utf8Value line(message->GetSourceLine(context).ToLocalChecked());
14960 CHECK_EQ(0, strcmp(" throw 'nirk';", *line));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014961 v8::String::Utf8Value name(message->GetScriptOrigin().ResourceName());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014962 CHECK_EQ(0, strcmp(resource_name, *name));
Steve Blocka7e24c12009-10-30 11:49:00 +000014963}
14964
14965
14966THREADED_TEST(TryCatchSourceInfo) {
Steve Blocka7e24c12009-10-30 11:49:00 +000014967 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014968 v8::HandleScope scope(context->GetIsolate());
14969 v8::Local<v8::String> source = v8_str(
Steve Blocka7e24c12009-10-30 11:49:00 +000014970 "function Foo() {\n"
14971 " return Bar();\n"
14972 "}\n"
14973 "\n"
14974 "function Bar() {\n"
14975 " return Baz();\n"
14976 "}\n"
14977 "\n"
14978 "function Baz() {\n"
14979 " throw 'nirk';\n"
14980 "}\n"
14981 "\n"
14982 "Foo();\n");
14983
14984 const char* resource_name;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014985 v8::Local<v8::Script> script;
Steve Blocka7e24c12009-10-30 11:49:00 +000014986 resource_name = "test.js";
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014987 script = CompileWithOrigin(source, resource_name);
Steve Blocka7e24c12009-10-30 11:49:00 +000014988 CheckTryCatchSourceInfo(script, resource_name, 0);
14989
14990 resource_name = "test1.js";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014991 v8::ScriptOrigin origin1(v8_str(resource_name));
14992 script =
14993 v8::Script::Compile(context.local(), source, &origin1).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000014994 CheckTryCatchSourceInfo(script, resource_name, 0);
14995
14996 resource_name = "test2.js";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014997 v8::ScriptOrigin origin2(v8_str(resource_name),
14998 v8::Integer::New(context->GetIsolate(), 7));
14999 script =
15000 v8::Script::Compile(context.local(), source, &origin2).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000015001 CheckTryCatchSourceInfo(script, resource_name, 7);
15002}
15003
15004
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015005THREADED_TEST(TryCatchSourceInfoForEOSError) {
15006 LocalContext context;
15007 v8::HandleScope scope(context->GetIsolate());
15008 v8::TryCatch try_catch(context->GetIsolate());
15009 CHECK(v8::Script::Compile(context.local(), v8_str("!\n")).IsEmpty());
15010 CHECK(try_catch.HasCaught());
15011 v8::Local<v8::Message> message = try_catch.Message();
15012 CHECK_EQ(1, message->GetLineNumber(context.local()).FromJust());
15013 CHECK_EQ(0, message->GetStartColumn(context.local()).FromJust());
15014}
15015
15016
Steve Blocka7e24c12009-10-30 11:49:00 +000015017THREADED_TEST(CompilationCache) {
Steve Blocka7e24c12009-10-30 11:49:00 +000015018 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015019 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015020 v8::Local<v8::String> source0 = v8_str("1234");
15021 v8::Local<v8::String> source1 = v8_str("1234");
15022 v8::Local<v8::Script> script0 = CompileWithOrigin(source0, "test.js");
15023 v8::Local<v8::Script> script1 = CompileWithOrigin(source1, "test.js");
15024 v8::Local<v8::Script> script2 = v8::Script::Compile(context.local(), source0)
15025 .ToLocalChecked(); // different origin
15026 CHECK_EQ(1234, script0->Run(context.local())
15027 .ToLocalChecked()
15028 ->Int32Value(context.local())
15029 .FromJust());
15030 CHECK_EQ(1234, script1->Run(context.local())
15031 .ToLocalChecked()
15032 ->Int32Value(context.local())
15033 .FromJust());
15034 CHECK_EQ(1234, script2->Run(context.local())
15035 .ToLocalChecked()
15036 ->Int32Value(context.local())
15037 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000015038}
15039
15040
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015041static void FunctionNameCallback(
15042 const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +000015043 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015044 args.GetReturnValue().Set(v8_num(42));
Steve Blocka7e24c12009-10-30 11:49:00 +000015045}
15046
15047
15048THREADED_TEST(CallbackFunctionName) {
Steve Blocka7e24c12009-10-30 11:49:00 +000015049 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015050 v8::Isolate* isolate = context->GetIsolate();
15051 v8::HandleScope scope(isolate);
15052 Local<ObjectTemplate> t = ObjectTemplate::New(isolate);
15053 t->Set(v8_str("asdf"),
15054 v8::FunctionTemplate::New(isolate, FunctionNameCallback));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015055 CHECK(context->Global()
15056 ->Set(context.local(), v8_str("obj"),
15057 t->NewInstance(context.local()).ToLocalChecked())
15058 .FromJust());
15059 v8::Local<v8::Value> value = CompileRun("obj.asdf.name");
Steve Blocka7e24c12009-10-30 11:49:00 +000015060 CHECK(value->IsString());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015061 v8::String::Utf8Value name(value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015062 CHECK_EQ(0, strcmp("asdf", *name));
Steve Blocka7e24c12009-10-30 11:49:00 +000015063}
15064
15065
15066THREADED_TEST(DateAccess) {
Steve Blocka7e24c12009-10-30 11:49:00 +000015067 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015068 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015069 v8::Local<v8::Value> date =
15070 v8::Date::New(context.local(), 1224744689038.0).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000015071 CHECK(date->IsDate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015072 CHECK_EQ(1224744689038.0, date.As<v8::Date>()->ValueOf());
Steve Blocka7e24c12009-10-30 11:49:00 +000015073}
15074
15075
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015076void CheckProperties(v8::Isolate* isolate, v8::Local<v8::Value> val,
15077 unsigned elmc, const char* elmv[]) {
15078 v8::Local<v8::Context> context = isolate->GetCurrentContext();
15079 v8::Local<v8::Object> obj = val.As<v8::Object>();
15080 v8::Local<v8::Array> props = obj->GetPropertyNames(context).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000015081 CHECK_EQ(elmc, props->Length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015082 for (unsigned i = 0; i < elmc; i++) {
15083 v8::String::Utf8Value elm(
15084 props->Get(context, v8::Integer::New(isolate, i)).ToLocalChecked());
15085 CHECK_EQ(0, strcmp(elmv[i], *elm));
Steve Blocka7e24c12009-10-30 11:49:00 +000015086 }
15087}
15088
15089
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015090void CheckOwnProperties(v8::Isolate* isolate, v8::Local<v8::Value> val,
15091 unsigned elmc, const char* elmv[]) {
15092 v8::Local<v8::Context> context = isolate->GetCurrentContext();
15093 v8::Local<v8::Object> obj = val.As<v8::Object>();
15094 v8::Local<v8::Array> props =
15095 obj->GetOwnPropertyNames(context).ToLocalChecked();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000015096 CHECK_EQ(elmc, props->Length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015097 for (unsigned i = 0; i < elmc; i++) {
15098 v8::String::Utf8Value elm(
15099 props->Get(context, v8::Integer::New(isolate, i)).ToLocalChecked());
15100 CHECK_EQ(0, strcmp(elmv[i], *elm));
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000015101 }
15102}
15103
15104
Steve Blocka7e24c12009-10-30 11:49:00 +000015105THREADED_TEST(PropertyEnumeration) {
Steve Blocka7e24c12009-10-30 11:49:00 +000015106 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015107 v8::Isolate* isolate = context->GetIsolate();
15108 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015109 v8::Local<v8::Value> obj = CompileRun(
Steve Blocka7e24c12009-10-30 11:49:00 +000015110 "var result = [];"
15111 "result[0] = {};"
15112 "result[1] = {a: 1, b: 2};"
15113 "result[2] = [1, 2, 3];"
15114 "var proto = {x: 1, y: 2, z: 3};"
15115 "var x = { __proto__: proto, w: 0, z: 1 };"
15116 "result[3] = x;"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015117 "result;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015118 v8::Local<v8::Array> elms = obj.As<v8::Array>();
15119 CHECK_EQ(4u, elms->Length());
Steve Blocka7e24c12009-10-30 11:49:00 +000015120 int elmc0 = 0;
15121 const char** elmv0 = NULL;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015122 CheckProperties(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015123 isolate,
15124 elms->Get(context.local(), v8::Integer::New(isolate, 0)).ToLocalChecked(),
15125 elmc0, elmv0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015126 CheckOwnProperties(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015127 isolate,
15128 elms->Get(context.local(), v8::Integer::New(isolate, 0)).ToLocalChecked(),
15129 elmc0, elmv0);
Steve Blocka7e24c12009-10-30 11:49:00 +000015130 int elmc1 = 2;
15131 const char* elmv1[] = {"a", "b"};
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015132 CheckProperties(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015133 isolate,
15134 elms->Get(context.local(), v8::Integer::New(isolate, 1)).ToLocalChecked(),
15135 elmc1, elmv1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015136 CheckOwnProperties(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015137 isolate,
15138 elms->Get(context.local(), v8::Integer::New(isolate, 1)).ToLocalChecked(),
15139 elmc1, elmv1);
Steve Blocka7e24c12009-10-30 11:49:00 +000015140 int elmc2 = 3;
15141 const char* elmv2[] = {"0", "1", "2"};
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015142 CheckProperties(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015143 isolate,
15144 elms->Get(context.local(), v8::Integer::New(isolate, 2)).ToLocalChecked(),
15145 elmc2, elmv2);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015146 CheckOwnProperties(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015147 isolate,
15148 elms->Get(context.local(), v8::Integer::New(isolate, 2)).ToLocalChecked(),
15149 elmc2, elmv2);
Steve Blocka7e24c12009-10-30 11:49:00 +000015150 int elmc3 = 4;
15151 const char* elmv3[] = {"w", "z", "x", "y"};
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015152 CheckProperties(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015153 isolate,
15154 elms->Get(context.local(), v8::Integer::New(isolate, 3)).ToLocalChecked(),
15155 elmc3, elmv3);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000015156 int elmc4 = 2;
15157 const char* elmv4[] = {"w", "z"};
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015158 CheckOwnProperties(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015159 isolate,
15160 elms->Get(context.local(), v8::Integer::New(isolate, 3)).ToLocalChecked(),
15161 elmc4, elmv4);
Steve Blocka7e24c12009-10-30 11:49:00 +000015162}
15163
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015164
Steve Block44f0eee2011-05-26 01:26:41 +010015165THREADED_TEST(PropertyEnumeration2) {
Steve Block44f0eee2011-05-26 01:26:41 +010015166 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015167 v8::Isolate* isolate = context->GetIsolate();
15168 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015169 v8::Local<v8::Value> obj = CompileRun(
Steve Block44f0eee2011-05-26 01:26:41 +010015170 "var result = [];"
15171 "result[0] = {};"
15172 "result[1] = {a: 1, b: 2};"
15173 "result[2] = [1, 2, 3];"
15174 "var proto = {x: 1, y: 2, z: 3};"
15175 "var x = { __proto__: proto, w: 0, z: 1 };"
15176 "result[3] = x;"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015177 "result;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015178 v8::Local<v8::Array> elms = obj.As<v8::Array>();
15179 CHECK_EQ(4u, elms->Length());
Steve Block44f0eee2011-05-26 01:26:41 +010015180 int elmc0 = 0;
15181 const char** elmv0 = NULL;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015182 CheckProperties(
15183 isolate,
15184 elms->Get(context.local(), v8::Integer::New(isolate, 0)).ToLocalChecked(),
15185 elmc0, elmv0);
Steve Block44f0eee2011-05-26 01:26:41 +010015186
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015187 v8::Local<v8::Value> val =
15188 elms->Get(context.local(), v8::Integer::New(isolate, 0)).ToLocalChecked();
15189 v8::Local<v8::Array> props =
15190 val.As<v8::Object>()->GetPropertyNames(context.local()).ToLocalChecked();
15191 CHECK_EQ(0u, props->Length());
Steve Block44f0eee2011-05-26 01:26:41 +010015192 for (uint32_t i = 0; i < props->Length(); i++) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040015193 printf("p[%u]\n", i);
Steve Block44f0eee2011-05-26 01:26:41 +010015194 }
15195}
Steve Blocka7e24c12009-10-30 11:49:00 +000015196
Steve Blocka7e24c12009-10-30 11:49:00 +000015197
15198THREADED_TEST(AccessChecksReenabledCorrectly) {
Steve Blocka7e24c12009-10-30 11:49:00 +000015199 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015200 v8::Isolate* isolate = context->GetIsolate();
15201 v8::HandleScope scope(isolate);
15202 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015203 templ->SetAccessCheckCallback(AccessAlwaysBlocked);
Steve Blocka7e24c12009-10-30 11:49:00 +000015204 templ->Set(v8_str("a"), v8_str("a"));
15205 // Add more than 8 (see kMaxFastProperties) properties
15206 // so that the constructor will force copying map.
15207 // Cannot sprintf, gcc complains unsafety.
15208 char buf[4];
15209 for (char i = '0'; i <= '9' ; i++) {
15210 buf[0] = i;
15211 for (char j = '0'; j <= '9'; j++) {
15212 buf[1] = j;
15213 for (char k = '0'; k <= '9'; k++) {
15214 buf[2] = k;
15215 buf[3] = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015216 templ->Set(v8_str(buf), v8::Number::New(isolate, k));
Steve Blocka7e24c12009-10-30 11:49:00 +000015217 }
15218 }
15219 }
15220
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015221 Local<v8::Object> instance_1 =
15222 templ->NewInstance(context.local()).ToLocalChecked();
15223 CHECK(context->Global()
15224 ->Set(context.local(), v8_str("obj_1"), instance_1)
15225 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000015226
15227 Local<Value> value_1 = CompileRun("obj_1.a");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015228 CHECK(value_1.IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +000015229
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015230 Local<v8::Object> instance_2 =
15231 templ->NewInstance(context.local()).ToLocalChecked();
15232 CHECK(context->Global()
15233 ->Set(context.local(), v8_str("obj_2"), instance_2)
15234 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000015235
15236 Local<Value> value_2 = CompileRun("obj_2.a");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015237 CHECK(value_2.IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +000015238}
15239
15240
Leon Clarkef7060e22010-06-03 12:02:55 +010015241// Tests that ScriptData can be serialized and deserialized.
15242TEST(PreCompileSerialization) {
Ben Murdochda12d292016-06-02 14:46:10 +010015243 // Producing cached parser data while parsing eagerly is not supported.
15244 if (!i::FLAG_lazy || (i::FLAG_ignition && i::FLAG_ignition_eager)) return;
15245
Leon Clarkef7060e22010-06-03 12:02:55 +010015246 v8::V8::Initialize();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015247 LocalContext env;
15248 v8::Isolate* isolate = env->GetIsolate();
15249 HandleScope handle_scope(isolate);
Leon Clarkef7060e22010-06-03 12:02:55 +010015250
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015251 i::FLAG_min_preparse_length = 0;
15252 const char* script = "function foo(a) { return a+1; }";
15253 v8::ScriptCompiler::Source source(v8_str(script));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015254 v8::ScriptCompiler::Compile(env.local(), &source,
15255 v8::ScriptCompiler::kProduceParserCache)
15256 .ToLocalChecked();
Leon Clarkef7060e22010-06-03 12:02:55 +010015257 // Serialize.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015258 const v8::ScriptCompiler::CachedData* cd = source.GetCachedData();
15259 i::byte* serialized_data = i::NewArray<i::byte>(cd->length);
15260 i::MemCopy(serialized_data, cd->data, cd->length);
Leon Clarkef7060e22010-06-03 12:02:55 +010015261
15262 // Deserialize.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015263 i::ScriptData* deserialized = new i::ScriptData(serialized_data, cd->length);
Leon Clarkef7060e22010-06-03 12:02:55 +010015264
15265 // Verify that the original is the same as the deserialized.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015266 CHECK_EQ(cd->length, deserialized->length());
15267 CHECK_EQ(0, memcmp(cd->data, deserialized->data(), cd->length));
Leon Clarkef7060e22010-06-03 12:02:55 +010015268
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015269 delete deserialized;
15270 i::DeleteArray(serialized_data);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +010015271}
15272
15273
Steve Blocka7e24c12009-10-30 11:49:00 +000015274// This tests that we do not allow dictionary load/call inline caches
15275// to use functions that have not yet been compiled. The potential
15276// problem of loading a function that has not yet been compiled can
15277// arise because we share code between contexts via the compilation
15278// cache.
15279THREADED_TEST(DictionaryICLoadedFunction) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015280 v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000015281 // Test LoadIC.
15282 for (int i = 0; i < 2; i++) {
15283 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015284 CHECK(context->Global()
15285 ->Set(context.local(), v8_str("tmp"), v8::True(CcTest::isolate()))
15286 .FromJust());
15287 context->Global()->Delete(context.local(), v8_str("tmp")).FromJust();
Steve Blocka7e24c12009-10-30 11:49:00 +000015288 CompileRun("for (var j = 0; j < 10; j++) new RegExp('');");
15289 }
15290 // Test CallIC.
15291 for (int i = 0; i < 2; i++) {
15292 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015293 CHECK(context->Global()
15294 ->Set(context.local(), v8_str("tmp"), v8::True(CcTest::isolate()))
15295 .FromJust());
15296 context->Global()->Delete(context.local(), v8_str("tmp")).FromJust();
Steve Blocka7e24c12009-10-30 11:49:00 +000015297 CompileRun("for (var j = 0; j < 10; j++) RegExp('')");
15298 }
15299}
15300
15301
15302// Test that cross-context new calls use the context of the callee to
15303// create the new JavaScript object.
15304THREADED_TEST(CrossContextNew) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015305 v8::Isolate* isolate = CcTest::isolate();
15306 v8::HandleScope scope(isolate);
15307 v8::Local<Context> context0 = Context::New(isolate);
15308 v8::Local<Context> context1 = Context::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000015309
15310 // Allow cross-domain access.
15311 Local<String> token = v8_str("<security token>");
15312 context0->SetSecurityToken(token);
15313 context1->SetSecurityToken(token);
15314
15315 // Set an 'x' property on the Object prototype and define a
15316 // constructor function in context0.
15317 context0->Enter();
15318 CompileRun("Object.prototype.x = 42; function C() {};");
15319 context0->Exit();
15320
15321 // Call the constructor function from context0 and check that the
15322 // result has the 'x' property.
15323 context1->Enter();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015324 CHECK(context1->Global()
15325 ->Set(context1, v8_str("other"), context0->Global())
15326 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000015327 Local<Value> value = CompileRun("var instance = new other.C(); instance.x");
15328 CHECK(value->IsInt32());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015329 CHECK_EQ(42, value->Int32Value(context1).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000015330 context1->Exit();
Steve Blocka7e24c12009-10-30 11:49:00 +000015331}
15332
15333
15334// Verify that we can clone an object
15335TEST(ObjectClone) {
Steve Blocka7e24c12009-10-30 11:49:00 +000015336 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015337 v8::Isolate* isolate = env->GetIsolate();
15338 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000015339
15340 const char* sample =
15341 "var rv = {};" \
15342 "rv.alpha = 'hello';" \
15343 "rv.beta = 123;" \
15344 "rv;";
15345
15346 // Create an object, verify basics.
15347 Local<Value> val = CompileRun(sample);
15348 CHECK(val->IsObject());
Steve Block6ded16b2010-05-10 14:33:55 +010015349 Local<v8::Object> obj = val.As<v8::Object>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015350 obj->Set(env.local(), v8_str("gamma"), v8_str("cloneme")).FromJust();
Steve Blocka7e24c12009-10-30 11:49:00 +000015351
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015352 CHECK(v8_str("hello")
15353 ->Equals(env.local(),
15354 obj->Get(env.local(), v8_str("alpha")).ToLocalChecked())
15355 .FromJust());
15356 CHECK(v8::Integer::New(isolate, 123)
15357 ->Equals(env.local(),
15358 obj->Get(env.local(), v8_str("beta")).ToLocalChecked())
15359 .FromJust());
15360 CHECK(v8_str("cloneme")
15361 ->Equals(env.local(),
15362 obj->Get(env.local(), v8_str("gamma")).ToLocalChecked())
15363 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000015364
15365 // Clone it.
15366 Local<v8::Object> clone = obj->Clone();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015367 CHECK(v8_str("hello")
15368 ->Equals(env.local(),
15369 clone->Get(env.local(), v8_str("alpha")).ToLocalChecked())
15370 .FromJust());
15371 CHECK(v8::Integer::New(isolate, 123)
15372 ->Equals(env.local(),
15373 clone->Get(env.local(), v8_str("beta")).ToLocalChecked())
15374 .FromJust());
15375 CHECK(v8_str("cloneme")
15376 ->Equals(env.local(),
15377 clone->Get(env.local(), v8_str("gamma")).ToLocalChecked())
15378 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000015379
15380 // Set a property on the clone, verify each object.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015381 CHECK(clone->Set(env.local(), v8_str("beta"), v8::Integer::New(isolate, 456))
15382 .FromJust());
15383 CHECK(v8::Integer::New(isolate, 123)
15384 ->Equals(env.local(),
15385 obj->Get(env.local(), v8_str("beta")).ToLocalChecked())
15386 .FromJust());
15387 CHECK(v8::Integer::New(isolate, 456)
15388 ->Equals(env.local(),
15389 clone->Get(env.local(), v8_str("beta")).ToLocalChecked())
15390 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000015391}
15392
15393
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015394class OneByteVectorResource : public v8::String::ExternalOneByteStringResource {
Steve Blocka7e24c12009-10-30 11:49:00 +000015395 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015396 explicit OneByteVectorResource(i::Vector<const char> vector)
Steve Blocka7e24c12009-10-30 11:49:00 +000015397 : data_(vector) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015398 virtual ~OneByteVectorResource() {}
Steve Blocka7e24c12009-10-30 11:49:00 +000015399 virtual size_t length() const { return data_.length(); }
15400 virtual const char* data() const { return data_.start(); }
15401 private:
15402 i::Vector<const char> data_;
15403};
15404
15405
15406class UC16VectorResource : public v8::String::ExternalStringResource {
15407 public:
15408 explicit UC16VectorResource(i::Vector<const i::uc16> vector)
15409 : data_(vector) {}
15410 virtual ~UC16VectorResource() {}
15411 virtual size_t length() const { return data_.length(); }
15412 virtual const i::uc16* data() const { return data_.start(); }
15413 private:
15414 i::Vector<const i::uc16> data_;
15415};
15416
15417
15418static void MorphAString(i::String* string,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015419 OneByteVectorResource* one_byte_resource,
Steve Blocka7e24c12009-10-30 11:49:00 +000015420 UC16VectorResource* uc16_resource) {
15421 CHECK(i::StringShape(string).IsExternal());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015422 if (string->IsOneByteRepresentation()) {
15423 // Check old map is not internalized or long.
15424 CHECK(string->map() == CcTest::heap()->external_one_byte_string_map());
Steve Blocka7e24c12009-10-30 11:49:00 +000015425 // Morph external string to be TwoByte string.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015426 string->set_map(CcTest::heap()->external_string_map());
Steve Blocka7e24c12009-10-30 11:49:00 +000015427 i::ExternalTwoByteString* morphed =
15428 i::ExternalTwoByteString::cast(string);
15429 morphed->set_resource(uc16_resource);
15430 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015431 // Check old map is not internalized or long.
15432 CHECK(string->map() == CcTest::heap()->external_string_map());
15433 // Morph external string to be one-byte string.
15434 string->set_map(CcTest::heap()->external_one_byte_string_map());
15435 i::ExternalOneByteString* morphed = i::ExternalOneByteString::cast(string);
15436 morphed->set_resource(one_byte_resource);
Steve Blocka7e24c12009-10-30 11:49:00 +000015437 }
15438}
15439
15440
15441// Test that we can still flatten a string if the components it is built up
15442// from have been turned into 16 bit strings in the mean time.
15443THREADED_TEST(MorphCompositeStringTest) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010015444 char utf_buffer[129];
Steve Blocka7e24c12009-10-30 11:49:00 +000015445 const char* c_string = "Now is the time for all good men"
15446 " to come to the aid of the party";
15447 uint16_t* two_byte_string = AsciiToTwoByteString(c_string);
15448 {
Steve Blocka7e24c12009-10-30 11:49:00 +000015449 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015450 i::Factory* factory = CcTest::i_isolate()->factory();
15451 v8::HandleScope scope(env->GetIsolate());
15452 OneByteVectorResource one_byte_resource(
Steve Blockd0582a62009-12-15 09:54:21 +000015453 i::Vector<const char>(c_string, i::StrLength(c_string)));
Steve Blocka7e24c12009-10-30 11:49:00 +000015454 UC16VectorResource uc16_resource(
Steve Blockd0582a62009-12-15 09:54:21 +000015455 i::Vector<const uint16_t>(two_byte_string,
15456 i::StrLength(c_string)));
Steve Blocka7e24c12009-10-30 11:49:00 +000015457
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015458 Local<String> lhs(
15459 v8::Utils::ToLocal(factory->NewExternalStringFromOneByte(
15460 &one_byte_resource).ToHandleChecked()));
15461 Local<String> rhs(
15462 v8::Utils::ToLocal(factory->NewExternalStringFromOneByte(
15463 &one_byte_resource).ToHandleChecked()));
Steve Blocka7e24c12009-10-30 11:49:00 +000015464
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015465 CHECK(env->Global()->Set(env.local(), v8_str("lhs"), lhs).FromJust());
15466 CHECK(env->Global()->Set(env.local(), v8_str("rhs"), rhs).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000015467
15468 CompileRun(
15469 "var cons = lhs + rhs;"
15470 "var slice = lhs.substring(1, lhs.length - 1);"
15471 "var slice_on_cons = (lhs + rhs).substring(1, lhs.length *2 - 1);");
15472
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015473 CHECK(lhs->IsOneByte());
15474 CHECK(rhs->IsOneByte());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010015475
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015476 MorphAString(*v8::Utils::OpenHandle(*lhs), &one_byte_resource,
15477 &uc16_resource);
15478 MorphAString(*v8::Utils::OpenHandle(*rhs), &one_byte_resource,
15479 &uc16_resource);
Steve Blocka7e24c12009-10-30 11:49:00 +000015480
Ben Murdoch3ef787d2012-04-12 10:51:47 +010015481 // This should UTF-8 without flattening, since everything is ASCII.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015482 Local<String> cons =
15483 v8_compile("cons")->Run(env.local()).ToLocalChecked().As<String>();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010015484 CHECK_EQ(128, cons->Utf8Length());
15485 int nchars = -1;
15486 CHECK_EQ(129, cons->WriteUtf8(utf_buffer, -1, &nchars));
15487 CHECK_EQ(128, nchars);
15488 CHECK_EQ(0, strcmp(
15489 utf_buffer,
15490 "Now is the time for all good men to come to the aid of the party"
15491 "Now is the time for all good men to come to the aid of the party"));
15492
Steve Blocka7e24c12009-10-30 11:49:00 +000015493 // Now do some stuff to make sure the strings are flattened, etc.
15494 CompileRun(
15495 "/[^a-z]/.test(cons);"
15496 "/[^a-z]/.test(slice);"
15497 "/[^a-z]/.test(slice_on_cons);");
15498 const char* expected_cons =
15499 "Now is the time for all good men to come to the aid of the party"
15500 "Now is the time for all good men to come to the aid of the party";
15501 const char* expected_slice =
15502 "ow is the time for all good men to come to the aid of the part";
15503 const char* expected_slice_on_cons =
15504 "ow is the time for all good men to come to the aid of the party"
15505 "Now is the time for all good men to come to the aid of the part";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015506 CHECK(v8_str(expected_cons)
15507 ->Equals(env.local(), env->Global()
15508 ->Get(env.local(), v8_str("cons"))
15509 .ToLocalChecked())
15510 .FromJust());
15511 CHECK(v8_str(expected_slice)
15512 ->Equals(env.local(), env->Global()
15513 ->Get(env.local(), v8_str("slice"))
15514 .ToLocalChecked())
15515 .FromJust());
15516 CHECK(v8_str(expected_slice_on_cons)
15517 ->Equals(env.local(),
15518 env->Global()
15519 ->Get(env.local(), v8_str("slice_on_cons"))
15520 .ToLocalChecked())
15521 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000015522 }
Ben Murdoch3bec4d22010-07-22 14:51:16 +010015523 i::DeleteArray(two_byte_string);
Steve Blocka7e24c12009-10-30 11:49:00 +000015524}
15525
15526
15527TEST(CompileExternalTwoByteSource) {
Steve Blocka7e24c12009-10-30 11:49:00 +000015528 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015529 v8::HandleScope scope(context->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000015530
15531 // This is a very short list of sources, which currently is to check for a
15532 // regression caused by r2703.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015533 const char* one_byte_sources[] = {
15534 "0.5",
15535 "-0.5", // This mainly testes PushBack in the Scanner.
15536 "--0.5", // This mainly testes PushBack in the Scanner.
15537 NULL};
Steve Blocka7e24c12009-10-30 11:49:00 +000015538
15539 // Compile the sources as external two byte strings.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015540 for (int i = 0; one_byte_sources[i] != NULL; i++) {
15541 uint16_t* two_byte_string = AsciiToTwoByteString(one_byte_sources[i]);
15542 TestResource* uc16_resource = new TestResource(two_byte_string);
15543 v8::Local<v8::String> source =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015544 v8::String::NewExternalTwoByte(context->GetIsolate(), uc16_resource)
15545 .ToLocalChecked();
15546 v8::Script::Compile(context.local(), source).FromMaybe(Local<Script>());
Steve Blocka7e24c12009-10-30 11:49:00 +000015547 }
15548}
15549
15550
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015551#ifndef V8_INTERPRETED_REGEXP
15552
15553struct RegExpInterruptionData {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040015554 v8::base::Atomic32 loop_count;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015555 UC16VectorResource* string_resource;
15556 v8::Persistent<v8::String> string;
15557} regexp_interruption_data;
15558
15559
15560class RegExpInterruptionThread : public v8::base::Thread {
Steve Blocka7e24c12009-10-30 11:49:00 +000015561 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015562 explicit RegExpInterruptionThread(v8::Isolate* isolate)
15563 : Thread(Options("TimeoutThread")), isolate_(isolate) {}
Steve Blocka7e24c12009-10-30 11:49:00 +000015564
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015565 virtual void Run() {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040015566 for (v8::base::NoBarrier_Store(&regexp_interruption_data.loop_count, 0);
15567 v8::base::NoBarrier_Load(&regexp_interruption_data.loop_count) < 7;
15568 v8::base::NoBarrier_AtomicIncrement(
15569 &regexp_interruption_data.loop_count, 1)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015570 // Wait a bit before requesting GC.
15571 v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(50));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015572 reinterpret_cast<i::Isolate*>(isolate_)->stack_guard()->RequestGC();
Steve Blocka7e24c12009-10-30 11:49:00 +000015573 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015574 // Wait a bit before terminating.
15575 v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(50));
15576 isolate_->TerminateExecution();
Steve Blocka7e24c12009-10-30 11:49:00 +000015577 }
Steve Blocka7e24c12009-10-30 11:49:00 +000015578
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000015579 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015580 v8::Isolate* isolate_;
Steve Blocka7e24c12009-10-30 11:49:00 +000015581};
15582
15583
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015584void RunBeforeGC(v8::Isolate* isolate, v8::GCType type,
15585 v8::GCCallbackFlags flags) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040015586 if (v8::base::NoBarrier_Load(&regexp_interruption_data.loop_count) != 2) {
15587 return;
15588 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015589 v8::HandleScope scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015590 v8::Local<v8::String> string = v8::Local<v8::String>::New(
15591 CcTest::isolate(), regexp_interruption_data.string);
15592 string->MakeExternal(regexp_interruption_data.string_resource);
Steve Blocka7e24c12009-10-30 11:49:00 +000015593}
15594
15595
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015596// Test that RegExp execution can be interrupted. Specifically, we test
15597// * interrupting with GC
15598// * turn the subject string from one-byte internal to two-byte external string
15599// * force termination
15600TEST(RegExpInterruption) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015601 LocalContext env;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015602 v8::HandleScope scope(env->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015603
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015604 RegExpInterruptionThread timeout_thread(env->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015605
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015606 env->GetIsolate()->AddGCPrologueCallback(RunBeforeGC);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015607 static const char* one_byte_content = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
15608 i::uc16* uc16_content = AsciiToTwoByteString(one_byte_content);
15609 v8::Local<v8::String> string = v8_str(one_byte_content);
15610
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015611 env->Global()->Set(env.local(), v8_str("a"), string).FromJust();
15612 regexp_interruption_data.string.Reset(env->GetIsolate(), string);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015613 regexp_interruption_data.string_resource = new UC16VectorResource(
15614 i::Vector<const i::uc16>(uc16_content, i::StrLength(one_byte_content)));
15615
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015616 v8::TryCatch try_catch(env->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015617 timeout_thread.Start();
15618
15619 CompileRun("/((a*)*)*b/.exec(a)");
15620 CHECK(try_catch.HasTerminated());
15621
15622 timeout_thread.Join();
15623
15624 regexp_interruption_data.string.Reset();
15625 i::DeleteArray(uc16_content);
15626}
15627
15628#endif // V8_INTERPRETED_REGEXP
15629
15630
15631// Test that we cannot set a property on the global object if there
Steve Blocka7e24c12009-10-30 11:49:00 +000015632// is a read-only property in the prototype chain.
15633TEST(ReadOnlyPropertyInGlobalProto) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015634 v8::Isolate* isolate = CcTest::isolate();
15635 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015636 v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000015637 LocalContext context(0, templ);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015638 v8::Local<v8::Object> global = context->Global();
15639 v8::Local<v8::Object> global_proto = v8::Local<v8::Object>::Cast(
15640 global->Get(context.local(), v8_str("__proto__")).ToLocalChecked());
15641 global_proto->DefineOwnProperty(context.local(), v8_str("x"),
15642 v8::Integer::New(isolate, 0), v8::ReadOnly)
15643 .FromJust();
15644 global_proto->DefineOwnProperty(context.local(), v8_str("y"),
15645 v8::Integer::New(isolate, 0), v8::ReadOnly)
15646 .FromJust();
Steve Blocka7e24c12009-10-30 11:49:00 +000015647 // Check without 'eval' or 'with'.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015648 v8::Local<v8::Value> res =
Steve Blocka7e24c12009-10-30 11:49:00 +000015649 CompileRun("function f() { x = 42; return x; }; f()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015650 CHECK(v8::Integer::New(isolate, 0)->Equals(context.local(), res).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000015651 // Check with 'eval'.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015652 res = CompileRun("function f() { eval('1'); y = 43; return y; }; f()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015653 CHECK(v8::Integer::New(isolate, 0)->Equals(context.local(), res).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000015654 // Check with 'with'.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015655 res = CompileRun("function f() { with (this) { y = 44 }; return y; }; f()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015656 CHECK(v8::Integer::New(isolate, 0)->Equals(context.local(), res).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000015657}
15658
Steve Blocka7e24c12009-10-30 11:49:00 +000015659
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015660TEST(CreateDataProperty) {
15661 LocalContext env;
15662 v8::Isolate* isolate = env->GetIsolate();
15663 v8::HandleScope handle_scope(isolate);
15664
15665 CompileRun(
15666 "var a = {};"
15667 "var b = [];"
15668 "Object.defineProperty(a, 'foo', {value: 23});"
15669 "Object.defineProperty(a, 'bar', {value: 23, configurable: true});");
15670
15671 v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(
15672 env->Global()->Get(env.local(), v8_str("a")).ToLocalChecked());
15673 v8::Local<v8::Array> arr = v8::Local<v8::Array>::Cast(
15674 env->Global()->Get(env.local(), v8_str("b")).ToLocalChecked());
15675 {
15676 // Can't change a non-configurable properties.
15677 v8::TryCatch try_catch(isolate);
15678 CHECK(!obj->CreateDataProperty(env.local(), v8_str("foo"),
15679 v8::Integer::New(isolate, 42)).FromJust());
15680 CHECK(!try_catch.HasCaught());
15681 CHECK(obj->CreateDataProperty(env.local(), v8_str("bar"),
15682 v8::Integer::New(isolate, 42)).FromJust());
15683 CHECK(!try_catch.HasCaught());
15684 v8::Local<v8::Value> val =
15685 obj->Get(env.local(), v8_str("bar")).ToLocalChecked();
15686 CHECK(val->IsNumber());
15687 CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000015688 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015689
15690 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015691 // Set a regular property.
15692 v8::TryCatch try_catch(isolate);
15693 CHECK(obj->CreateDataProperty(env.local(), v8_str("blub"),
15694 v8::Integer::New(isolate, 42)).FromJust());
15695 CHECK(!try_catch.HasCaught());
15696 v8::Local<v8::Value> val =
15697 obj->Get(env.local(), v8_str("blub")).ToLocalChecked();
15698 CHECK(val->IsNumber());
15699 CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
15700 }
15701
15702 {
15703 // Set an indexed property.
15704 v8::TryCatch try_catch(isolate);
15705 CHECK(obj->CreateDataProperty(env.local(), v8_str("1"),
15706 v8::Integer::New(isolate, 42)).FromJust());
15707 CHECK(!try_catch.HasCaught());
15708 v8::Local<v8::Value> val = obj->Get(env.local(), 1).ToLocalChecked();
15709 CHECK(val->IsNumber());
15710 CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
15711 }
15712
15713 {
15714 // Special cases for arrays.
15715 v8::TryCatch try_catch(isolate);
15716 CHECK(!arr->CreateDataProperty(env.local(), v8_str("length"),
15717 v8::Integer::New(isolate, 1)).FromJust());
15718 CHECK(!try_catch.HasCaught());
15719 }
15720 {
15721 // Special cases for arrays: index exceeds the array's length
15722 v8::TryCatch try_catch(isolate);
15723 CHECK(arr->CreateDataProperty(env.local(), 1, v8::Integer::New(isolate, 23))
15724 .FromJust());
15725 CHECK(!try_catch.HasCaught());
15726 CHECK_EQ(2U, arr->Length());
15727 v8::Local<v8::Value> val = arr->Get(env.local(), 1).ToLocalChecked();
15728 CHECK(val->IsNumber());
15729 CHECK_EQ(23.0, val->NumberValue(env.local()).FromJust());
15730
15731 // Set an existing entry.
15732 CHECK(arr->CreateDataProperty(env.local(), 0, v8::Integer::New(isolate, 42))
15733 .FromJust());
15734 CHECK(!try_catch.HasCaught());
15735 val = arr->Get(env.local(), 0).ToLocalChecked();
15736 CHECK(val->IsNumber());
15737 CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
15738 }
15739
15740 CompileRun("Object.freeze(a);");
15741 {
15742 // Can't change non-extensible objects.
15743 v8::TryCatch try_catch(isolate);
15744 CHECK(!obj->CreateDataProperty(env.local(), v8_str("baz"),
15745 v8::Integer::New(isolate, 42)).FromJust());
15746 CHECK(!try_catch.HasCaught());
15747 }
15748
15749 v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
15750 templ->SetAccessCheckCallback(AccessAlwaysBlocked);
15751 v8::Local<v8::Object> access_checked =
15752 templ->NewInstance(env.local()).ToLocalChecked();
15753 {
15754 v8::TryCatch try_catch(isolate);
15755 CHECK(access_checked->CreateDataProperty(env.local(), v8_str("foo"),
15756 v8::Integer::New(isolate, 42))
15757 .IsNothing());
15758 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015759 }
15760}
15761
15762
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015763TEST(DefineOwnProperty) {
15764 LocalContext env;
15765 v8::Isolate* isolate = env->GetIsolate();
15766 v8::HandleScope handle_scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000015767
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015768 CompileRun(
15769 "var a = {};"
15770 "var b = [];"
15771 "Object.defineProperty(a, 'foo', {value: 23});"
15772 "Object.defineProperty(a, 'bar', {value: 23, configurable: true});");
Steve Blocka7e24c12009-10-30 11:49:00 +000015773
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015774 v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(
15775 env->Global()->Get(env.local(), v8_str("a")).ToLocalChecked());
15776 v8::Local<v8::Array> arr = v8::Local<v8::Array>::Cast(
15777 env->Global()->Get(env.local(), v8_str("b")).ToLocalChecked());
15778 {
15779 // Can't change a non-configurable properties.
15780 v8::TryCatch try_catch(isolate);
15781 CHECK(!obj->DefineOwnProperty(env.local(), v8_str("foo"),
15782 v8::Integer::New(isolate, 42)).FromJust());
15783 CHECK(!try_catch.HasCaught());
15784 CHECK(obj->DefineOwnProperty(env.local(), v8_str("bar"),
15785 v8::Integer::New(isolate, 42)).FromJust());
15786 CHECK(!try_catch.HasCaught());
15787 v8::Local<v8::Value> val =
15788 obj->Get(env.local(), v8_str("bar")).ToLocalChecked();
15789 CHECK(val->IsNumber());
15790 CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
15791 }
15792
15793 {
15794 // Set a regular property.
15795 v8::TryCatch try_catch(isolate);
15796 CHECK(obj->DefineOwnProperty(env.local(), v8_str("blub"),
15797 v8::Integer::New(isolate, 42)).FromJust());
15798 CHECK(!try_catch.HasCaught());
15799 v8::Local<v8::Value> val =
15800 obj->Get(env.local(), v8_str("blub")).ToLocalChecked();
15801 CHECK(val->IsNumber());
15802 CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
15803 }
15804
15805 {
15806 // Set an indexed property.
15807 v8::TryCatch try_catch(isolate);
15808 CHECK(obj->DefineOwnProperty(env.local(), v8_str("1"),
15809 v8::Integer::New(isolate, 42)).FromJust());
15810 CHECK(!try_catch.HasCaught());
15811 v8::Local<v8::Value> val = obj->Get(env.local(), 1).ToLocalChecked();
15812 CHECK(val->IsNumber());
15813 CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
15814 }
15815
15816 {
15817 // Special cases for arrays.
15818 v8::TryCatch try_catch(isolate);
15819 CHECK(!arr->DefineOwnProperty(env.local(), v8_str("length"),
15820 v8::Integer::New(isolate, 1)).FromJust());
15821 CHECK(!try_catch.HasCaught());
15822 }
15823 {
15824 // Special cases for arrays: index exceeds the array's length
15825 v8::TryCatch try_catch(isolate);
15826 CHECK(arr->DefineOwnProperty(env.local(), v8_str("1"),
15827 v8::Integer::New(isolate, 23)).FromJust());
15828 CHECK(!try_catch.HasCaught());
15829 CHECK_EQ(2U, arr->Length());
15830 v8::Local<v8::Value> val = arr->Get(env.local(), 1).ToLocalChecked();
15831 CHECK(val->IsNumber());
15832 CHECK_EQ(23.0, val->NumberValue(env.local()).FromJust());
15833
15834 // Set an existing entry.
15835 CHECK(arr->DefineOwnProperty(env.local(), v8_str("0"),
15836 v8::Integer::New(isolate, 42)).FromJust());
15837 CHECK(!try_catch.HasCaught());
15838 val = arr->Get(env.local(), 0).ToLocalChecked();
15839 CHECK(val->IsNumber());
15840 CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
15841 }
15842
15843 {
15844 // Set a non-writable property.
15845 v8::TryCatch try_catch(isolate);
15846 CHECK(obj->DefineOwnProperty(env.local(), v8_str("lala"),
15847 v8::Integer::New(isolate, 42),
15848 v8::ReadOnly).FromJust());
15849 CHECK(!try_catch.HasCaught());
15850 v8::Local<v8::Value> val =
15851 obj->Get(env.local(), v8_str("lala")).ToLocalChecked();
15852 CHECK(val->IsNumber());
15853 CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
15854 CHECK_EQ(v8::ReadOnly, obj->GetPropertyAttributes(
15855 env.local(), v8_str("lala")).FromJust());
15856 CHECK(!try_catch.HasCaught());
15857 }
15858
15859 CompileRun("Object.freeze(a);");
15860 {
15861 // Can't change non-extensible objects.
15862 v8::TryCatch try_catch(isolate);
15863 CHECK(!obj->DefineOwnProperty(env.local(), v8_str("baz"),
15864 v8::Integer::New(isolate, 42)).FromJust());
15865 CHECK(!try_catch.HasCaught());
15866 }
15867
15868 v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
15869 templ->SetAccessCheckCallback(AccessAlwaysBlocked);
15870 v8::Local<v8::Object> access_checked =
15871 templ->NewInstance(env.local()).ToLocalChecked();
15872 {
15873 v8::TryCatch try_catch(isolate);
15874 CHECK(access_checked->DefineOwnProperty(env.local(), v8_str("foo"),
15875 v8::Integer::New(isolate, 42))
15876 .IsNothing());
15877 CHECK(try_catch.HasCaught());
15878 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015879}
15880
15881
15882THREADED_TEST(GetCurrentContextWhenNotInContext) {
15883 i::Isolate* isolate = CcTest::i_isolate();
15884 CHECK(isolate != NULL);
15885 CHECK(isolate->context() == NULL);
15886 v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
15887 v8::HandleScope scope(v8_isolate);
15888 // The following should not crash, but return an empty handle.
15889 v8::Local<v8::Context> current = v8_isolate->GetCurrentContext();
15890 CHECK(current.IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +000015891}
15892
15893
Steve Blocka7e24c12009-10-30 11:49:00 +000015894// Check that a variable declaration with no explicit initialization
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015895// value does shadow an existing property in the prototype chain.
Steve Blocka7e24c12009-10-30 11:49:00 +000015896THREADED_TEST(InitGlobalVarInProtoChain) {
Steve Blocka7e24c12009-10-30 11:49:00 +000015897 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015898 v8::HandleScope scope(context->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000015899 // Introduce a variable in the prototype chain.
15900 CompileRun("__proto__.x = 42");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015901 v8::Local<v8::Value> result = CompileRun("var x = 43; x");
Steve Blocka7e24c12009-10-30 11:49:00 +000015902 CHECK(!result->IsUndefined());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015903 CHECK_EQ(43, result->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000015904}
15905
15906
15907// Regression test for issue 398.
15908// If a function is added to an object, creating a constant function
15909// field, and the result is cloned, replacing the constant function on the
15910// original should not affect the clone.
15911// See http://code.google.com/p/v8/issues/detail?id=398
15912THREADED_TEST(ReplaceConstantFunction) {
Steve Blocka7e24c12009-10-30 11:49:00 +000015913 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015914 v8::Isolate* isolate = context->GetIsolate();
15915 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015916 v8::Local<v8::Object> obj = v8::Object::New(isolate);
15917 v8::Local<v8::FunctionTemplate> func_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015918 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015919 v8::Local<v8::String> foo_string = v8_str("foo");
15920 obj->Set(context.local(), foo_string,
15921 func_templ->GetFunction(context.local()).ToLocalChecked())
15922 .FromJust();
15923 v8::Local<v8::Object> obj_clone = obj->Clone();
15924 obj_clone->Set(context.local(), foo_string, v8_str("Hello")).FromJust();
15925 CHECK(!obj->Get(context.local(), foo_string).ToLocalChecked()->IsUndefined());
Steve Blocka7e24c12009-10-30 11:49:00 +000015926}
15927
15928
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015929static void CheckElementValue(i::Isolate* isolate,
15930 int expected,
15931 i::Handle<i::Object> obj,
15932 int offset) {
15933 i::Object* element =
15934 *i::Object::GetElement(isolate, obj, offset).ToHandleChecked();
15935 CHECK_EQ(expected, i::Smi::cast(element)->value());
Steve Blocka7e24c12009-10-30 11:49:00 +000015936}
15937
15938
Steve Block3ce2e202009-11-05 08:53:23 +000015939template <class ExternalArrayClass, class ElementType>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015940static void ObjectWithExternalArrayTestHelper(Local<Context> context,
15941 v8::Local<Object> obj,
15942 int element_count,
15943 i::ExternalArrayType array_type,
15944 int64_t low, int64_t high) {
15945 i::Handle<i::JSReceiver> jsobj = v8::Utils::OpenHandle(*obj);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015946 i::Isolate* isolate = jsobj->GetIsolate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015947 obj->Set(context, v8_str("field"),
15948 v8::Int32::New(reinterpret_cast<v8::Isolate*>(isolate), 1503))
15949 .FromJust();
15950 CHECK(context->Global()->Set(context, v8_str("ext_array"), obj).FromJust());
15951 v8::Local<v8::Value> result = CompileRun("ext_array.field");
15952 CHECK_EQ(1503, result->Int32Value(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000015953 result = CompileRun("ext_array[1]");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015954 CHECK_EQ(1, result->Int32Value(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000015955
Steve Block3ce2e202009-11-05 08:53:23 +000015956 // Check assigned smis
15957 result = CompileRun("for (var i = 0; i < 8; i++) {"
15958 " ext_array[i] = i;"
15959 "}"
15960 "var sum = 0;"
15961 "for (var i = 0; i < 8; i++) {"
15962 " sum += ext_array[i];"
15963 "}"
15964 "sum;");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015965
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015966 CHECK_EQ(28, result->Int32Value(context).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015967 // Check pass through of assigned smis
15968 result = CompileRun("var sum = 0;"
15969 "for (var i = 0; i < 8; i++) {"
15970 " sum += ext_array[i] = ext_array[i] = -i;"
15971 "}"
15972 "sum;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015973 CHECK_EQ(-28, result->Int32Value(context).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015974
Steve Block3ce2e202009-11-05 08:53:23 +000015975
15976 // Check assigned smis in reverse order
15977 result = CompileRun("for (var i = 8; --i >= 0; ) {"
15978 " ext_array[i] = i;"
15979 "}"
15980 "var sum = 0;"
15981 "for (var i = 0; i < 8; i++) {"
15982 " sum += ext_array[i];"
15983 "}"
15984 "sum;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015985 CHECK_EQ(28, result->Int32Value(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000015986
15987 // Check pass through of assigned HeapNumbers
15988 result = CompileRun("var sum = 0;"
15989 "for (var i = 0; i < 16; i+=2) {"
15990 " sum += ext_array[i] = ext_array[i] = (-i * 0.5);"
15991 "}"
15992 "sum;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015993 CHECK_EQ(-28, result->Int32Value(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000015994
15995 // Check assigned HeapNumbers
15996 result = CompileRun("for (var i = 0; i < 16; i+=2) {"
15997 " ext_array[i] = (i * 0.5);"
15998 "}"
15999 "var sum = 0;"
16000 "for (var i = 0; i < 16; i+=2) {"
16001 " sum += ext_array[i];"
16002 "}"
16003 "sum;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016004 CHECK_EQ(28, result->Int32Value(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000016005
16006 // Check assigned HeapNumbers in reverse order
16007 result = CompileRun("for (var i = 14; i >= 0; i-=2) {"
16008 " ext_array[i] = (i * 0.5);"
16009 "}"
16010 "var sum = 0;"
16011 "for (var i = 0; i < 16; i+=2) {"
16012 " sum += ext_array[i];"
16013 "}"
16014 "sum;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016015 CHECK_EQ(28, result->Int32Value(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000016016
16017 i::ScopedVector<char> test_buf(1024);
16018
16019 // Check legal boundary conditions.
16020 // The repeated loads and stores ensure the ICs are exercised.
16021 const char* boundary_program =
16022 "var res = 0;"
16023 "for (var i = 0; i < 16; i++) {"
16024 " ext_array[i] = %lld;"
16025 " if (i > 8) {"
16026 " res = ext_array[i];"
16027 " }"
16028 "}"
16029 "res;";
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016030 i::SNPrintF(test_buf,
16031 boundary_program,
16032 low);
Steve Block3ce2e202009-11-05 08:53:23 +000016033 result = CompileRun(test_buf.start());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016034 CHECK_EQ(low, result->IntegerValue(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000016035
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016036 i::SNPrintF(test_buf,
16037 boundary_program,
16038 high);
Steve Block3ce2e202009-11-05 08:53:23 +000016039 result = CompileRun(test_buf.start());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016040 CHECK_EQ(high, result->IntegerValue(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000016041
16042 // Check misprediction of type in IC.
16043 result = CompileRun("var tmp_array = ext_array;"
16044 "var sum = 0;"
16045 "for (var i = 0; i < 8; i++) {"
16046 " tmp_array[i] = i;"
16047 " sum += tmp_array[i];"
16048 " if (i == 4) {"
16049 " tmp_array = {};"
16050 " }"
16051 "}"
16052 "sum;");
Ben Murdoch3ef787d2012-04-12 10:51:47 +010016053 // Force GC to trigger verification.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016054 CcTest::heap()->CollectAllGarbage();
16055 CHECK_EQ(28, result->Int32Value(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000016056
16057 // Make sure out-of-range loads do not throw.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016058 i::SNPrintF(test_buf,
16059 "var caught_exception = false;"
16060 "try {"
16061 " ext_array[%d];"
16062 "} catch (e) {"
16063 " caught_exception = true;"
16064 "}"
16065 "caught_exception;",
16066 element_count);
Steve Block3ce2e202009-11-05 08:53:23 +000016067 result = CompileRun(test_buf.start());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016068 CHECK_EQ(false, result->BooleanValue(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000016069
16070 // Make sure out-of-range stores do not throw.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016071 i::SNPrintF(test_buf,
16072 "var caught_exception = false;"
16073 "try {"
16074 " ext_array[%d] = 1;"
16075 "} catch (e) {"
16076 " caught_exception = true;"
16077 "}"
16078 "caught_exception;",
16079 element_count);
Steve Block3ce2e202009-11-05 08:53:23 +000016080 result = CompileRun(test_buf.start());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016081 CHECK_EQ(false, result->BooleanValue(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000016082
16083 // Check other boundary conditions, values and operations.
16084 result = CompileRun("for (var i = 0; i < 8; i++) {"
16085 " ext_array[7] = undefined;"
16086 "}"
16087 "ext_array[7];");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016088 CHECK_EQ(0, result->Int32Value(context).FromJust());
16089 if (array_type == i::kExternalFloat64Array ||
16090 array_type == i::kExternalFloat32Array) {
16091 CHECK(std::isnan(
16092 i::Object::GetElement(isolate, jsobj, 7).ToHandleChecked()->Number()));
Ben Murdoch3ef787d2012-04-12 10:51:47 +010016093 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016094 CheckElementValue(isolate, 0, jsobj, 7);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010016095 }
Steve Block3ce2e202009-11-05 08:53:23 +000016096
16097 result = CompileRun("for (var i = 0; i < 8; i++) {"
16098 " ext_array[6] = '2.3';"
16099 "}"
16100 "ext_array[6];");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016101 CHECK_EQ(2, result->Int32Value(context).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016102 CHECK_EQ(2,
16103 static_cast<int>(
16104 i::Object::GetElement(
16105 isolate, jsobj, 6).ToHandleChecked()->Number()));
Steve Block3ce2e202009-11-05 08:53:23 +000016106
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016107 if (array_type != i::kExternalFloat32Array &&
16108 array_type != i::kExternalFloat64Array) {
Steve Block3ce2e202009-11-05 08:53:23 +000016109 // Though the specification doesn't state it, be explicit about
16110 // converting NaNs and +/-Infinity to zero.
16111 result = CompileRun("for (var i = 0; i < 8; i++) {"
16112 " ext_array[i] = 5;"
16113 "}"
16114 "for (var i = 0; i < 8; i++) {"
16115 " ext_array[i] = NaN;"
16116 "}"
16117 "ext_array[5];");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016118 CHECK_EQ(0, result->Int32Value(context).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016119 CheckElementValue(isolate, 0, jsobj, 5);
Steve Block3ce2e202009-11-05 08:53:23 +000016120
16121 result = CompileRun("for (var i = 0; i < 8; i++) {"
16122 " ext_array[i] = 5;"
16123 "}"
16124 "for (var i = 0; i < 8; i++) {"
16125 " ext_array[i] = Infinity;"
16126 "}"
16127 "ext_array[5];");
Steve Block44f0eee2011-05-26 01:26:41 +010016128 int expected_value =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016129 (array_type == i::kExternalUint8ClampedArray) ? 255 : 0;
16130 CHECK_EQ(expected_value, result->Int32Value(context).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016131 CheckElementValue(isolate, expected_value, jsobj, 5);
Steve Block3ce2e202009-11-05 08:53:23 +000016132
16133 result = CompileRun("for (var i = 0; i < 8; i++) {"
16134 " ext_array[i] = 5;"
16135 "}"
16136 "for (var i = 0; i < 8; i++) {"
16137 " ext_array[i] = -Infinity;"
16138 "}"
16139 "ext_array[5];");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016140 CHECK_EQ(0, result->Int32Value(context).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016141 CheckElementValue(isolate, 0, jsobj, 5);
Steve Block1e0659c2011-05-24 12:43:12 +010016142
16143 // Check truncation behavior of integral arrays.
16144 const char* unsigned_data =
16145 "var source_data = [0.6, 10.6];"
16146 "var expected_results = [0, 10];";
16147 const char* signed_data =
16148 "var source_data = [0.6, 10.6, -0.6, -10.6];"
16149 "var expected_results = [0, 10, 0, -10];";
Steve Block44f0eee2011-05-26 01:26:41 +010016150 const char* pixel_data =
16151 "var source_data = [0.6, 10.6];"
16152 "var expected_results = [1, 11];";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016153 bool is_unsigned = (array_type == i::kExternalUint8Array ||
16154 array_type == i::kExternalUint16Array ||
16155 array_type == i::kExternalUint32Array);
16156 bool is_pixel_data = array_type == i::kExternalUint8ClampedArray;
Steve Block1e0659c2011-05-24 12:43:12 +010016157
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016158 i::SNPrintF(test_buf,
16159 "%s"
16160 "var all_passed = true;"
16161 "for (var i = 0; i < source_data.length; i++) {"
16162 " for (var j = 0; j < 8; j++) {"
16163 " ext_array[j] = source_data[i];"
16164 " }"
16165 " all_passed = all_passed &&"
16166 " (ext_array[5] == expected_results[i]);"
16167 "}"
16168 "all_passed;",
16169 (is_unsigned ?
16170 unsigned_data :
16171 (is_pixel_data ? pixel_data : signed_data)));
Steve Block1e0659c2011-05-24 12:43:12 +010016172 result = CompileRun(test_buf.start());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016173 CHECK_EQ(true, result->BooleanValue(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000016174 }
16175
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016176 i::Handle<ExternalArrayClass> array(ExternalArrayClass::cast(
16177 i::Handle<i::JSObject>::cast(jsobj)->elements()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016178 for (int i = 0; i < element_count; i++) {
Ben Murdoch8b112d22011-06-08 16:22:53 +010016179 array->set(i, static_cast<ElementType>(i));
16180 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016181
Ben Murdoch8b112d22011-06-08 16:22:53 +010016182 // Test complex assignments
16183 result = CompileRun("function ee_op_test_complex_func(sum) {"
16184 " for (var i = 0; i < 40; ++i) {"
16185 " sum += (ext_array[i] += 1);"
16186 " sum += (ext_array[i] -= 1);"
16187 " } "
16188 " return sum;"
16189 "}"
16190 "sum=0;"
16191 "for (var i=0;i<10000;++i) {"
16192 " sum=ee_op_test_complex_func(sum);"
16193 "}"
16194 "sum;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016195 CHECK_EQ(16000000, result->Int32Value(context).FromJust());
Ben Murdoch8b112d22011-06-08 16:22:53 +010016196
16197 // Test count operations
16198 result = CompileRun("function ee_op_test_count_func(sum) {"
16199 " for (var i = 0; i < 40; ++i) {"
16200 " sum += (++ext_array[i]);"
16201 " sum += (--ext_array[i]);"
16202 " } "
16203 " return sum;"
16204 "}"
16205 "sum=0;"
16206 "for (var i=0;i<10000;++i) {"
16207 " sum=ee_op_test_count_func(sum);"
16208 "}"
16209 "sum;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016210 CHECK_EQ(16000000, result->Int32Value(context).FromJust());
Ben Murdoch8b112d22011-06-08 16:22:53 +010016211
Steve Block3ce2e202009-11-05 08:53:23 +000016212 result = CompileRun("ext_array[3] = 33;"
16213 "delete ext_array[3];"
16214 "ext_array[3];");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016215 CHECK_EQ(33, result->Int32Value(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000016216
16217 result = CompileRun("ext_array[0] = 10; ext_array[1] = 11;"
16218 "ext_array[2] = 12; ext_array[3] = 13;"
16219 "ext_array.__defineGetter__('2',"
16220 "function() { return 120; });"
16221 "ext_array[2];");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016222 CHECK_EQ(12, result->Int32Value(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000016223
16224 result = CompileRun("var js_array = new Array(40);"
16225 "js_array[0] = 77;"
16226 "js_array;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016227 CHECK_EQ(77, v8::Object::Cast(*result)
16228 ->Get(context, v8_str("0"))
16229 .ToLocalChecked()
16230 ->Int32Value(context)
16231 .FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000016232
16233 result = CompileRun("ext_array[1] = 23;"
16234 "ext_array.__proto__ = [];"
16235 "js_array.__proto__ = ext_array;"
16236 "js_array.concat(ext_array);");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016237 CHECK_EQ(77, v8::Object::Cast(*result)
16238 ->Get(context, v8_str("0"))
16239 .ToLocalChecked()
16240 ->Int32Value(context)
16241 .FromJust());
16242 CHECK_EQ(23, v8::Object::Cast(*result)
16243 ->Get(context, v8_str("1"))
16244 .ToLocalChecked()
16245 ->Int32Value(context)
16246 .FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000016247
16248 result = CompileRun("ext_array[1] = 23;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016249 CHECK_EQ(23, result->Int32Value(context).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016250}
16251
16252
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016253template <class FixedTypedArrayClass, i::ElementsKind elements_kind,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016254 class ElementType>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016255static void FixedTypedArrayTestHelper(i::ExternalArrayType array_type,
16256 ElementType low, ElementType high) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016257 i::FLAG_allow_natives_syntax = true;
16258 LocalContext context;
16259 i::Isolate* isolate = CcTest::i_isolate();
16260 i::Factory* factory = isolate->factory();
16261 v8::HandleScope scope(context->GetIsolate());
16262 const int kElementCount = 260;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016263 i::Handle<i::JSTypedArray> jsobj =
16264 factory->NewJSTypedArray(elements_kind, kElementCount);
16265 i::Handle<FixedTypedArrayClass> fixed_array(
16266 FixedTypedArrayClass::cast(jsobj->elements()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016267 CHECK_EQ(FixedTypedArrayClass::kInstanceType,
16268 fixed_array->map()->instance_type());
16269 CHECK_EQ(kElementCount, fixed_array->length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016270 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016271 for (int i = 0; i < kElementCount; i++) {
16272 fixed_array->set(i, static_cast<ElementType>(i));
16273 }
16274 // Force GC to trigger verification.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016275 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016276 for (int i = 0; i < kElementCount; i++) {
16277 CHECK_EQ(static_cast<int64_t>(static_cast<ElementType>(i)),
16278 static_cast<int64_t>(fixed_array->get_scalar(i)));
16279 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016280 v8::Local<v8::Object> obj = v8::Utils::ToLocal(jsobj);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016281
16282 ObjectWithExternalArrayTestHelper<FixedTypedArrayClass, ElementType>(
16283 context.local(), obj, kElementCount, array_type,
16284 static_cast<int64_t>(low),
16285 static_cast<int64_t>(high));
16286}
16287
16288
16289THREADED_TEST(FixedUint8Array) {
16290 FixedTypedArrayTestHelper<i::FixedUint8Array, i::UINT8_ELEMENTS, uint8_t>(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016291 i::kExternalUint8Array, 0x0, 0xFF);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016292}
16293
16294
16295THREADED_TEST(FixedUint8ClampedArray) {
16296 FixedTypedArrayTestHelper<i::FixedUint8ClampedArray,
16297 i::UINT8_CLAMPED_ELEMENTS, uint8_t>(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016298 i::kExternalUint8ClampedArray, 0x0, 0xFF);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016299}
16300
16301
16302THREADED_TEST(FixedInt8Array) {
16303 FixedTypedArrayTestHelper<i::FixedInt8Array, i::INT8_ELEMENTS, int8_t>(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016304 i::kExternalInt8Array, -0x80, 0x7F);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016305}
16306
16307
16308THREADED_TEST(FixedUint16Array) {
16309 FixedTypedArrayTestHelper<i::FixedUint16Array, i::UINT16_ELEMENTS, uint16_t>(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016310 i::kExternalUint16Array, 0x0, 0xFFFF);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016311}
16312
16313
16314THREADED_TEST(FixedInt16Array) {
16315 FixedTypedArrayTestHelper<i::FixedInt16Array, i::INT16_ELEMENTS, int16_t>(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016316 i::kExternalInt16Array, -0x8000, 0x7FFF);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016317}
16318
16319
16320THREADED_TEST(FixedUint32Array) {
16321 FixedTypedArrayTestHelper<i::FixedUint32Array, i::UINT32_ELEMENTS, uint32_t>(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016322 i::kExternalUint32Array, 0x0, UINT_MAX);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016323}
16324
16325
16326THREADED_TEST(FixedInt32Array) {
16327 FixedTypedArrayTestHelper<i::FixedInt32Array, i::INT32_ELEMENTS, int32_t>(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016328 i::kExternalInt32Array, INT_MIN, INT_MAX);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016329}
16330
16331
16332THREADED_TEST(FixedFloat32Array) {
16333 FixedTypedArrayTestHelper<i::FixedFloat32Array, i::FLOAT32_ELEMENTS, float>(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016334 i::kExternalFloat32Array, -500, 500);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016335}
16336
16337
16338THREADED_TEST(FixedFloat64Array) {
16339 FixedTypedArrayTestHelper<i::FixedFloat64Array, i::FLOAT64_ELEMENTS, float>(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016340 i::kExternalFloat64Array, -500, 500);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016341}
16342
16343
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016344template <typename ElementType, typename TypedArray, class ExternalArrayClass,
16345 class ArrayBufferType>
16346void TypedArrayTestHelper(i::ExternalArrayType array_type, int64_t low,
16347 int64_t high) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016348 const int kElementCount = 50;
16349
16350 i::ScopedVector<ElementType> backing_store(kElementCount+2);
16351
16352 LocalContext env;
16353 v8::Isolate* isolate = env->GetIsolate();
16354 v8::HandleScope handle_scope(isolate);
16355
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016356 Local<ArrayBufferType> ab =
16357 ArrayBufferType::New(isolate, backing_store.start(),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016358 (kElementCount + 2) * sizeof(ElementType));
16359 Local<TypedArray> ta =
16360 TypedArray::New(ab, 2*sizeof(ElementType), kElementCount);
16361 CheckInternalFieldsAreZero<v8::ArrayBufferView>(ta);
16362 CHECK_EQ(kElementCount, static_cast<int>(ta->Length()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016363 CHECK_EQ(2 * sizeof(ElementType), ta->ByteOffset());
16364 CHECK_EQ(kElementCount * sizeof(ElementType), ta->ByteLength());
16365 CHECK(ab->Equals(env.local(), ta->Buffer()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016366
16367 ElementType* data = backing_store.start() + 2;
16368 for (int i = 0; i < kElementCount; i++) {
16369 data[i] = static_cast<ElementType>(i);
16370 }
16371
16372 ObjectWithExternalArrayTestHelper<ExternalArrayClass, ElementType>(
16373 env.local(), ta, kElementCount, array_type, low, high);
16374}
16375
16376
16377THREADED_TEST(Uint8Array) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016378 TypedArrayTestHelper<uint8_t, v8::Uint8Array, i::FixedUint8Array,
16379 v8::ArrayBuffer>(i::kExternalUint8Array, 0, 0xFF);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016380}
16381
16382
16383THREADED_TEST(Int8Array) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016384 TypedArrayTestHelper<int8_t, v8::Int8Array, i::FixedInt8Array,
16385 v8::ArrayBuffer>(i::kExternalInt8Array, -0x80, 0x7F);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016386}
16387
16388
16389THREADED_TEST(Uint16Array) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016390 TypedArrayTestHelper<uint16_t, v8::Uint16Array, i::FixedUint16Array,
16391 v8::ArrayBuffer>(i::kExternalUint16Array, 0, 0xFFFF);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016392}
16393
16394
16395THREADED_TEST(Int16Array) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016396 TypedArrayTestHelper<int16_t, v8::Int16Array, i::FixedInt16Array,
16397 v8::ArrayBuffer>(i::kExternalInt16Array, -0x8000,
16398 0x7FFF);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016399}
16400
16401
16402THREADED_TEST(Uint32Array) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016403 TypedArrayTestHelper<uint32_t, v8::Uint32Array, i::FixedUint32Array,
16404 v8::ArrayBuffer>(i::kExternalUint32Array, 0, UINT_MAX);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016405}
16406
16407
16408THREADED_TEST(Int32Array) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016409 TypedArrayTestHelper<int32_t, v8::Int32Array, i::FixedInt32Array,
16410 v8::ArrayBuffer>(i::kExternalInt32Array, INT_MIN,
16411 INT_MAX);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016412}
16413
16414
16415THREADED_TEST(Float32Array) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016416 TypedArrayTestHelper<float, v8::Float32Array, i::FixedFloat32Array,
16417 v8::ArrayBuffer>(i::kExternalFloat32Array, -500, 500);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016418}
16419
16420
16421THREADED_TEST(Float64Array) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016422 TypedArrayTestHelper<double, v8::Float64Array, i::FixedFloat64Array,
16423 v8::ArrayBuffer>(i::kExternalFloat64Array, -500, 500);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016424}
16425
16426
16427THREADED_TEST(Uint8ClampedArray) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016428 TypedArrayTestHelper<uint8_t, v8::Uint8ClampedArray,
16429 i::FixedUint8ClampedArray, v8::ArrayBuffer>(
16430 i::kExternalUint8ClampedArray, 0, 0xFF);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016431}
16432
16433
16434THREADED_TEST(DataView) {
16435 const int kSize = 50;
16436
16437 i::ScopedVector<uint8_t> backing_store(kSize+2);
16438
16439 LocalContext env;
16440 v8::Isolate* isolate = env->GetIsolate();
16441 v8::HandleScope handle_scope(isolate);
16442
16443 Local<v8::ArrayBuffer> ab =
16444 v8::ArrayBuffer::New(isolate, backing_store.start(), 2 + kSize);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016445 Local<v8::DataView> dv = v8::DataView::New(ab, 2, kSize);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016446 CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016447 CHECK_EQ(2u, dv->ByteOffset());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016448 CHECK_EQ(kSize, static_cast<int>(dv->ByteLength()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016449 CHECK(ab->Equals(env.local(), dv->Buffer()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016450}
16451
16452
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016453THREADED_TEST(SkipArrayBufferBackingStoreDuringGC) {
16454 LocalContext env;
16455 v8::Isolate* isolate = env->GetIsolate();
16456 v8::HandleScope handle_scope(isolate);
16457
16458 // Make sure the pointer looks like a heap object
16459 uint8_t* store_ptr = reinterpret_cast<uint8_t*>(i::kHeapObjectTag);
16460
16461 // Create ArrayBuffer with pointer-that-cannot-be-visited in the backing store
16462 Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, store_ptr, 8);
16463
16464 // Should not crash
16465 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
16466 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
16467 CcTest::heap()->CollectAllGarbage();
16468 CcTest::heap()->CollectAllGarbage();
16469
16470 // Should not move the pointer
16471 CHECK_EQ(ab->GetContents().Data(), store_ptr);
16472}
16473
16474
16475THREADED_TEST(SkipArrayBufferDuringScavenge) {
16476 LocalContext env;
16477 v8::Isolate* isolate = env->GetIsolate();
16478 v8::HandleScope handle_scope(isolate);
16479
16480 // Make sure the pointer looks like a heap object
16481 Local<v8::Object> tmp = v8::Object::New(isolate);
16482 uint8_t* store_ptr =
16483 reinterpret_cast<uint8_t*>(*reinterpret_cast<uintptr_t*>(*tmp));
16484
16485 // Make `store_ptr` point to from space
16486 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
16487
16488 // Create ArrayBuffer with pointer-that-cannot-be-visited in the backing store
16489 Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, store_ptr, 8);
16490
16491 // Should not crash,
16492 // i.e. backing store pointer should not be treated as a heap object pointer
16493 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
16494 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
16495
16496 // Use `ab` to silence compiler warning
16497 CHECK_EQ(ab->GetContents().Data(), store_ptr);
16498}
16499
16500
16501THREADED_TEST(SharedUint8Array) {
16502 i::FLAG_harmony_sharedarraybuffer = true;
16503 TypedArrayTestHelper<uint8_t, v8::Uint8Array, i::FixedUint8Array,
16504 v8::SharedArrayBuffer>(i::kExternalUint8Array, 0, 0xFF);
16505}
16506
16507
16508THREADED_TEST(SharedInt8Array) {
16509 i::FLAG_harmony_sharedarraybuffer = true;
16510 TypedArrayTestHelper<int8_t, v8::Int8Array, i::FixedInt8Array,
16511 v8::SharedArrayBuffer>(i::kExternalInt8Array, -0x80,
16512 0x7F);
16513}
16514
16515
16516THREADED_TEST(SharedUint16Array) {
16517 i::FLAG_harmony_sharedarraybuffer = true;
16518 TypedArrayTestHelper<uint16_t, v8::Uint16Array, i::FixedUint16Array,
16519 v8::SharedArrayBuffer>(i::kExternalUint16Array, 0,
16520 0xFFFF);
16521}
16522
16523
16524THREADED_TEST(SharedInt16Array) {
16525 i::FLAG_harmony_sharedarraybuffer = true;
16526 TypedArrayTestHelper<int16_t, v8::Int16Array, i::FixedInt16Array,
16527 v8::SharedArrayBuffer>(i::kExternalInt16Array, -0x8000,
16528 0x7FFF);
16529}
16530
16531
16532THREADED_TEST(SharedUint32Array) {
16533 i::FLAG_harmony_sharedarraybuffer = true;
16534 TypedArrayTestHelper<uint32_t, v8::Uint32Array, i::FixedUint32Array,
16535 v8::SharedArrayBuffer>(i::kExternalUint32Array, 0,
16536 UINT_MAX);
16537}
16538
16539
16540THREADED_TEST(SharedInt32Array) {
16541 i::FLAG_harmony_sharedarraybuffer = true;
16542 TypedArrayTestHelper<int32_t, v8::Int32Array, i::FixedInt32Array,
16543 v8::SharedArrayBuffer>(i::kExternalInt32Array, INT_MIN,
16544 INT_MAX);
16545}
16546
16547
16548THREADED_TEST(SharedFloat32Array) {
16549 i::FLAG_harmony_sharedarraybuffer = true;
16550 TypedArrayTestHelper<float, v8::Float32Array, i::FixedFloat32Array,
16551 v8::SharedArrayBuffer>(i::kExternalFloat32Array, -500,
16552 500);
16553}
16554
16555
16556THREADED_TEST(SharedFloat64Array) {
16557 i::FLAG_harmony_sharedarraybuffer = true;
16558 TypedArrayTestHelper<double, v8::Float64Array, i::FixedFloat64Array,
16559 v8::SharedArrayBuffer>(i::kExternalFloat64Array, -500,
16560 500);
16561}
16562
16563
16564THREADED_TEST(SharedUint8ClampedArray) {
16565 i::FLAG_harmony_sharedarraybuffer = true;
16566 TypedArrayTestHelper<uint8_t, v8::Uint8ClampedArray,
16567 i::FixedUint8ClampedArray, v8::SharedArrayBuffer>(
16568 i::kExternalUint8ClampedArray, 0, 0xFF);
16569}
16570
16571
16572THREADED_TEST(SharedDataView) {
16573 i::FLAG_harmony_sharedarraybuffer = true;
16574 const int kSize = 50;
16575
16576 i::ScopedVector<uint8_t> backing_store(kSize + 2);
16577
16578 LocalContext env;
16579 v8::Isolate* isolate = env->GetIsolate();
16580 v8::HandleScope handle_scope(isolate);
16581
16582 Local<v8::SharedArrayBuffer> ab =
16583 v8::SharedArrayBuffer::New(isolate, backing_store.start(), 2 + kSize);
16584 Local<v8::DataView> dv =
16585 v8::DataView::New(ab, 2, kSize);
16586 CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
16587 CHECK_EQ(2u, dv->ByteOffset());
16588 CHECK_EQ(kSize, static_cast<int>(dv->ByteLength()));
16589 CHECK(ab->Equals(env.local(), dv->Buffer()).FromJust());
16590}
16591
16592
16593#define IS_ARRAY_BUFFER_VIEW_TEST(View) \
16594 THREADED_TEST(Is##View) { \
16595 LocalContext env; \
16596 v8::Isolate* isolate = env->GetIsolate(); \
16597 v8::HandleScope handle_scope(isolate); \
16598 \
16599 Local<Value> result = CompileRun( \
16600 "var ab = new ArrayBuffer(128);" \
16601 "new " #View "(ab)"); \
16602 CHECK(result->IsArrayBufferView()); \
16603 CHECK(result->Is##View()); \
16604 CheckInternalFieldsAreZero<v8::ArrayBufferView>(result.As<v8::View>()); \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016605 }
16606
16607IS_ARRAY_BUFFER_VIEW_TEST(Uint8Array)
16608IS_ARRAY_BUFFER_VIEW_TEST(Int8Array)
16609IS_ARRAY_BUFFER_VIEW_TEST(Uint16Array)
16610IS_ARRAY_BUFFER_VIEW_TEST(Int16Array)
16611IS_ARRAY_BUFFER_VIEW_TEST(Uint32Array)
16612IS_ARRAY_BUFFER_VIEW_TEST(Int32Array)
16613IS_ARRAY_BUFFER_VIEW_TEST(Float32Array)
16614IS_ARRAY_BUFFER_VIEW_TEST(Float64Array)
16615IS_ARRAY_BUFFER_VIEW_TEST(Uint8ClampedArray)
16616IS_ARRAY_BUFFER_VIEW_TEST(DataView)
16617
16618#undef IS_ARRAY_BUFFER_VIEW_TEST
16619
16620
16621
Steve Blocka7e24c12009-10-30 11:49:00 +000016622THREADED_TEST(ScriptContextDependence) {
Steve Blocka7e24c12009-10-30 11:49:00 +000016623 LocalContext c1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016624 v8::HandleScope scope(c1->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000016625 const char *source = "foo";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016626 v8::Local<v8::Script> dep = v8_compile(source);
16627 v8::ScriptCompiler::Source script_source(
16628 v8::String::NewFromUtf8(c1->GetIsolate(), source,
16629 v8::NewStringType::kNormal)
16630 .ToLocalChecked());
16631 v8::Local<v8::UnboundScript> indep =
16632 v8::ScriptCompiler::CompileUnboundScript(c1->GetIsolate(), &script_source)
16633 .ToLocalChecked();
16634 c1->Global()
16635 ->Set(c1.local(), v8::String::NewFromUtf8(c1->GetIsolate(), "foo",
16636 v8::NewStringType::kNormal)
16637 .ToLocalChecked(),
16638 v8::Integer::New(c1->GetIsolate(), 100))
16639 .FromJust();
16640 CHECK_EQ(
16641 dep->Run(c1.local()).ToLocalChecked()->Int32Value(c1.local()).FromJust(),
16642 100);
16643 CHECK_EQ(indep->BindToCurrentContext()
16644 ->Run(c1.local())
16645 .ToLocalChecked()
16646 ->Int32Value(c1.local())
16647 .FromJust(),
16648 100);
Steve Blocka7e24c12009-10-30 11:49:00 +000016649 LocalContext c2;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016650 c2->Global()
16651 ->Set(c2.local(), v8::String::NewFromUtf8(c2->GetIsolate(), "foo",
16652 v8::NewStringType::kNormal)
16653 .ToLocalChecked(),
16654 v8::Integer::New(c2->GetIsolate(), 101))
16655 .FromJust();
16656 CHECK_EQ(
16657 dep->Run(c2.local()).ToLocalChecked()->Int32Value(c2.local()).FromJust(),
16658 100);
16659 CHECK_EQ(indep->BindToCurrentContext()
16660 ->Run(c2.local())
16661 .ToLocalChecked()
16662 ->Int32Value(c2.local())
16663 .FromJust(),
16664 101);
Steve Blocka7e24c12009-10-30 11:49:00 +000016665}
16666
16667
16668THREADED_TEST(StackTrace) {
Steve Blocka7e24c12009-10-30 11:49:00 +000016669 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016670 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016671 v8::TryCatch try_catch(context->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000016672 const char *source = "function foo() { FAIL.FAIL; }; foo();";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016673 v8::Local<v8::String> src = v8_str(source);
16674 v8::Local<v8::String> origin = v8_str("stack-trace-test");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016675 v8::ScriptCompiler::Source script_source(src, v8::ScriptOrigin(origin));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016676 CHECK(v8::ScriptCompiler::CompileUnboundScript(context->GetIsolate(),
16677 &script_source)
16678 .ToLocalChecked()
16679 ->BindToCurrentContext()
16680 ->Run(context.local())
16681 .IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +000016682 CHECK(try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016683 v8::String::Utf8Value stack(
16684 try_catch.StackTrace(context.local()).ToLocalChecked());
Steve Blocka7e24c12009-10-30 11:49:00 +000016685 CHECK(strstr(*stack, "at foo (stack-trace-test") != NULL);
16686}
16687
16688
Kristian Monsen25f61362010-05-21 11:50:48 +010016689// Checks that a StackFrame has certain expected values.
16690void checkStackFrame(const char* expected_script_name,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016691 const char* expected_func_name, int expected_line_number,
16692 int expected_column, bool is_eval, bool is_constructor,
16693 v8::Local<v8::StackFrame> frame) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016694 v8::HandleScope scope(CcTest::isolate());
Kristian Monsen25f61362010-05-21 11:50:48 +010016695 v8::String::Utf8Value func_name(frame->GetFunctionName());
16696 v8::String::Utf8Value script_name(frame->GetScriptName());
16697 if (*script_name == NULL) {
16698 // The situation where there is no associated script, like for evals.
16699 CHECK(expected_script_name == NULL);
16700 } else {
16701 CHECK(strstr(*script_name, expected_script_name) != NULL);
16702 }
16703 CHECK(strstr(*func_name, expected_func_name) != NULL);
16704 CHECK_EQ(expected_line_number, frame->GetLineNumber());
16705 CHECK_EQ(expected_column, frame->GetColumn());
16706 CHECK_EQ(is_eval, frame->IsEval());
16707 CHECK_EQ(is_constructor, frame->IsConstructor());
16708}
16709
16710
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016711void AnalyzeStackInNativeCode(const v8::FunctionCallbackInfo<v8::Value>& args) {
16712 v8::HandleScope scope(args.GetIsolate());
Kristian Monsen25f61362010-05-21 11:50:48 +010016713 const char* origin = "capture-stack-trace-test";
16714 const int kOverviewTest = 1;
16715 const int kDetailedTest = 2;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016716 const int kFunctionName = 3;
16717 const int kDisplayName = 4;
16718 const int kFunctionNameAndDisplayName = 5;
16719 const int kDisplayNameIsNotString = 6;
16720 const int kFunctionNameIsNotString = 7;
Kristian Monsen25f61362010-05-21 11:50:48 +010016721
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016722 CHECK(args.Length() == 1);
Kristian Monsen25f61362010-05-21 11:50:48 +010016723
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016724 v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
16725 int testGroup = args[0]->Int32Value(context).FromJust();
Kristian Monsen25f61362010-05-21 11:50:48 +010016726 if (testGroup == kOverviewTest) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016727 v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016728 args.GetIsolate(), 10, v8::StackTrace::kOverview);
Kristian Monsen25f61362010-05-21 11:50:48 +010016729 CHECK_EQ(4, stackTrace->GetFrameCount());
16730 checkStackFrame(origin, "bar", 2, 10, false, false,
16731 stackTrace->GetFrame(0));
16732 checkStackFrame(origin, "foo", 6, 3, false, false,
16733 stackTrace->GetFrame(1));
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000016734 // This is the source string inside the eval which has the call to foo.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016735 checkStackFrame(NULL, "", 1, 1, false, false, stackTrace->GetFrame(2));
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000016736 // The last frame is an anonymous function which has the initial eval call.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016737 checkStackFrame(origin, "", 8, 7, false, false, stackTrace->GetFrame(3));
Kristian Monsen25f61362010-05-21 11:50:48 +010016738
16739 CHECK(stackTrace->AsArray()->IsArray());
16740 } else if (testGroup == kDetailedTest) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016741 v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016742 args.GetIsolate(), 10, v8::StackTrace::kDetailed);
Kristian Monsen25f61362010-05-21 11:50:48 +010016743 CHECK_EQ(4, stackTrace->GetFrameCount());
16744 checkStackFrame(origin, "bat", 4, 22, false, false,
16745 stackTrace->GetFrame(0));
16746 checkStackFrame(origin, "baz", 8, 3, false, true,
16747 stackTrace->GetFrame(1));
Kristian Monsen9dcf7e22010-06-28 14:14:28 +010016748 bool is_eval = true;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000016749 // This is the source string inside the eval which has the call to baz.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016750 checkStackFrame(NULL, "", 1, 1, is_eval, false, stackTrace->GetFrame(2));
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000016751 // The last frame is an anonymous function which has the initial eval call.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016752 checkStackFrame(origin, "", 10, 1, false, false, stackTrace->GetFrame(3));
Kristian Monsen25f61362010-05-21 11:50:48 +010016753
16754 CHECK(stackTrace->AsArray()->IsArray());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016755 } else if (testGroup == kFunctionName) {
16756 v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
16757 args.GetIsolate(), 5, v8::StackTrace::kOverview);
16758 CHECK_EQ(3, stackTrace->GetFrameCount());
16759 checkStackFrame(origin, "function.name", 2, 24, false, false,
16760 stackTrace->GetFrame(0));
16761 } else if (testGroup == kDisplayName) {
16762 v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
16763 args.GetIsolate(), 5, v8::StackTrace::kOverview);
16764 CHECK_EQ(3, stackTrace->GetFrameCount());
16765 checkStackFrame(origin, "function.displayName", 2, 24, false, false,
16766 stackTrace->GetFrame(0));
16767 } else if (testGroup == kFunctionNameAndDisplayName) {
16768 v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
16769 args.GetIsolate(), 5, v8::StackTrace::kOverview);
16770 CHECK_EQ(3, stackTrace->GetFrameCount());
16771 checkStackFrame(origin, "function.displayName", 2, 24, false, false,
16772 stackTrace->GetFrame(0));
16773 } else if (testGroup == kDisplayNameIsNotString) {
16774 v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
16775 args.GetIsolate(), 5, v8::StackTrace::kOverview);
16776 CHECK_EQ(3, stackTrace->GetFrameCount());
16777 checkStackFrame(origin, "function.name", 2, 24, false, false,
16778 stackTrace->GetFrame(0));
16779 } else if (testGroup == kFunctionNameIsNotString) {
16780 v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
16781 args.GetIsolate(), 5, v8::StackTrace::kOverview);
16782 CHECK_EQ(3, stackTrace->GetFrameCount());
16783 checkStackFrame(origin, "f", 2, 24, false, false, stackTrace->GetFrame(0));
Kristian Monsen25f61362010-05-21 11:50:48 +010016784 }
Kristian Monsen25f61362010-05-21 11:50:48 +010016785}
16786
16787
16788// Tests the C++ StackTrace API.
Ben Murdochb0fe1622011-05-05 13:52:32 +010016789// TODO(3074796): Reenable this as a THREADED_TEST once it passes.
16790// THREADED_TEST(CaptureStackTrace) {
16791TEST(CaptureStackTrace) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016792 v8::Isolate* isolate = CcTest::isolate();
16793 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016794 v8::Local<v8::String> origin = v8_str("capture-stack-trace-test");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016795 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Kristian Monsen25f61362010-05-21 11:50:48 +010016796 templ->Set(v8_str("AnalyzeStackInNativeCode"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016797 v8::FunctionTemplate::New(isolate, AnalyzeStackInNativeCode));
Kristian Monsen25f61362010-05-21 11:50:48 +010016798 LocalContext context(0, templ);
16799
16800 // Test getting OVERVIEW information. Should ignore information that is not
16801 // script name, function name, line number, and column offset.
16802 const char *overview_source =
16803 "function bar() {\n"
16804 " var y; AnalyzeStackInNativeCode(1);\n"
16805 "}\n"
16806 "function foo() {\n"
16807 "\n"
16808 " bar();\n"
16809 "}\n"
16810 "var x;eval('new foo();');";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016811 v8::Local<v8::String> overview_src = v8_str(overview_source);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016812 v8::ScriptCompiler::Source script_source(overview_src,
16813 v8::ScriptOrigin(origin));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016814 v8::Local<Value> overview_result(
16815 v8::ScriptCompiler::CompileUnboundScript(isolate, &script_source)
16816 .ToLocalChecked()
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016817 ->BindToCurrentContext()
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016818 ->Run(context.local())
16819 .ToLocalChecked());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010016820 CHECK(!overview_result.IsEmpty());
16821 CHECK(overview_result->IsObject());
Kristian Monsen25f61362010-05-21 11:50:48 +010016822
16823 // Test getting DETAILED information.
16824 const char *detailed_source =
16825 "function bat() {AnalyzeStackInNativeCode(2);\n"
16826 "}\n"
16827 "\n"
16828 "function baz() {\n"
16829 " bat();\n"
16830 "}\n"
16831 "eval('new baz();');";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016832 v8::Local<v8::String> detailed_src = v8_str(detailed_source);
Kristian Monsen25f61362010-05-21 11:50:48 +010016833 // Make the script using a non-zero line and column offset.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016834 v8::Local<v8::Integer> line_offset = v8::Integer::New(isolate, 3);
16835 v8::Local<v8::Integer> column_offset = v8::Integer::New(isolate, 5);
Kristian Monsen25f61362010-05-21 11:50:48 +010016836 v8::ScriptOrigin detailed_origin(origin, line_offset, column_offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016837 v8::ScriptCompiler::Source script_source2(detailed_src, detailed_origin);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016838 v8::Local<v8::UnboundScript> detailed_script(
16839 v8::ScriptCompiler::CompileUnboundScript(isolate, &script_source2)
16840 .ToLocalChecked());
16841 v8::Local<Value> detailed_result(detailed_script->BindToCurrentContext()
16842 ->Run(context.local())
16843 .ToLocalChecked());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010016844 CHECK(!detailed_result.IsEmpty());
16845 CHECK(detailed_result->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016846
16847 // Test using function.name and function.displayName in stack trace
16848 const char* function_name_source =
16849 "function bar(function_name, display_name, testGroup) {\n"
16850 " var f = function() { AnalyzeStackInNativeCode(testGroup); };\n"
16851 " if (function_name) {\n"
16852 " Object.defineProperty(f, 'name', { value: function_name });\n"
16853 " }\n"
16854 " if (display_name) {\n"
16855 " f.displayName = display_name;"
16856 " }\n"
16857 " f()\n"
16858 "}\n"
16859 "bar('function.name', undefined, 3);\n"
16860 "bar(undefined, 'function.displayName', 4);\n"
16861 "bar('function.name', 'function.displayName', 5);\n"
16862 "bar('function.name', 239, 6);\n"
16863 "bar(239, undefined, 7);\n";
16864 v8::Local<v8::String> function_name_src =
16865 v8::String::NewFromUtf8(isolate, function_name_source,
16866 v8::NewStringType::kNormal)
16867 .ToLocalChecked();
16868 v8::ScriptCompiler::Source script_source3(function_name_src,
16869 v8::ScriptOrigin(origin));
16870 v8::Local<Value> function_name_result(
16871 v8::ScriptCompiler::CompileUnboundScript(isolate, &script_source3)
16872 .ToLocalChecked()
16873 ->BindToCurrentContext()
16874 ->Run(context.local())
16875 .ToLocalChecked());
16876 CHECK(!function_name_result.IsEmpty());
Kristian Monsen25f61362010-05-21 11:50:48 +010016877}
16878
16879
Ben Murdoch3bec4d22010-07-22 14:51:16 +010016880static void StackTraceForUncaughtExceptionListener(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016881 v8::Local<v8::Message> message, v8::Local<Value>) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040016882 report_count++;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016883 v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
Ben Murdoch3bec4d22010-07-22 14:51:16 +010016884 CHECK_EQ(2, stack_trace->GetFrameCount());
16885 checkStackFrame("origin", "foo", 2, 3, false, false,
16886 stack_trace->GetFrame(0));
16887 checkStackFrame("origin", "bar", 5, 3, false, false,
16888 stack_trace->GetFrame(1));
16889}
16890
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016891
Ben Murdoch3bec4d22010-07-22 14:51:16 +010016892TEST(CaptureStackTraceForUncaughtException) {
16893 report_count = 0;
Ben Murdoch3bec4d22010-07-22 14:51:16 +010016894 LocalContext env;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016895 v8::Isolate* isolate = env->GetIsolate();
16896 v8::HandleScope scope(isolate);
16897 isolate->AddMessageListener(StackTraceForUncaughtExceptionListener);
16898 isolate->SetCaptureStackTraceForUncaughtExceptions(true);
Ben Murdoch3bec4d22010-07-22 14:51:16 +010016899
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016900 CompileRunWithOrigin(
16901 "function foo() {\n"
16902 " throw 1;\n"
16903 "};\n"
16904 "function bar() {\n"
16905 " foo();\n"
16906 "};",
16907 "origin");
Ben Murdoch3bec4d22010-07-22 14:51:16 +010016908 v8::Local<v8::Object> global = env->Global();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016909 Local<Value> trouble =
16910 global->Get(env.local(), v8_str("bar")).ToLocalChecked();
Ben Murdoch3bec4d22010-07-22 14:51:16 +010016911 CHECK(trouble->IsFunction());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016912 CHECK(Function::Cast(*trouble)->Call(env.local(), global, 0, NULL).IsEmpty());
16913 isolate->SetCaptureStackTraceForUncaughtExceptions(false);
16914 isolate->RemoveMessageListeners(StackTraceForUncaughtExceptionListener);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040016915 CHECK_EQ(1, report_count);
16916}
16917
16918
16919TEST(GetStackTraceForUncaughtExceptionFromSimpleStackTrace) {
16920 report_count = 0;
16921 LocalContext env;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016922 v8::Isolate* isolate = env->GetIsolate();
16923 v8::HandleScope scope(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040016924
16925 // Create an Error object first.
16926 CompileRunWithOrigin(
16927 "function foo() {\n"
16928 "e=new Error('err');\n"
16929 "};\n"
16930 "function bar() {\n"
16931 " foo();\n"
16932 "};\n"
16933 "var e;",
16934 "origin");
16935 v8::Local<v8::Object> global = env->Global();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016936 Local<Value> trouble =
16937 global->Get(env.local(), v8_str("bar")).ToLocalChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040016938 CHECK(trouble->IsFunction());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016939 Function::Cast(*trouble)->Call(env.local(), global, 0, NULL).ToLocalChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040016940
16941 // Enable capturing detailed stack trace late, and throw the exception.
16942 // The detailed stack trace should be extracted from the simple stack.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016943 isolate->AddMessageListener(StackTraceForUncaughtExceptionListener);
16944 isolate->SetCaptureStackTraceForUncaughtExceptions(true);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040016945 CompileRunWithOrigin("throw e", "origin");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016946 isolate->SetCaptureStackTraceForUncaughtExceptions(false);
16947 isolate->RemoveMessageListeners(StackTraceForUncaughtExceptionListener);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040016948 CHECK_EQ(1, report_count);
Ben Murdoch3bec4d22010-07-22 14:51:16 +010016949}
16950
16951
Steve Block1e0659c2011-05-24 12:43:12 +010016952TEST(CaptureStackTraceForUncaughtExceptionAndSetters) {
Steve Block1e0659c2011-05-24 12:43:12 +010016953 LocalContext env;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016954 v8::Isolate* isolate = env->GetIsolate();
16955 v8::HandleScope scope(isolate);
16956 isolate->SetCaptureStackTraceForUncaughtExceptions(true, 1024,
16957 v8::StackTrace::kDetailed);
Steve Block1e0659c2011-05-24 12:43:12 +010016958
16959 CompileRun(
16960 "var setters = ['column', 'lineNumber', 'scriptName',\n"
16961 " 'scriptNameOrSourceURL', 'functionName', 'isEval',\n"
16962 " 'isConstructor'];\n"
16963 "for (var i = 0; i < setters.length; i++) {\n"
16964 " var prop = setters[i];\n"
16965 " Object.prototype.__defineSetter__(prop, function() { throw prop; });\n"
16966 "}\n");
16967 CompileRun("throw 'exception';");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016968 isolate->SetCaptureStackTraceForUncaughtExceptions(false);
Steve Block1e0659c2011-05-24 12:43:12 +010016969}
16970
16971
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016972static void StackTraceFunctionNameListener(v8::Local<v8::Message> message,
16973 v8::Local<Value>) {
16974 v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
16975 CHECK_EQ(5, stack_trace->GetFrameCount());
16976 checkStackFrame("origin", "foo:0", 4, 7, false, false,
16977 stack_trace->GetFrame(0));
16978 checkStackFrame("origin", "foo:1", 5, 27, false, false,
16979 stack_trace->GetFrame(1));
16980 checkStackFrame("origin", "foo", 5, 27, false, false,
16981 stack_trace->GetFrame(2));
16982 checkStackFrame("origin", "foo", 5, 27, false, false,
16983 stack_trace->GetFrame(3));
16984 checkStackFrame("origin", "", 1, 14, false, false, stack_trace->GetFrame(4));
16985}
16986
16987
16988TEST(GetStackTraceContainsFunctionsWithFunctionName) {
16989 LocalContext env;
16990 v8::Isolate* isolate = env->GetIsolate();
16991 v8::HandleScope scope(isolate);
16992
16993 CompileRunWithOrigin(
16994 "function gen(name, counter) {\n"
16995 " var f = function foo() {\n"
16996 " if (counter === 0)\n"
16997 " throw 1;\n"
16998 " gen(name, counter - 1)();\n"
16999 " };\n"
17000 " if (counter == 3) {\n"
17001 " Object.defineProperty(f, 'name', {get: function(){ throw 239; }});\n"
17002 " } else {\n"
17003 " Object.defineProperty(f, 'name', {writable:true});\n"
17004 " if (counter == 2)\n"
17005 " f.name = 42;\n"
17006 " else\n"
17007 " f.name = name + ':' + counter;\n"
17008 " }\n"
17009 " return f;\n"
17010 "};",
17011 "origin");
17012
17013 isolate->AddMessageListener(StackTraceFunctionNameListener);
17014 isolate->SetCaptureStackTraceForUncaughtExceptions(true);
17015 CompileRunWithOrigin("gen('foo', 3)();", "origin");
17016 isolate->SetCaptureStackTraceForUncaughtExceptions(false);
17017 isolate->RemoveMessageListeners(StackTraceFunctionNameListener);
17018}
17019
17020
17021static void RethrowStackTraceHandler(v8::Local<v8::Message> message,
17022 v8::Local<v8::Value> data) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017023 // Use the frame where JavaScript is called from.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017024 v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017025 CHECK(!stack_trace.IsEmpty());
17026 int frame_count = stack_trace->GetFrameCount();
17027 CHECK_EQ(3, frame_count);
17028 int line_number[] = {1, 2, 5};
17029 for (int i = 0; i < frame_count; i++) {
17030 CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber());
17031 }
17032}
17033
17034
17035// Test that we only return the stack trace at the site where the exception
17036// is first thrown (not where it is rethrown).
17037TEST(RethrowStackTrace) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017038 LocalContext env;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017039 v8::Isolate* isolate = env->GetIsolate();
17040 v8::HandleScope scope(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017041 // We make sure that
17042 // - the stack trace of the ReferenceError in g() is reported.
17043 // - the stack trace is not overwritten when e1 is rethrown by t().
17044 // - the stack trace of e2 does not overwrite that of e1.
17045 const char* source =
17046 "function g() { error; } \n"
17047 "function f() { g(); } \n"
17048 "function t(e) { throw e; } \n"
17049 "try { \n"
17050 " f(); \n"
17051 "} catch (e1) { \n"
17052 " try { \n"
17053 " error; \n"
17054 " } catch (e2) { \n"
17055 " t(e1); \n"
17056 " } \n"
17057 "} \n";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017058 isolate->AddMessageListener(RethrowStackTraceHandler);
17059 isolate->SetCaptureStackTraceForUncaughtExceptions(true);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017060 CompileRun(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017061 isolate->SetCaptureStackTraceForUncaughtExceptions(false);
17062 isolate->RemoveMessageListeners(RethrowStackTraceHandler);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017063}
17064
17065
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017066static void RethrowPrimitiveStackTraceHandler(v8::Local<v8::Message> message,
17067 v8::Local<v8::Value> data) {
17068 v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017069 CHECK(!stack_trace.IsEmpty());
17070 int frame_count = stack_trace->GetFrameCount();
17071 CHECK_EQ(2, frame_count);
17072 int line_number[] = {3, 7};
17073 for (int i = 0; i < frame_count; i++) {
17074 CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber());
17075 }
17076}
17077
17078
17079// Test that we do not recognize identity for primitive exceptions.
17080TEST(RethrowPrimitiveStackTrace) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017081 LocalContext env;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017082 v8::Isolate* isolate = env->GetIsolate();
17083 v8::HandleScope scope(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017084 // We do not capture stack trace for non Error objects on creation time.
17085 // Instead, we capture the stack trace on last throw.
17086 const char* source =
17087 "function g() { throw 404; } \n"
17088 "function f() { g(); } \n"
17089 "function t(e) { throw e; } \n"
17090 "try { \n"
17091 " f(); \n"
17092 "} catch (e1) { \n"
17093 " t(e1) \n"
17094 "} \n";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017095 isolate->AddMessageListener(RethrowPrimitiveStackTraceHandler);
17096 isolate->SetCaptureStackTraceForUncaughtExceptions(true);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017097 CompileRun(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017098 isolate->SetCaptureStackTraceForUncaughtExceptions(false);
17099 isolate->RemoveMessageListeners(RethrowPrimitiveStackTraceHandler);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017100}
17101
17102
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017103static void RethrowExistingStackTraceHandler(v8::Local<v8::Message> message,
17104 v8::Local<v8::Value> data) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017105 // Use the frame where JavaScript is called from.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017106 v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017107 CHECK(!stack_trace.IsEmpty());
17108 CHECK_EQ(1, stack_trace->GetFrameCount());
17109 CHECK_EQ(1, stack_trace->GetFrame(0)->GetLineNumber());
17110}
17111
17112
17113// Test that the stack trace is captured when the error object is created and
17114// not where it is thrown.
17115TEST(RethrowExistingStackTrace) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017116 LocalContext env;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017117 v8::Isolate* isolate = env->GetIsolate();
17118 v8::HandleScope scope(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017119 const char* source =
17120 "var e = new Error(); \n"
17121 "throw e; \n";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017122 isolate->AddMessageListener(RethrowExistingStackTraceHandler);
17123 isolate->SetCaptureStackTraceForUncaughtExceptions(true);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017124 CompileRun(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017125 isolate->SetCaptureStackTraceForUncaughtExceptions(false);
17126 isolate->RemoveMessageListeners(RethrowExistingStackTraceHandler);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017127}
17128
17129
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017130static void RethrowBogusErrorStackTraceHandler(v8::Local<v8::Message> message,
17131 v8::Local<v8::Value> data) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017132 // Use the frame where JavaScript is called from.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017133 v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017134 CHECK(!stack_trace.IsEmpty());
17135 CHECK_EQ(1, stack_trace->GetFrameCount());
17136 CHECK_EQ(2, stack_trace->GetFrame(0)->GetLineNumber());
17137}
17138
17139
17140// Test that the stack trace is captured where the bogus Error object is thrown.
17141TEST(RethrowBogusErrorStackTrace) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017142 LocalContext env;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017143 v8::Isolate* isolate = env->GetIsolate();
17144 v8::HandleScope scope(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017145 const char* source =
17146 "var e = {__proto__: new Error()} \n"
17147 "throw e; \n";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017148 isolate->AddMessageListener(RethrowBogusErrorStackTraceHandler);
17149 isolate->SetCaptureStackTraceForUncaughtExceptions(true);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017150 CompileRun(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017151 isolate->SetCaptureStackTraceForUncaughtExceptions(false);
17152 isolate->RemoveMessageListeners(RethrowBogusErrorStackTraceHandler);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017153}
17154
17155
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017156v8::PromiseRejectEvent reject_event = v8::kPromiseRejectWithNoHandler;
17157int promise_reject_counter = 0;
17158int promise_revoke_counter = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017159int promise_reject_msg_line_number = -1;
17160int promise_reject_msg_column_number = -1;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017161int promise_reject_line_number = -1;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017162int promise_reject_column_number = -1;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017163int promise_reject_frame_count = -1;
17164
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017165void PromiseRejectCallback(v8::PromiseRejectMessage reject_message) {
17166 v8::Local<v8::Object> global = CcTest::global();
17167 v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
17168 if (reject_message.GetEvent() == v8::kPromiseRejectWithNoHandler) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017169 promise_reject_counter++;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017170 global->Set(context, v8_str("rejected"), reject_message.GetPromise())
17171 .FromJust();
17172 global->Set(context, v8_str("value"), reject_message.GetValue()).FromJust();
17173 v8::Local<v8::Message> message = v8::Exception::CreateMessage(
17174 CcTest::isolate(), reject_message.GetValue());
17175 v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
17176
17177 promise_reject_msg_line_number = message->GetLineNumber(context).FromJust();
17178 promise_reject_msg_column_number =
17179 message->GetStartColumn(context).FromJust() + 1;
17180
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017181 if (!stack_trace.IsEmpty()) {
17182 promise_reject_frame_count = stack_trace->GetFrameCount();
17183 if (promise_reject_frame_count > 0) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017184 CHECK(stack_trace->GetFrame(0)
17185 ->GetScriptName()
17186 ->Equals(context, v8_str("pro"))
17187 .FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017188 promise_reject_line_number = stack_trace->GetFrame(0)->GetLineNumber();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017189 promise_reject_column_number = stack_trace->GetFrame(0)->GetColumn();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017190 } else {
17191 promise_reject_line_number = -1;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017192 promise_reject_column_number = -1;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017193 }
17194 }
17195 } else {
17196 promise_revoke_counter++;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017197 global->Set(context, v8_str("revoked"), reject_message.GetPromise())
17198 .FromJust();
17199 CHECK(reject_message.GetValue().IsEmpty());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017200 }
17201}
17202
17203
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017204v8::Local<v8::Promise> GetPromise(const char* name) {
17205 return v8::Local<v8::Promise>::Cast(
17206 CcTest::global()
17207 ->Get(CcTest::isolate()->GetCurrentContext(), v8_str(name))
17208 .ToLocalChecked());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017209}
17210
17211
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017212v8::Local<v8::Value> RejectValue() {
17213 return CcTest::global()
17214 ->Get(CcTest::isolate()->GetCurrentContext(), v8_str("value"))
17215 .ToLocalChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017216}
17217
17218
17219void ResetPromiseStates() {
17220 promise_reject_counter = 0;
17221 promise_revoke_counter = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017222 promise_reject_msg_line_number = -1;
17223 promise_reject_msg_column_number = -1;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017224 promise_reject_line_number = -1;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017225 promise_reject_column_number = -1;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017226 promise_reject_frame_count = -1;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017227
17228 v8::Local<v8::Object> global = CcTest::global();
17229 v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
17230 global->Set(context, v8_str("rejected"), v8_str("")).FromJust();
17231 global->Set(context, v8_str("value"), v8_str("")).FromJust();
17232 global->Set(context, v8_str("revoked"), v8_str("")).FromJust();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017233}
17234
17235
17236TEST(PromiseRejectCallback) {
17237 LocalContext env;
17238 v8::Isolate* isolate = env->GetIsolate();
17239 v8::HandleScope scope(isolate);
17240
17241 isolate->SetPromiseRejectCallback(PromiseRejectCallback);
17242
17243 ResetPromiseStates();
17244
17245 // Create promise p0.
17246 CompileRun(
17247 "var reject; \n"
17248 "var p0 = new Promise( \n"
17249 " function(res, rej) { \n"
17250 " reject = rej; \n"
17251 " } \n"
17252 "); \n");
17253 CHECK(!GetPromise("p0")->HasHandler());
17254 CHECK_EQ(0, promise_reject_counter);
17255 CHECK_EQ(0, promise_revoke_counter);
17256
17257 // Add resolve handler (and default reject handler) to p0.
17258 CompileRun("var p1 = p0.then(function(){});");
17259 CHECK(GetPromise("p0")->HasHandler());
17260 CHECK(!GetPromise("p1")->HasHandler());
17261 CHECK_EQ(0, promise_reject_counter);
17262 CHECK_EQ(0, promise_revoke_counter);
17263
17264 // Reject p0.
17265 CompileRun("reject('ppp');");
17266 CHECK(GetPromise("p0")->HasHandler());
17267 CHECK(!GetPromise("p1")->HasHandler());
17268 CHECK_EQ(1, promise_reject_counter);
17269 CHECK_EQ(0, promise_revoke_counter);
17270 CHECK_EQ(v8::kPromiseRejectWithNoHandler, reject_event);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017271 CHECK(
17272 GetPromise("rejected")->Equals(env.local(), GetPromise("p1")).FromJust());
17273 CHECK(RejectValue()->Equals(env.local(), v8_str("ppp")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017274
17275 // Reject p0 again. Callback is not triggered again.
17276 CompileRun("reject();");
17277 CHECK(GetPromise("p0")->HasHandler());
17278 CHECK(!GetPromise("p1")->HasHandler());
17279 CHECK_EQ(1, promise_reject_counter);
17280 CHECK_EQ(0, promise_revoke_counter);
17281
17282 // Add resolve handler to p1.
17283 CompileRun("var p2 = p1.then(function(){});");
17284 CHECK(GetPromise("p0")->HasHandler());
17285 CHECK(GetPromise("p1")->HasHandler());
17286 CHECK(!GetPromise("p2")->HasHandler());
17287 CHECK_EQ(2, promise_reject_counter);
17288 CHECK_EQ(1, promise_revoke_counter);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017289 CHECK(
17290 GetPromise("rejected")->Equals(env.local(), GetPromise("p2")).FromJust());
17291 CHECK(RejectValue()->Equals(env.local(), v8_str("ppp")).FromJust());
17292 CHECK(
17293 GetPromise("revoked")->Equals(env.local(), GetPromise("p1")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017294
17295 ResetPromiseStates();
17296
17297 // Create promise q0.
17298 CompileRun(
17299 "var q0 = new Promise( \n"
17300 " function(res, rej) { \n"
17301 " reject = rej; \n"
17302 " } \n"
17303 "); \n");
17304 CHECK(!GetPromise("q0")->HasHandler());
17305 CHECK_EQ(0, promise_reject_counter);
17306 CHECK_EQ(0, promise_revoke_counter);
17307
17308 // Add reject handler to q0.
17309 CompileRun("var q1 = q0.catch(function() {});");
17310 CHECK(GetPromise("q0")->HasHandler());
17311 CHECK(!GetPromise("q1")->HasHandler());
17312 CHECK_EQ(0, promise_reject_counter);
17313 CHECK_EQ(0, promise_revoke_counter);
17314
17315 // Reject q0.
17316 CompileRun("reject('qq')");
17317 CHECK(GetPromise("q0")->HasHandler());
17318 CHECK(!GetPromise("q1")->HasHandler());
17319 CHECK_EQ(0, promise_reject_counter);
17320 CHECK_EQ(0, promise_revoke_counter);
17321
17322 // Add a new reject handler, which rejects by returning Promise.reject().
17323 // The returned promise q_ triggers a reject callback at first, only to
17324 // revoke it when returning it causes q2 to be rejected.
17325 CompileRun(
17326 "var q_;"
17327 "var q2 = q0.catch( \n"
17328 " function() { \n"
17329 " q_ = Promise.reject('qqq'); \n"
17330 " return q_; \n"
17331 " } \n"
17332 "); \n");
17333 CHECK(GetPromise("q0")->HasHandler());
17334 CHECK(!GetPromise("q1")->HasHandler());
17335 CHECK(!GetPromise("q2")->HasHandler());
17336 CHECK(GetPromise("q_")->HasHandler());
17337 CHECK_EQ(2, promise_reject_counter);
17338 CHECK_EQ(1, promise_revoke_counter);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017339 CHECK(
17340 GetPromise("rejected")->Equals(env.local(), GetPromise("q2")).FromJust());
17341 CHECK(
17342 GetPromise("revoked")->Equals(env.local(), GetPromise("q_")).FromJust());
17343 CHECK(RejectValue()->Equals(env.local(), v8_str("qqq")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017344
17345 // Add a reject handler to the resolved q1, which rejects by throwing.
17346 CompileRun(
17347 "var q3 = q1.then( \n"
17348 " function() { \n"
17349 " throw 'qqqq'; \n"
17350 " } \n"
17351 "); \n");
17352 CHECK(GetPromise("q0")->HasHandler());
17353 CHECK(GetPromise("q1")->HasHandler());
17354 CHECK(!GetPromise("q2")->HasHandler());
17355 CHECK(!GetPromise("q3")->HasHandler());
17356 CHECK_EQ(3, promise_reject_counter);
17357 CHECK_EQ(1, promise_revoke_counter);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017358 CHECK(
17359 GetPromise("rejected")->Equals(env.local(), GetPromise("q3")).FromJust());
17360 CHECK(RejectValue()->Equals(env.local(), v8_str("qqqq")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017361
17362 ResetPromiseStates();
17363
17364 // Create promise r0, which has three handlers, two of which handle rejects.
17365 CompileRun(
17366 "var r0 = new Promise( \n"
17367 " function(res, rej) { \n"
17368 " reject = rej; \n"
17369 " } \n"
17370 "); \n"
17371 "var r1 = r0.catch(function() {}); \n"
17372 "var r2 = r0.then(function() {}); \n"
17373 "var r3 = r0.then(function() {}, \n"
17374 " function() {}); \n");
17375 CHECK(GetPromise("r0")->HasHandler());
17376 CHECK(!GetPromise("r1")->HasHandler());
17377 CHECK(!GetPromise("r2")->HasHandler());
17378 CHECK(!GetPromise("r3")->HasHandler());
17379 CHECK_EQ(0, promise_reject_counter);
17380 CHECK_EQ(0, promise_revoke_counter);
17381
17382 // Reject r0.
17383 CompileRun("reject('rrr')");
17384 CHECK(GetPromise("r0")->HasHandler());
17385 CHECK(!GetPromise("r1")->HasHandler());
17386 CHECK(!GetPromise("r2")->HasHandler());
17387 CHECK(!GetPromise("r3")->HasHandler());
17388 CHECK_EQ(1, promise_reject_counter);
17389 CHECK_EQ(0, promise_revoke_counter);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017390 CHECK(
17391 GetPromise("rejected")->Equals(env.local(), GetPromise("r2")).FromJust());
17392 CHECK(RejectValue()->Equals(env.local(), v8_str("rrr")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017393
17394 // Add reject handler to r2.
17395 CompileRun("var r4 = r2.catch(function() {});");
17396 CHECK(GetPromise("r0")->HasHandler());
17397 CHECK(!GetPromise("r1")->HasHandler());
17398 CHECK(GetPromise("r2")->HasHandler());
17399 CHECK(!GetPromise("r3")->HasHandler());
17400 CHECK(!GetPromise("r4")->HasHandler());
17401 CHECK_EQ(1, promise_reject_counter);
17402 CHECK_EQ(1, promise_revoke_counter);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017403 CHECK(
17404 GetPromise("revoked")->Equals(env.local(), GetPromise("r2")).FromJust());
17405 CHECK(RejectValue()->Equals(env.local(), v8_str("rrr")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017406
17407 // Add reject handlers to r4.
17408 CompileRun("var r5 = r4.then(function() {}, function() {});");
17409 CHECK(GetPromise("r0")->HasHandler());
17410 CHECK(!GetPromise("r1")->HasHandler());
17411 CHECK(GetPromise("r2")->HasHandler());
17412 CHECK(!GetPromise("r3")->HasHandler());
17413 CHECK(GetPromise("r4")->HasHandler());
17414 CHECK(!GetPromise("r5")->HasHandler());
17415 CHECK_EQ(1, promise_reject_counter);
17416 CHECK_EQ(1, promise_revoke_counter);
17417
17418 ResetPromiseStates();
17419
17420 // Create promise s0, which has three handlers, none of which handle rejects.
17421 CompileRun(
17422 "var s0 = new Promise( \n"
17423 " function(res, rej) { \n"
17424 " reject = rej; \n"
17425 " } \n"
17426 "); \n"
17427 "var s1 = s0.then(function() {}); \n"
17428 "var s2 = s0.then(function() {}); \n"
17429 "var s3 = s0.then(function() {}); \n");
17430 CHECK(GetPromise("s0")->HasHandler());
17431 CHECK(!GetPromise("s1")->HasHandler());
17432 CHECK(!GetPromise("s2")->HasHandler());
17433 CHECK(!GetPromise("s3")->HasHandler());
17434 CHECK_EQ(0, promise_reject_counter);
17435 CHECK_EQ(0, promise_revoke_counter);
17436
17437 // Reject s0.
17438 CompileRun("reject('sss')");
17439 CHECK(GetPromise("s0")->HasHandler());
17440 CHECK(!GetPromise("s1")->HasHandler());
17441 CHECK(!GetPromise("s2")->HasHandler());
17442 CHECK(!GetPromise("s3")->HasHandler());
17443 CHECK_EQ(3, promise_reject_counter);
17444 CHECK_EQ(0, promise_revoke_counter);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017445 CHECK(RejectValue()->Equals(env.local(), v8_str("sss")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017446
17447 // Test stack frames.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017448 env->GetIsolate()->SetCaptureStackTraceForUncaughtExceptions(true);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017449
17450 ResetPromiseStates();
17451
17452 // Create promise t0, which is rejected in the constructor with an error.
17453 CompileRunWithOrigin(
17454 "var t0 = new Promise( \n"
17455 " function(res, rej) { \n"
17456 " reference_error; \n"
17457 " } \n"
17458 "); \n",
17459 "pro", 0, 0);
17460 CHECK(!GetPromise("t0")->HasHandler());
17461 CHECK_EQ(1, promise_reject_counter);
17462 CHECK_EQ(0, promise_revoke_counter);
17463 CHECK_EQ(2, promise_reject_frame_count);
17464 CHECK_EQ(3, promise_reject_line_number);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017465 CHECK_EQ(5, promise_reject_column_number);
17466 CHECK_EQ(3, promise_reject_msg_line_number);
17467 CHECK_EQ(5, promise_reject_msg_column_number);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017468
17469 ResetPromiseStates();
17470
17471 // Create promise u0 and chain u1 to it, which is rejected via throw.
17472 CompileRunWithOrigin(
17473 "var u0 = Promise.resolve(); \n"
17474 "var u1 = u0.then( \n"
17475 " function() { \n"
17476 " (function() { \n"
17477 " throw new Error(); \n"
17478 " })(); \n"
17479 " } \n"
17480 " ); \n",
17481 "pro", 0, 0);
17482 CHECK(GetPromise("u0")->HasHandler());
17483 CHECK(!GetPromise("u1")->HasHandler());
17484 CHECK_EQ(1, promise_reject_counter);
17485 CHECK_EQ(0, promise_revoke_counter);
17486 CHECK_EQ(2, promise_reject_frame_count);
17487 CHECK_EQ(5, promise_reject_line_number);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017488 CHECK_EQ(23, promise_reject_column_number);
17489 CHECK_EQ(5, promise_reject_msg_line_number);
17490 CHECK_EQ(23, promise_reject_msg_column_number);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017491
17492 // Throw in u3, which handles u1's rejection.
17493 CompileRunWithOrigin(
17494 "function f() { \n"
17495 " return (function() { \n"
17496 " return new Error(); \n"
17497 " })(); \n"
17498 "} \n"
17499 "var u2 = Promise.reject(f()); \n"
17500 "var u3 = u1.catch( \n"
17501 " function() { \n"
17502 " return u2; \n"
17503 " } \n"
17504 " ); \n",
17505 "pro", 0, 0);
17506 CHECK(GetPromise("u0")->HasHandler());
17507 CHECK(GetPromise("u1")->HasHandler());
17508 CHECK(GetPromise("u2")->HasHandler());
17509 CHECK(!GetPromise("u3")->HasHandler());
17510 CHECK_EQ(3, promise_reject_counter);
17511 CHECK_EQ(2, promise_revoke_counter);
17512 CHECK_EQ(3, promise_reject_frame_count);
17513 CHECK_EQ(3, promise_reject_line_number);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017514 CHECK_EQ(12, promise_reject_column_number);
17515 CHECK_EQ(3, promise_reject_msg_line_number);
17516 CHECK_EQ(12, promise_reject_msg_column_number);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017517
17518 ResetPromiseStates();
17519
17520 // Create promise rejected promise v0, which is incorrectly handled by v1
17521 // via chaining cycle.
17522 CompileRunWithOrigin(
17523 "var v0 = Promise.reject(); \n"
17524 "var v1 = v0.catch( \n"
17525 " function() { \n"
17526 " return v1; \n"
17527 " } \n"
17528 " ); \n",
17529 "pro", 0, 0);
17530 CHECK(GetPromise("v0")->HasHandler());
17531 CHECK(!GetPromise("v1")->HasHandler());
17532 CHECK_EQ(2, promise_reject_counter);
17533 CHECK_EQ(1, promise_revoke_counter);
17534 CHECK_EQ(0, promise_reject_frame_count);
17535 CHECK_EQ(-1, promise_reject_line_number);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017536 CHECK_EQ(-1, promise_reject_column_number);
17537
17538 ResetPromiseStates();
17539
17540 // Create promise t1, which rejects by throwing syntax error from eval.
17541 CompileRunWithOrigin(
17542 "var t1 = new Promise( \n"
17543 " function(res, rej) { \n"
17544 " var content = '\\n\\\n"
17545 " }'; \n"
17546 " eval(content); \n"
17547 " } \n"
17548 "); \n",
17549 "pro", 0, 0);
17550 CHECK(!GetPromise("t1")->HasHandler());
17551 CHECK_EQ(1, promise_reject_counter);
17552 CHECK_EQ(0, promise_revoke_counter);
17553 CHECK_EQ(2, promise_reject_frame_count);
17554 CHECK_EQ(5, promise_reject_line_number);
17555 CHECK_EQ(10, promise_reject_column_number);
17556 CHECK_EQ(2, promise_reject_msg_line_number);
17557 CHECK_EQ(7, promise_reject_msg_column_number);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017558}
17559
17560
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017561void AnalyzeStackOfEvalWithSourceURL(
17562 const v8::FunctionCallbackInfo<v8::Value>& args) {
17563 v8::HandleScope scope(args.GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017564 v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017565 args.GetIsolate(), 10, v8::StackTrace::kDetailed);
Ben Murdochf87a2032010-10-22 12:50:53 +010017566 CHECK_EQ(5, stackTrace->GetFrameCount());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017567 v8::Local<v8::String> url = v8_str("eval_url");
Ben Murdochf87a2032010-10-22 12:50:53 +010017568 for (int i = 0; i < 3; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017569 v8::Local<v8::String> name =
Ben Murdochf87a2032010-10-22 12:50:53 +010017570 stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
17571 CHECK(!name.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017572 CHECK(url->Equals(args.GetIsolate()->GetCurrentContext(), name).FromJust());
Ben Murdochf87a2032010-10-22 12:50:53 +010017573 }
Ben Murdochf87a2032010-10-22 12:50:53 +010017574}
17575
17576
17577TEST(SourceURLInStackTrace) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017578 v8::Isolate* isolate = CcTest::isolate();
17579 v8::HandleScope scope(isolate);
17580 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Ben Murdochf87a2032010-10-22 12:50:53 +010017581 templ->Set(v8_str("AnalyzeStackOfEvalWithSourceURL"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017582 v8::FunctionTemplate::New(isolate,
17583 AnalyzeStackOfEvalWithSourceURL));
Ben Murdochf87a2032010-10-22 12:50:53 +010017584 LocalContext context(0, templ);
17585
17586 const char *source =
17587 "function outer() {\n"
17588 "function bar() {\n"
17589 " AnalyzeStackOfEvalWithSourceURL();\n"
17590 "}\n"
17591 "function foo() {\n"
17592 "\n"
17593 " bar();\n"
17594 "}\n"
17595 "foo();\n"
17596 "}\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017597 "eval('(' + outer +')()%s');";
17598
17599 i::ScopedVector<char> code(1024);
17600 i::SNPrintF(code, source, "//# sourceURL=eval_url");
17601 CHECK(CompileRun(code.start())->IsUndefined());
17602 i::SNPrintF(code, source, "//@ sourceURL=eval_url");
17603 CHECK(CompileRun(code.start())->IsUndefined());
17604}
17605
17606
17607static int scriptIdInStack[2];
17608
17609void AnalyzeScriptIdInStack(
17610 const v8::FunctionCallbackInfo<v8::Value>& args) {
17611 v8::HandleScope scope(args.GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017612 v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017613 args.GetIsolate(), 10, v8::StackTrace::kScriptId);
17614 CHECK_EQ(2, stackTrace->GetFrameCount());
17615 for (int i = 0; i < 2; i++) {
17616 scriptIdInStack[i] = stackTrace->GetFrame(i)->GetScriptId();
17617 }
17618}
17619
17620
17621TEST(ScriptIdInStackTrace) {
17622 v8::Isolate* isolate = CcTest::isolate();
17623 v8::HandleScope scope(isolate);
17624 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
17625 templ->Set(v8_str("AnalyzeScriptIdInStack"),
17626 v8::FunctionTemplate::New(isolate, AnalyzeScriptIdInStack));
17627 LocalContext context(0, templ);
17628
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017629 v8::Local<v8::String> scriptSource = v8_str(
17630 "function foo() {\n"
17631 " AnalyzeScriptIdInStack();"
17632 "}\n"
17633 "foo();\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017634 v8::Local<v8::Script> script = CompileWithOrigin(scriptSource, "test");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017635 script->Run(context.local()).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017636 for (int i = 0; i < 2; i++) {
17637 CHECK(scriptIdInStack[i] != v8::Message::kNoScriptIdInfo);
17638 CHECK_EQ(scriptIdInStack[i], script->GetUnboundScript()->GetId());
17639 }
17640}
17641
17642
17643void AnalyzeStackOfInlineScriptWithSourceURL(
17644 const v8::FunctionCallbackInfo<v8::Value>& args) {
17645 v8::HandleScope scope(args.GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017646 v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017647 args.GetIsolate(), 10, v8::StackTrace::kDetailed);
17648 CHECK_EQ(4, stackTrace->GetFrameCount());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017649 v8::Local<v8::String> url = v8_str("source_url");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017650 for (int i = 0; i < 3; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017651 v8::Local<v8::String> name =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017652 stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
17653 CHECK(!name.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017654 CHECK(url->Equals(args.GetIsolate()->GetCurrentContext(), name).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017655 }
17656}
17657
17658
17659TEST(InlineScriptWithSourceURLInStackTrace) {
17660 v8::Isolate* isolate = CcTest::isolate();
17661 v8::HandleScope scope(isolate);
17662 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
17663 templ->Set(v8_str("AnalyzeStackOfInlineScriptWithSourceURL"),
17664 v8::FunctionTemplate::New(
17665 CcTest::isolate(), AnalyzeStackOfInlineScriptWithSourceURL));
17666 LocalContext context(0, templ);
17667
17668 const char *source =
17669 "function outer() {\n"
17670 "function bar() {\n"
17671 " AnalyzeStackOfInlineScriptWithSourceURL();\n"
17672 "}\n"
17673 "function foo() {\n"
17674 "\n"
17675 " bar();\n"
17676 "}\n"
17677 "foo();\n"
17678 "}\n"
17679 "outer()\n%s";
17680
17681 i::ScopedVector<char> code(1024);
17682 i::SNPrintF(code, source, "//# sourceURL=source_url");
17683 CHECK(CompileRunWithOrigin(code.start(), "url", 0, 1)->IsUndefined());
17684 i::SNPrintF(code, source, "//@ sourceURL=source_url");
17685 CHECK(CompileRunWithOrigin(code.start(), "url", 0, 1)->IsUndefined());
17686}
17687
17688
17689void AnalyzeStackOfDynamicScriptWithSourceURL(
17690 const v8::FunctionCallbackInfo<v8::Value>& args) {
17691 v8::HandleScope scope(args.GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017692 v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017693 args.GetIsolate(), 10, v8::StackTrace::kDetailed);
17694 CHECK_EQ(4, stackTrace->GetFrameCount());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017695 v8::Local<v8::String> url = v8_str("source_url");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017696 for (int i = 0; i < 3; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017697 v8::Local<v8::String> name =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017698 stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
17699 CHECK(!name.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017700 CHECK(url->Equals(args.GetIsolate()->GetCurrentContext(), name).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017701 }
17702}
17703
17704
17705TEST(DynamicWithSourceURLInStackTrace) {
17706 v8::Isolate* isolate = CcTest::isolate();
17707 v8::HandleScope scope(isolate);
17708 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
17709 templ->Set(v8_str("AnalyzeStackOfDynamicScriptWithSourceURL"),
17710 v8::FunctionTemplate::New(
17711 CcTest::isolate(), AnalyzeStackOfDynamicScriptWithSourceURL));
17712 LocalContext context(0, templ);
17713
17714 const char *source =
17715 "function outer() {\n"
17716 "function bar() {\n"
17717 " AnalyzeStackOfDynamicScriptWithSourceURL();\n"
17718 "}\n"
17719 "function foo() {\n"
17720 "\n"
17721 " bar();\n"
17722 "}\n"
17723 "foo();\n"
17724 "}\n"
17725 "outer()\n%s";
17726
17727 i::ScopedVector<char> code(1024);
17728 i::SNPrintF(code, source, "//# sourceURL=source_url");
17729 CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined());
17730 i::SNPrintF(code, source, "//@ sourceURL=source_url");
17731 CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined());
17732}
17733
17734
17735TEST(DynamicWithSourceURLInStackTraceString) {
17736 LocalContext context;
17737 v8::HandleScope scope(context->GetIsolate());
17738
17739 const char *source =
17740 "function outer() {\n"
17741 " function foo() {\n"
17742 " FAIL.FAIL;\n"
17743 " }\n"
17744 " foo();\n"
17745 "}\n"
17746 "outer()\n%s";
17747
17748 i::ScopedVector<char> code(1024);
17749 i::SNPrintF(code, source, "//# sourceURL=source_url");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017750 v8::TryCatch try_catch(context->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017751 CompileRunWithOrigin(code.start(), "", 0, 0);
17752 CHECK(try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017753 v8::String::Utf8Value stack(
17754 try_catch.StackTrace(context.local()).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017755 CHECK(strstr(*stack, "at foo (source_url:3:5)") != NULL);
17756}
17757
17758
17759TEST(EvalWithSourceURLInMessageScriptResourceNameOrSourceURL) {
17760 LocalContext context;
17761 v8::HandleScope scope(context->GetIsolate());
17762
17763 const char *source =
17764 "function outer() {\n"
17765 " var scriptContents = \"function foo() { FAIL.FAIL; }\\\n"
17766 " //# sourceURL=source_url\";\n"
17767 " eval(scriptContents);\n"
17768 " foo(); }\n"
17769 "outer();\n"
17770 "//# sourceURL=outer_url";
17771
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017772 v8::TryCatch try_catch(context->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017773 CompileRun(source);
17774 CHECK(try_catch.HasCaught());
17775
17776 Local<v8::Message> message = try_catch.Message();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017777 Local<Value> sourceURL = message->GetScriptOrigin().ResourceName();
17778 CHECK_EQ(0, strcmp(*v8::String::Utf8Value(sourceURL), "source_url"));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017779}
17780
17781
17782TEST(RecursionWithSourceURLInMessageScriptResourceNameOrSourceURL) {
17783 LocalContext context;
17784 v8::HandleScope scope(context->GetIsolate());
17785
17786 const char *source =
17787 "function outer() {\n"
17788 " var scriptContents = \"function boo(){ boo(); }\\\n"
17789 " //# sourceURL=source_url\";\n"
17790 " eval(scriptContents);\n"
17791 " boo(); }\n"
17792 "outer();\n"
17793 "//# sourceURL=outer_url";
17794
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017795 v8::TryCatch try_catch(context->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017796 CompileRun(source);
17797 CHECK(try_catch.HasCaught());
17798
17799 Local<v8::Message> message = try_catch.Message();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017800 Local<Value> sourceURL = message->GetScriptOrigin().ResourceName();
17801 CHECK_EQ(0, strcmp(*v8::String::Utf8Value(sourceURL), "source_url"));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017802}
17803
17804
17805static void CreateGarbageInOldSpace() {
17806 i::Factory* factory = CcTest::i_isolate()->factory();
17807 v8::HandleScope scope(CcTest::isolate());
17808 i::AlwaysAllocateScope always_allocate(CcTest::i_isolate());
17809 for (int i = 0; i < 1000; i++) {
17810 factory->NewFixedArray(1000, i::TENURED);
17811 }
Ben Murdochf87a2032010-10-22 12:50:53 +010017812}
17813
17814
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017815// Test that idle notification can be handled and eventually collects garbage.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017816TEST(TestIdleNotification) {
17817 if (!i::FLAG_incremental_marking) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017818 const intptr_t MB = 1024 * 1024;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017819 const double IdlePauseInSeconds = 1.0;
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017820 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017821 v8::HandleScope scope(env->GetIsolate());
17822 intptr_t initial_size = CcTest::heap()->SizeOfObjects();
17823 CreateGarbageInOldSpace();
17824 intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
17825 CHECK_GT(size_with_garbage, initial_size + MB);
17826 bool finished = false;
17827 for (int i = 0; i < 200 && !finished; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017828 if (i < 10 && CcTest::heap()->incremental_marking()->IsStopped()) {
17829 CcTest::heap()->StartIdleIncrementalMarking();
17830 }
17831 finished = env->GetIsolate()->IdleNotificationDeadline(
17832 (v8::base::TimeTicks::HighResolutionNow().ToInternalValue() /
17833 static_cast<double>(v8::base::Time::kMicrosecondsPerSecond)) +
17834 IdlePauseInSeconds);
17835 if (CcTest::heap()->mark_compact_collector()->sweeping_in_progress()) {
17836 CcTest::heap()->mark_compact_collector()->EnsureSweepingCompleted();
17837 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017838 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017839 intptr_t final_size = CcTest::heap()->SizeOfObjects();
17840 CHECK(finished);
17841 CHECK_LT(final_size, initial_size + 1);
Ben Murdochc7cc0282012-03-05 14:35:55 +000017842}
17843
Steve Blocka7e24c12009-10-30 11:49:00 +000017844
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017845TEST(Regress2333) {
17846 LocalContext env;
17847 for (int i = 0; i < 3; i++) {
17848 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
17849 }
17850}
17851
Steve Blocka7e24c12009-10-30 11:49:00 +000017852static uint32_t* stack_limit;
17853
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017854static void GetStackLimitCallback(
17855 const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Block44f0eee2011-05-26 01:26:41 +010017856 stack_limit = reinterpret_cast<uint32_t*>(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017857 CcTest::i_isolate()->stack_guard()->real_climit());
Steve Blocka7e24c12009-10-30 11:49:00 +000017858}
17859
17860
17861// Uses the address of a local variable to determine the stack top now.
17862// Given a size, returns an address that is that far from the current
17863// top of stack.
17864static uint32_t* ComputeStackLimit(uint32_t size) {
17865 uint32_t* answer = &size - (size / sizeof(size));
17866 // If the size is very large and the stack is very near the bottom of
17867 // memory then the calculation above may wrap around and give an address
17868 // that is above the (downwards-growing) stack. In that case we return
17869 // a very low address.
17870 if (answer > &size) return reinterpret_cast<uint32_t*>(sizeof(size));
17871 return answer;
17872}
17873
17874
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017875// We need at least 165kB for an x64 debug build with clang and ASAN.
17876static const int stack_breathing_room = 256 * i::KB;
17877
17878
17879TEST(SetStackLimit) {
17880 uint32_t* set_limit = ComputeStackLimit(stack_breathing_room);
Steve Blocka7e24c12009-10-30 11:49:00 +000017881
17882 // Set stack limit.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017883 CcTest::isolate()->SetStackLimit(reinterpret_cast<uintptr_t>(set_limit));
Steve Blocka7e24c12009-10-30 11:49:00 +000017884
17885 // Execute a script.
Steve Blocka7e24c12009-10-30 11:49:00 +000017886 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017887 v8::HandleScope scope(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000017888 Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017889 v8::FunctionTemplate::New(env->GetIsolate(), GetStackLimitCallback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017890 Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
17891 CHECK(env->Global()
17892 ->Set(env.local(), v8_str("get_stack_limit"), fun)
17893 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000017894 CompileRun("get_stack_limit();");
17895
17896 CHECK(stack_limit == set_limit);
17897}
17898
17899
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017900TEST(SetStackLimitInThread) {
Steve Blocka7e24c12009-10-30 11:49:00 +000017901 uint32_t* set_limit;
17902 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017903 v8::Locker locker(CcTest::isolate());
17904 set_limit = ComputeStackLimit(stack_breathing_room);
Steve Blocka7e24c12009-10-30 11:49:00 +000017905
17906 // Set stack limit.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017907 CcTest::isolate()->SetStackLimit(reinterpret_cast<uintptr_t>(set_limit));
Steve Blocka7e24c12009-10-30 11:49:00 +000017908
17909 // Execute a script.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017910 v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000017911 LocalContext env;
17912 Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017913 v8::FunctionTemplate::New(CcTest::isolate(), GetStackLimitCallback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017914 Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
17915 CHECK(env->Global()
17916 ->Set(env.local(), v8_str("get_stack_limit"), fun)
17917 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000017918 CompileRun("get_stack_limit();");
17919
17920 CHECK(stack_limit == set_limit);
17921 }
17922 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017923 v8::Locker locker(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000017924 CHECK(stack_limit == set_limit);
17925 }
17926}
Steve Block3ce2e202009-11-05 08:53:23 +000017927
17928
17929THREADED_TEST(GetHeapStatistics) {
Steve Block3ce2e202009-11-05 08:53:23 +000017930 LocalContext c1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017931 v8::HandleScope scope(c1->GetIsolate());
Steve Block3ce2e202009-11-05 08:53:23 +000017932 v8::HeapStatistics heap_statistics;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017933 CHECK_EQ(0u, heap_statistics.total_heap_size());
17934 CHECK_EQ(0u, heap_statistics.used_heap_size());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017935 c1->GetIsolate()->GetHeapStatistics(&heap_statistics);
Steve Blockd0582a62009-12-15 09:54:21 +000017936 CHECK_NE(static_cast<int>(heap_statistics.total_heap_size()), 0);
17937 CHECK_NE(static_cast<int>(heap_statistics.used_heap_size()), 0);
17938}
17939
17940
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017941class VisitorImpl : public v8::ExternalResourceVisitor {
17942 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017943 explicit VisitorImpl(TestResource** resource) {
17944 for (int i = 0; i < 4; i++) {
17945 resource_[i] = resource[i];
17946 found_resource_[i] = false;
17947 }
17948 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017949 virtual ~VisitorImpl() {}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017950 virtual void VisitExternalString(v8::Local<v8::String> string) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017951 if (!string->IsExternal()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017952 CHECK(string->IsExternalOneByte());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017953 return;
17954 }
17955 v8::String::ExternalStringResource* resource =
17956 string->GetExternalStringResource();
17957 CHECK(resource);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017958 for (int i = 0; i < 4; i++) {
17959 if (resource_[i] == resource) {
17960 CHECK(!found_resource_[i]);
17961 found_resource_[i] = true;
17962 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017963 }
17964 }
17965 void CheckVisitedResources() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017966 for (int i = 0; i < 4; i++) {
17967 CHECK(found_resource_[i]);
17968 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017969 }
17970
17971 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017972 v8::String::ExternalStringResource* resource_[4];
17973 bool found_resource_[4];
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017974};
17975
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017976
17977TEST(ExternalizeOldSpaceTwoByteCons) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017978 v8::Isolate* isolate = CcTest::isolate();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017979 LocalContext env;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017980 v8::HandleScope scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017981 v8::Local<v8::String> cons =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017982 CompileRun("'Romeo Montague ' + 'Juliet Capulet'")
17983 ->ToString(env.local())
17984 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017985 CHECK(v8::Utils::OpenHandle(*cons)->IsConsString());
17986 CcTest::heap()->CollectAllAvailableGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017987 CHECK(CcTest::heap()->old_space()->Contains(*v8::Utils::OpenHandle(*cons)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017988
17989 TestResource* resource = new TestResource(
17990 AsciiToTwoByteString("Romeo Montague Juliet Capulet"));
17991 cons->MakeExternal(resource);
17992
17993 CHECK(cons->IsExternal());
17994 CHECK_EQ(resource, cons->GetExternalStringResource());
17995 String::Encoding encoding;
17996 CHECK_EQ(resource, cons->GetExternalStringResourceBase(&encoding));
17997 CHECK_EQ(String::TWO_BYTE_ENCODING, encoding);
17998}
17999
18000
18001TEST(ExternalizeOldSpaceOneByteCons) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040018002 v8::Isolate* isolate = CcTest::isolate();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018003 LocalContext env;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040018004 v8::HandleScope scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018005 v8::Local<v8::String> cons =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018006 CompileRun("'Romeo Montague ' + 'Juliet Capulet'")
18007 ->ToString(env.local())
18008 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018009 CHECK(v8::Utils::OpenHandle(*cons)->IsConsString());
18010 CcTest::heap()->CollectAllAvailableGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018011 CHECK(CcTest::heap()->old_space()->Contains(*v8::Utils::OpenHandle(*cons)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018012
18013 TestOneByteResource* resource =
18014 new TestOneByteResource(i::StrDup("Romeo Montague Juliet Capulet"));
18015 cons->MakeExternal(resource);
18016
18017 CHECK(cons->IsExternalOneByte());
18018 CHECK_EQ(resource, cons->GetExternalOneByteStringResource());
18019 String::Encoding encoding;
18020 CHECK_EQ(resource, cons->GetExternalStringResourceBase(&encoding));
18021 CHECK_EQ(String::ONE_BYTE_ENCODING, encoding);
18022}
18023
18024
18025TEST(VisitExternalStrings) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040018026 v8::Isolate* isolate = CcTest::isolate();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018027 LocalContext env;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040018028 v8::HandleScope scope(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018029 const char* string = "Some string";
18030 uint16_t* two_byte_string = AsciiToTwoByteString(string);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018031 TestResource* resource[4];
18032 resource[0] = new TestResource(two_byte_string);
18033 v8::Local<v8::String> string0 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018034 v8::String::NewExternalTwoByte(env->GetIsolate(), resource[0])
18035 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018036 resource[1] = new TestResource(two_byte_string, NULL, false);
18037 v8::Local<v8::String> string1 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018038 v8::String::NewExternalTwoByte(env->GetIsolate(), resource[1])
18039 .ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018040
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018041 // Externalized symbol.
18042 resource[2] = new TestResource(two_byte_string, NULL, false);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018043 v8::Local<v8::String> string2 =
18044 v8::String::NewFromUtf8(env->GetIsolate(), string,
18045 v8::NewStringType::kInternalized)
18046 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018047 CHECK(string2->MakeExternal(resource[2]));
18048
18049 // Symbolized External.
18050 resource[3] = new TestResource(AsciiToTwoByteString("Some other string"));
18051 v8::Local<v8::String> string3 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018052 v8::String::NewExternalTwoByte(env->GetIsolate(), resource[3])
18053 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018054 CcTest::heap()->CollectAllAvailableGarbage(); // Tenure string.
18055 // Turn into a symbol.
18056 i::Handle<i::String> string3_i = v8::Utils::OpenHandle(*string3);
18057 CHECK(!CcTest::i_isolate()->factory()->InternalizeString(
18058 string3_i).is_null());
18059 CHECK(string3_i->IsInternalizedString());
18060
18061 // We need to add usages for string* to avoid warnings in GCC 4.7
18062 CHECK(string0->IsExternal());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018063 CHECK(string1->IsExternal());
18064 CHECK(string2->IsExternal());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018065 CHECK(string3->IsExternal());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018066
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018067 VisitorImpl visitor(resource);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018068 isolate->VisitExternalResources(&visitor);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018069 visitor.CheckVisitedResources();
18070}
18071
18072
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018073TEST(ExternalStringCollectedAtTearDown) {
18074 int destroyed = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018075 v8::Isolate::CreateParams create_params;
18076 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
18077 v8::Isolate* isolate = v8::Isolate::New(create_params);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018078 { v8::Isolate::Scope isolate_scope(isolate);
18079 v8::HandleScope handle_scope(isolate);
18080 const char* s = "One string to test them all, one string to find them.";
18081 TestOneByteResource* inscription =
18082 new TestOneByteResource(i::StrDup(s), &destroyed);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018083 v8::Local<v8::String> ring =
18084 v8::String::NewExternalOneByte(isolate, inscription).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018085 // Ring is still alive. Orcs are roaming freely across our lands.
18086 CHECK_EQ(0, destroyed);
18087 USE(ring);
18088 }
18089
18090 isolate->Dispose();
18091 // Ring has been destroyed. Free Peoples of Middle-earth Rejoice.
18092 CHECK_EQ(1, destroyed);
18093}
18094
18095
18096TEST(ExternalInternalizedStringCollectedAtTearDown) {
18097 int destroyed = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018098 v8::Isolate::CreateParams create_params;
18099 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
18100 v8::Isolate* isolate = v8::Isolate::New(create_params);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018101 { v8::Isolate::Scope isolate_scope(isolate);
18102 LocalContext env(isolate);
18103 v8::HandleScope handle_scope(isolate);
18104 CompileRun("var ring = 'One string to test them all';");
18105 const char* s = "One string to test them all";
18106 TestOneByteResource* inscription =
18107 new TestOneByteResource(i::StrDup(s), &destroyed);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018108 v8::Local<v8::String> ring =
18109 CompileRun("ring")->ToString(env.local()).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018110 CHECK(v8::Utils::OpenHandle(*ring)->IsInternalizedString());
18111 ring->MakeExternal(inscription);
18112 // Ring is still alive. Orcs are roaming freely across our lands.
18113 CHECK_EQ(0, destroyed);
18114 USE(ring);
18115 }
18116
18117 isolate->Dispose();
18118 // Ring has been destroyed. Free Peoples of Middle-earth Rejoice.
18119 CHECK_EQ(1, destroyed);
18120}
18121
18122
18123TEST(ExternalInternalizedStringCollectedAtGC) {
18124 int destroyed = 0;
18125 { LocalContext env;
18126 v8::HandleScope handle_scope(env->GetIsolate());
18127 CompileRun("var ring = 'One string to test them all';");
18128 const char* s = "One string to test them all";
18129 TestOneByteResource* inscription =
18130 new TestOneByteResource(i::StrDup(s), &destroyed);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040018131 v8::Local<v8::String> ring = CompileRun("ring").As<v8::String>();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018132 CHECK(v8::Utils::OpenHandle(*ring)->IsInternalizedString());
18133 ring->MakeExternal(inscription);
18134 // Ring is still alive. Orcs are roaming freely across our lands.
18135 CHECK_EQ(0, destroyed);
18136 USE(ring);
18137 }
18138
18139 // Garbage collector deals swift blows to evil.
18140 CcTest::i_isolate()->compilation_cache()->Clear();
18141 CcTest::heap()->CollectAllAvailableGarbage();
18142
18143 // Ring has been destroyed. Free Peoples of Middle-earth Rejoice.
18144 CHECK_EQ(1, destroyed);
18145}
18146
18147
Steve Blockd0582a62009-12-15 09:54:21 +000018148static double DoubleFromBits(uint64_t value) {
18149 double target;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018150 i::MemCopy(&target, &value, sizeof(target));
Steve Blockd0582a62009-12-15 09:54:21 +000018151 return target;
18152}
18153
18154
18155static uint64_t DoubleToBits(double value) {
18156 uint64_t target;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018157 i::MemCopy(&target, &value, sizeof(target));
Steve Blockd0582a62009-12-15 09:54:21 +000018158 return target;
18159}
18160
18161
18162static double DoubleToDateTime(double input) {
18163 double date_limit = 864e13;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018164 if (std::isnan(input) || input < -date_limit || input > date_limit) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018165 return std::numeric_limits<double>::quiet_NaN();
Steve Blockd0582a62009-12-15 09:54:21 +000018166 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018167 return (input < 0) ? -(std::floor(-input)) : std::floor(input);
Steve Blockd0582a62009-12-15 09:54:21 +000018168}
18169
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018170
Steve Blockd0582a62009-12-15 09:54:21 +000018171// We don't have a consistent way to write 64-bit constants syntactically, so we
18172// split them into two 32-bit constants and combine them programmatically.
18173static double DoubleFromBits(uint32_t high_bits, uint32_t low_bits) {
18174 return DoubleFromBits((static_cast<uint64_t>(high_bits) << 32) | low_bits);
18175}
18176
18177
18178THREADED_TEST(QuietSignalingNaNs) {
Steve Blockd0582a62009-12-15 09:54:21 +000018179 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018180 v8::Isolate* isolate = context->GetIsolate();
18181 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018182 v8::TryCatch try_catch(isolate);
Steve Blockd0582a62009-12-15 09:54:21 +000018183
18184 // Special double values.
18185 double snan = DoubleFromBits(0x7ff00000, 0x00000001);
18186 double qnan = DoubleFromBits(0x7ff80000, 0x00000000);
18187 double infinity = DoubleFromBits(0x7ff00000, 0x00000000);
18188 double max_normal = DoubleFromBits(0x7fefffff, 0xffffffffu);
18189 double min_normal = DoubleFromBits(0x00100000, 0x00000000);
18190 double max_denormal = DoubleFromBits(0x000fffff, 0xffffffffu);
18191 double min_denormal = DoubleFromBits(0x00000000, 0x00000001);
18192
18193 // Date values are capped at +/-100000000 days (times 864e5 ms per day)
18194 // on either side of the epoch.
18195 double date_limit = 864e13;
18196
18197 double test_values[] = {
18198 snan,
18199 qnan,
18200 infinity,
18201 max_normal,
18202 date_limit + 1,
18203 date_limit,
18204 min_normal,
18205 max_denormal,
18206 min_denormal,
18207 0,
18208 -0,
18209 -min_denormal,
18210 -max_denormal,
18211 -min_normal,
18212 -date_limit,
18213 -date_limit - 1,
18214 -max_normal,
18215 -infinity,
18216 -qnan,
18217 -snan
18218 };
18219 int num_test_values = 20;
18220
18221 for (int i = 0; i < num_test_values; i++) {
18222 double test_value = test_values[i];
18223
18224 // Check that Number::New preserves non-NaNs and quiets SNaNs.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018225 v8::Local<v8::Value> number = v8::Number::New(isolate, test_value);
18226 double stored_number = number->NumberValue(context.local()).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018227 if (!std::isnan(test_value)) {
Steve Blockd0582a62009-12-15 09:54:21 +000018228 CHECK_EQ(test_value, stored_number);
18229 } else {
18230 uint64_t stored_bits = DoubleToBits(stored_number);
18231 // Check if quiet nan (bits 51..62 all set).
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018232#if (defined(V8_TARGET_ARCH_MIPS) || defined(V8_TARGET_ARCH_MIPS64)) && \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018233 !defined(_MIPS_ARCH_MIPS64R6) && !defined(_MIPS_ARCH_MIPS32R6) && \
18234 !defined(USE_SIMULATOR)
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018235 // Most significant fraction bit for quiet nan is set to 0
18236 // on MIPS architecture. Allowed by IEEE-754.
18237 CHECK_EQ(0xffe, static_cast<int>((stored_bits >> 51) & 0xfff));
18238#else
Steve Blockd0582a62009-12-15 09:54:21 +000018239 CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff));
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018240#endif
Steve Blockd0582a62009-12-15 09:54:21 +000018241 }
18242
18243 // Check that Date::New preserves non-NaNs in the date range and
18244 // quiets SNaNs.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018245 v8::Local<v8::Value> date =
18246 v8::Date::New(context.local(), test_value).ToLocalChecked();
Steve Blockd0582a62009-12-15 09:54:21 +000018247 double expected_stored_date = DoubleToDateTime(test_value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018248 double stored_date = date->NumberValue(context.local()).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018249 if (!std::isnan(expected_stored_date)) {
Steve Blockd0582a62009-12-15 09:54:21 +000018250 CHECK_EQ(expected_stored_date, stored_date);
18251 } else {
18252 uint64_t stored_bits = DoubleToBits(stored_date);
18253 // Check if quiet nan (bits 51..62 all set).
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018254#if (defined(V8_TARGET_ARCH_MIPS) || defined(V8_TARGET_ARCH_MIPS64)) && \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018255 !defined(_MIPS_ARCH_MIPS64R6) && !defined(_MIPS_ARCH_MIPS32R6) && \
18256 !defined(USE_SIMULATOR)
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018257 // Most significant fraction bit for quiet nan is set to 0
18258 // on MIPS architecture. Allowed by IEEE-754.
18259 CHECK_EQ(0xffe, static_cast<int>((stored_bits >> 51) & 0xfff));
18260#else
Steve Blockd0582a62009-12-15 09:54:21 +000018261 CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff));
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018262#endif
Steve Blockd0582a62009-12-15 09:54:21 +000018263 }
18264 }
18265}
18266
18267
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018268static void SpaghettiIncident(
18269 const v8::FunctionCallbackInfo<v8::Value>& args) {
18270 v8::HandleScope scope(args.GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018271 v8::TryCatch tc(args.GetIsolate());
18272 v8::MaybeLocal<v8::String> str(
18273 args[0]->ToString(args.GetIsolate()->GetCurrentContext()));
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018274 USE(str);
Steve Blockd0582a62009-12-15 09:54:21 +000018275 if (tc.HasCaught())
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018276 tc.ReThrow();
Steve Blockd0582a62009-12-15 09:54:21 +000018277}
18278
18279
18280// Test that an exception can be propagated down through a spaghetti
18281// stack using ReThrow.
18282THREADED_TEST(SpaghettiStackReThrow) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018283 v8::Isolate* isolate = CcTest::isolate();
18284 v8::HandleScope scope(isolate);
Steve Blockd0582a62009-12-15 09:54:21 +000018285 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018286 context->Global()
18287 ->Set(context.local(), v8_str("s"),
18288 v8::FunctionTemplate::New(isolate, SpaghettiIncident)
18289 ->GetFunction(context.local())
18290 .ToLocalChecked())
18291 .FromJust();
18292 v8::TryCatch try_catch(isolate);
Steve Blockd0582a62009-12-15 09:54:21 +000018293 CompileRun(
18294 "var i = 0;"
18295 "var o = {"
18296 " toString: function () {"
18297 " if (i == 10) {"
18298 " throw 'Hey!';"
18299 " } else {"
18300 " i++;"
18301 " return s(o);"
18302 " }"
18303 " }"
18304 "};"
18305 "s(o);");
18306 CHECK(try_catch.HasCaught());
18307 v8::String::Utf8Value value(try_catch.Exception());
18308 CHECK_EQ(0, strcmp(*value, "Hey!"));
18309}
18310
18311
Steve Blockd0582a62009-12-15 09:54:21 +000018312TEST(Regress528) {
18313 v8::V8::Initialize();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018314 v8::Isolate* isolate = CcTest::isolate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018315 i::FLAG_retain_maps_for_n_gc = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018316 v8::HandleScope scope(isolate);
18317 v8::Local<Context> other_context;
Steve Blockd0582a62009-12-15 09:54:21 +000018318 int gc_count;
18319
18320 // Create a context used to keep the code from aging in the compilation
18321 // cache.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018322 other_context = Context::New(isolate);
Steve Blockd0582a62009-12-15 09:54:21 +000018323
18324 // Context-dependent context data creates reference from the compilation
18325 // cache to the global object.
18326 const char* source_simple = "1";
Steve Blockd0582a62009-12-15 09:54:21 +000018327 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018328 v8::HandleScope scope(isolate);
18329 v8::Local<Context> context = Context::New(isolate);
Steve Blockd0582a62009-12-15 09:54:21 +000018330
18331 context->Enter();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018332 Local<v8::String> obj = v8_str("");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018333 context->SetEmbedderData(0, obj);
Steve Blockd0582a62009-12-15 09:54:21 +000018334 CompileRun(source_simple);
18335 context->Exit();
18336 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018337 isolate->ContextDisposedNotification();
Steve Blockd0582a62009-12-15 09:54:21 +000018338 for (gc_count = 1; gc_count < 10; gc_count++) {
18339 other_context->Enter();
18340 CompileRun(source_simple);
18341 other_context->Exit();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018342 CcTest::heap()->CollectAllGarbage();
Steve Blockd0582a62009-12-15 09:54:21 +000018343 if (GetGlobalObjectsCount() == 1) break;
18344 }
18345 CHECK_GE(2, gc_count);
18346 CHECK_EQ(1, GetGlobalObjectsCount());
18347
18348 // Eval in a function creates reference from the compilation cache to the
18349 // global object.
18350 const char* source_eval = "function f(){eval('1')}; f()";
Steve Blockd0582a62009-12-15 09:54:21 +000018351 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018352 v8::HandleScope scope(isolate);
18353 v8::Local<Context> context = Context::New(isolate);
Steve Blockd0582a62009-12-15 09:54:21 +000018354
18355 context->Enter();
18356 CompileRun(source_eval);
18357 context->Exit();
18358 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018359 isolate->ContextDisposedNotification();
Steve Blockd0582a62009-12-15 09:54:21 +000018360 for (gc_count = 1; gc_count < 10; gc_count++) {
18361 other_context->Enter();
18362 CompileRun(source_eval);
18363 other_context->Exit();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018364 CcTest::heap()->CollectAllGarbage();
Steve Blockd0582a62009-12-15 09:54:21 +000018365 if (GetGlobalObjectsCount() == 1) break;
18366 }
18367 CHECK_GE(2, gc_count);
18368 CHECK_EQ(1, GetGlobalObjectsCount());
18369
18370 // Looking up the line number for an exception creates reference from the
18371 // compilation cache to the global object.
18372 const char* source_exception = "function f(){throw 1;} f()";
Steve Blockd0582a62009-12-15 09:54:21 +000018373 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018374 v8::HandleScope scope(isolate);
18375 v8::Local<Context> context = Context::New(isolate);
Steve Blockd0582a62009-12-15 09:54:21 +000018376
18377 context->Enter();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018378 v8::TryCatch try_catch(isolate);
Steve Blockd0582a62009-12-15 09:54:21 +000018379 CompileRun(source_exception);
18380 CHECK(try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018381 v8::Local<v8::Message> message = try_catch.Message();
Steve Blockd0582a62009-12-15 09:54:21 +000018382 CHECK(!message.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018383 CHECK_EQ(1, message->GetLineNumber(context).FromJust());
Steve Blockd0582a62009-12-15 09:54:21 +000018384 context->Exit();
18385 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018386 isolate->ContextDisposedNotification();
Steve Blockd0582a62009-12-15 09:54:21 +000018387 for (gc_count = 1; gc_count < 10; gc_count++) {
18388 other_context->Enter();
18389 CompileRun(source_exception);
18390 other_context->Exit();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018391 CcTest::heap()->CollectAllGarbage();
Steve Blockd0582a62009-12-15 09:54:21 +000018392 if (GetGlobalObjectsCount() == 1) break;
18393 }
18394 CHECK_GE(2, gc_count);
18395 CHECK_EQ(1, GetGlobalObjectsCount());
18396
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018397 isolate->ContextDisposedNotification();
Steve Block3ce2e202009-11-05 08:53:23 +000018398}
Andrei Popescu402d9372010-02-26 13:31:12 +000018399
18400
18401THREADED_TEST(ScriptOrigin) {
Andrei Popescu402d9372010-02-26 13:31:12 +000018402 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018403 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018404 v8::ScriptOrigin origin = v8::ScriptOrigin(
18405 v8_str("test"), v8::Integer::New(env->GetIsolate(), 1),
18406 v8::Integer::New(env->GetIsolate(), 1), v8::True(env->GetIsolate()),
18407 v8::Local<v8::Integer>(), v8::True(env->GetIsolate()),
18408 v8_str("http://sourceMapUrl"), v8::True(env->GetIsolate()));
18409 v8::Local<v8::String> script = v8_str("function f() {}\n\nfunction g() {}");
18410 v8::Script::Compile(env.local(), script, &origin)
18411 .ToLocalChecked()
18412 ->Run(env.local())
18413 .ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000018414 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018415 env->Global()->Get(env.local(), v8_str("f")).ToLocalChecked());
Andrei Popescu402d9372010-02-26 13:31:12 +000018416 v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018417 env->Global()->Get(env.local(), v8_str("g")).ToLocalChecked());
Andrei Popescu402d9372010-02-26 13:31:12 +000018418
18419 v8::ScriptOrigin script_origin_f = f->GetScriptOrigin();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018420 CHECK_EQ(0, strcmp("test",
18421 *v8::String::Utf8Value(script_origin_f.ResourceName())));
18422 CHECK_EQ(
18423 1,
18424 script_origin_f.ResourceLineOffset()->Int32Value(env.local()).FromJust());
18425 CHECK(script_origin_f.Options().IsSharedCrossOrigin());
18426 CHECK(script_origin_f.Options().IsEmbedderDebugScript());
18427 CHECK(script_origin_f.Options().IsOpaque());
18428 printf("is name = %d\n", script_origin_f.SourceMapUrl()->IsUndefined());
18429
18430 CHECK_EQ(0, strcmp("http://sourceMapUrl",
18431 *v8::String::Utf8Value(script_origin_f.SourceMapUrl())));
Andrei Popescu402d9372010-02-26 13:31:12 +000018432
18433 v8::ScriptOrigin script_origin_g = g->GetScriptOrigin();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018434 CHECK_EQ(0, strcmp("test",
18435 *v8::String::Utf8Value(script_origin_g.ResourceName())));
18436 CHECK_EQ(
18437 1,
18438 script_origin_g.ResourceLineOffset()->Int32Value(env.local()).FromJust());
18439 CHECK(script_origin_g.Options().IsSharedCrossOrigin());
18440 CHECK(script_origin_g.Options().IsEmbedderDebugScript());
18441 CHECK(script_origin_g.Options().IsOpaque());
18442 CHECK_EQ(0, strcmp("http://sourceMapUrl",
18443 *v8::String::Utf8Value(script_origin_g.SourceMapUrl())));
Andrei Popescu402d9372010-02-26 13:31:12 +000018444}
18445
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018446
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018447THREADED_TEST(FunctionGetInferredName) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018448 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018449 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018450 v8::ScriptOrigin origin = v8::ScriptOrigin(v8_str("test"));
18451 v8::Local<v8::String> script =
18452 v8_str("var foo = { bar : { baz : function() {}}}; var f = foo.bar.baz;");
18453 v8::Script::Compile(env.local(), script, &origin)
18454 .ToLocalChecked()
18455 ->Run(env.local())
18456 .ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018457 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018458 env->Global()->Get(env.local(), v8_str("f")).ToLocalChecked());
18459 CHECK_EQ(0,
18460 strcmp("foo.bar.baz", *v8::String::Utf8Value(f->GetInferredName())));
18461}
18462
18463
18464THREADED_TEST(FunctionGetDebugName) {
Ben Murdochda12d292016-06-02 14:46:10 +010018465 i::FLAG_harmony_function_name = true;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018466 LocalContext env;
18467 v8::HandleScope scope(env->GetIsolate());
18468 const char* code =
18469 "var error = false;"
18470 "function a() { this.x = 1; };"
18471 "a.displayName = 'display_a';"
18472 "var b = (function() {"
18473 " var f = function() { this.x = 2; };"
18474 " f.displayName = 'display_b';"
18475 " return f;"
18476 "})();"
18477 "var c = function() {};"
18478 "c.__defineGetter__('displayName', function() {"
18479 " error = true;"
18480 " throw new Error();"
18481 "});"
18482 "function d() {};"
18483 "d.__defineGetter__('displayName', function() {"
18484 " error = true;"
18485 " return 'wrong_display_name';"
18486 "});"
18487 "function e() {};"
18488 "e.displayName = 'wrong_display_name';"
18489 "e.__defineSetter__('displayName', function() {"
18490 " error = true;"
18491 " throw new Error();"
18492 "});"
18493 "function f() {};"
18494 "f.displayName = { 'foo': 6, toString: function() {"
18495 " error = true;"
18496 " return 'wrong_display_name';"
18497 "}};"
18498 "var g = function() {"
18499 " arguments.callee.displayName = 'set_in_runtime';"
18500 "}; g();"
18501 "var h = function() {};"
18502 "h.displayName = 'displayName';"
18503 "Object.defineProperty(h, 'name', { value: 'function.name' });"
18504 "var i = function() {};"
18505 "i.displayName = 239;"
18506 "Object.defineProperty(i, 'name', { value: 'function.name' });"
18507 "var j = function() {};"
18508 "Object.defineProperty(j, 'name', { value: 'function.name' });"
Ben Murdochda12d292016-06-02 14:46:10 +010018509 "var foo = { bar : { baz : (0, function() {})}}; var k = foo.bar.baz;"
18510 "var foo = { bar : { baz : function() {} }}; var l = foo.bar.baz;";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018511 v8::ScriptOrigin origin = v8::ScriptOrigin(v8_str("test"));
18512 v8::Script::Compile(env.local(), v8_str(code), &origin)
18513 .ToLocalChecked()
18514 ->Run(env.local())
18515 .ToLocalChecked();
18516 v8::Local<v8::Value> error =
18517 env->Global()->Get(env.local(), v8_str("error")).ToLocalChecked();
18518 CHECK_EQ(false, error->BooleanValue(env.local()).FromJust());
18519 const char* functions[] = {"a", "display_a",
18520 "b", "display_b",
18521 "c", "c",
18522 "d", "d",
18523 "e", "e",
18524 "f", "f",
18525 "g", "set_in_runtime",
18526 "h", "displayName",
18527 "i", "function.name",
18528 "j", "function.name",
Ben Murdochda12d292016-06-02 14:46:10 +010018529 "k", "foo.bar.baz",
18530 "l", "baz"};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018531 for (size_t i = 0; i < sizeof(functions) / sizeof(functions[0]) / 2; ++i) {
18532 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
18533 env->Global()
18534 ->Get(env.local(),
18535 v8::String::NewFromUtf8(env->GetIsolate(), functions[i * 2],
18536 v8::NewStringType::kNormal)
18537 .ToLocalChecked())
18538 .ToLocalChecked());
18539 CHECK_EQ(0, strcmp(functions[i * 2 + 1],
18540 *v8::String::Utf8Value(f->GetDebugName())));
18541 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018542}
Andrei Popescu402d9372010-02-26 13:31:12 +000018543
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018544
18545THREADED_TEST(FunctionGetDisplayName) {
Andrei Popescu402d9372010-02-26 13:31:12 +000018546 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018547 v8::HandleScope scope(env->GetIsolate());
18548 const char* code = "var error = false;"
18549 "function a() { this.x = 1; };"
18550 "a.displayName = 'display_a';"
18551 "var b = (function() {"
18552 " var f = function() { this.x = 2; };"
18553 " f.displayName = 'display_b';"
18554 " return f;"
18555 "})();"
18556 "var c = function() {};"
18557 "c.__defineGetter__('displayName', function() {"
18558 " error = true;"
18559 " throw new Error();"
18560 "});"
18561 "function d() {};"
18562 "d.__defineGetter__('displayName', function() {"
18563 " error = true;"
18564 " return 'wrong_display_name';"
18565 "});"
18566 "function e() {};"
18567 "e.displayName = 'wrong_display_name';"
18568 "e.__defineSetter__('displayName', function() {"
18569 " error = true;"
18570 " throw new Error();"
18571 "});"
18572 "function f() {};"
18573 "f.displayName = { 'foo': 6, toString: function() {"
18574 " error = true;"
18575 " return 'wrong_display_name';"
18576 "}};"
18577 "var g = function() {"
18578 " arguments.callee.displayName = 'set_in_runtime';"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018579 "}; g();";
18580 v8::ScriptOrigin origin = v8::ScriptOrigin(v8_str("test"));
18581 v8::Script::Compile(env.local(), v8_str(code), &origin)
18582 .ToLocalChecked()
18583 ->Run(env.local())
18584 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018585 v8::Local<v8::Value> error =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018586 env->Global()->Get(env.local(), v8_str("error")).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018587 v8::Local<v8::Function> a = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018588 env->Global()->Get(env.local(), v8_str("a")).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018589 v8::Local<v8::Function> b = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018590 env->Global()->Get(env.local(), v8_str("b")).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018591 v8::Local<v8::Function> c = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018592 env->Global()->Get(env.local(), v8_str("c")).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018593 v8::Local<v8::Function> d = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018594 env->Global()->Get(env.local(), v8_str("d")).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018595 v8::Local<v8::Function> e = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018596 env->Global()->Get(env.local(), v8_str("e")).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018597 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018598 env->Global()->Get(env.local(), v8_str("f")).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018599 v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018600 env->Global()->Get(env.local(), v8_str("g")).ToLocalChecked());
18601 CHECK_EQ(false, error->BooleanValue(env.local()).FromJust());
18602 CHECK_EQ(0, strcmp("display_a", *v8::String::Utf8Value(a->GetDisplayName())));
18603 CHECK_EQ(0, strcmp("display_b", *v8::String::Utf8Value(b->GetDisplayName())));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018604 CHECK(c->GetDisplayName()->IsUndefined());
18605 CHECK(d->GetDisplayName()->IsUndefined());
18606 CHECK(e->GetDisplayName()->IsUndefined());
18607 CHECK(f->GetDisplayName()->IsUndefined());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018608 CHECK_EQ(
18609 0, strcmp("set_in_runtime", *v8::String::Utf8Value(g->GetDisplayName())));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018610}
18611
18612
18613THREADED_TEST(ScriptLineNumber) {
18614 LocalContext env;
18615 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018616 v8::ScriptOrigin origin = v8::ScriptOrigin(v8_str("test"));
18617 v8::Local<v8::String> script = v8_str("function f() {}\n\nfunction g() {}");
18618 v8::Script::Compile(env.local(), script, &origin)
18619 .ToLocalChecked()
18620 ->Run(env.local())
18621 .ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000018622 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018623 env->Global()->Get(env.local(), v8_str("f")).ToLocalChecked());
Andrei Popescu402d9372010-02-26 13:31:12 +000018624 v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018625 env->Global()->Get(env.local(), v8_str("g")).ToLocalChecked());
Andrei Popescu402d9372010-02-26 13:31:12 +000018626 CHECK_EQ(0, f->GetScriptLineNumber());
18627 CHECK_EQ(2, g->GetScriptLineNumber());
18628}
18629
18630
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018631THREADED_TEST(ScriptColumnNumber) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018632 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018633 v8::Isolate* isolate = env->GetIsolate();
18634 v8::HandleScope scope(isolate);
18635 v8::ScriptOrigin origin =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018636 v8::ScriptOrigin(v8_str("test"), v8::Integer::New(isolate, 3),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018637 v8::Integer::New(isolate, 2));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018638 v8::Local<v8::String> script =
18639 v8_str("function foo() {}\n\n function bar() {}");
18640 v8::Script::Compile(env.local(), script, &origin)
18641 .ToLocalChecked()
18642 ->Run(env.local())
18643 .ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018644 v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018645 env->Global()->Get(env.local(), v8_str("foo")).ToLocalChecked());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018646 v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018647 env->Global()->Get(env.local(), v8_str("bar")).ToLocalChecked());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018648 CHECK_EQ(14, foo->GetScriptColumnNumber());
18649 CHECK_EQ(17, bar->GetScriptColumnNumber());
18650}
18651
18652
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018653THREADED_TEST(FunctionIsBuiltin) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018654 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018655 v8::Isolate* isolate = env->GetIsolate();
18656 v8::HandleScope scope(isolate);
18657 v8::Local<v8::Function> f;
18658 f = v8::Local<v8::Function>::Cast(CompileRun("Math.floor"));
18659 CHECK(f->IsBuiltin());
18660 f = v8::Local<v8::Function>::Cast(CompileRun("Object"));
18661 CHECK(f->IsBuiltin());
18662 f = v8::Local<v8::Function>::Cast(CompileRun("Object.__defineSetter__"));
18663 CHECK(f->IsBuiltin());
18664 f = v8::Local<v8::Function>::Cast(CompileRun("Array.prototype.toString"));
18665 CHECK(f->IsBuiltin());
18666 f = v8::Local<v8::Function>::Cast(CompileRun("function a() {}; a;"));
18667 CHECK(!f->IsBuiltin());
18668}
18669
18670
18671THREADED_TEST(FunctionGetScriptId) {
18672 LocalContext env;
18673 v8::Isolate* isolate = env->GetIsolate();
18674 v8::HandleScope scope(isolate);
18675 v8::ScriptOrigin origin =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018676 v8::ScriptOrigin(v8_str("test"), v8::Integer::New(isolate, 3),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018677 v8::Integer::New(isolate, 2));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018678 v8::Local<v8::String> scriptSource =
18679 v8_str("function foo() {}\n\n function bar() {}");
18680 v8::Local<v8::Script> script(
18681 v8::Script::Compile(env.local(), scriptSource, &origin).ToLocalChecked());
18682 script->Run(env.local()).ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018683 v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018684 env->Global()->Get(env.local(), v8_str("foo")).ToLocalChecked());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018685 v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018686 env->Global()->Get(env.local(), v8_str("bar")).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018687 CHECK_EQ(script->GetUnboundScript()->GetId(), foo->ScriptId());
18688 CHECK_EQ(script->GetUnboundScript()->GetId(), bar->ScriptId());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018689}
18690
18691
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018692THREADED_TEST(FunctionGetBoundFunction) {
18693 LocalContext env;
18694 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018695 v8::ScriptOrigin origin = v8::ScriptOrigin(v8_str("test"));
18696 v8::Local<v8::String> script = v8_str(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018697 "var a = new Object();\n"
18698 "a.x = 1;\n"
18699 "function f () { return this.x };\n"
18700 "var g = f.bind(a);\n"
18701 "var b = g();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018702 v8::Script::Compile(env.local(), script, &origin)
18703 .ToLocalChecked()
18704 ->Run(env.local())
18705 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018706 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018707 env->Global()->Get(env.local(), v8_str("f")).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018708 v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018709 env->Global()->Get(env.local(), v8_str("g")).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018710 CHECK(g->GetBoundFunction()->IsFunction());
18711 Local<v8::Function> original_function = Local<v8::Function>::Cast(
18712 g->GetBoundFunction());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018713 CHECK(f->GetName()
18714 ->Equals(env.local(), original_function->GetName())
18715 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018716 CHECK_EQ(f->GetScriptLineNumber(), original_function->GetScriptLineNumber());
18717 CHECK_EQ(f->GetScriptColumnNumber(),
18718 original_function->GetScriptColumnNumber());
Andrei Popescu402d9372010-02-26 13:31:12 +000018719}
18720
18721
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018722static void GetterWhichReturns42(
18723 Local<String> name,
18724 const v8::PropertyCallbackInfo<v8::Value>& info) {
18725 CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
18726 CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
18727 info.GetReturnValue().Set(v8_num(42));
18728}
18729
18730
18731static void SetterWhichSetsYOnThisTo23(
18732 Local<String> name,
18733 Local<Value> value,
18734 const v8::PropertyCallbackInfo<void>& info) {
18735 CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
18736 CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018737 Local<Object>::Cast(info.This())
18738 ->Set(info.GetIsolate()->GetCurrentContext(), v8_str("y"), v8_num(23))
18739 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018740}
18741
18742
Emily Bernierd0a1eb72015-03-24 16:35:39 -040018743void FooGetInterceptor(Local<Name> name,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018744 const v8::PropertyCallbackInfo<v8::Value>& info) {
18745 CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
18746 CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018747 if (!name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
18748 .FromJust()) {
18749 return;
18750 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018751 info.GetReturnValue().Set(v8_num(42));
18752}
18753
18754
Emily Bernierd0a1eb72015-03-24 16:35:39 -040018755void FooSetInterceptor(Local<Name> name, Local<Value> value,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018756 const v8::PropertyCallbackInfo<v8::Value>& info) {
18757 CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
18758 CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018759 if (!name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
18760 .FromJust()) {
18761 return;
18762 }
18763 Local<Object>::Cast(info.This())
18764 ->Set(info.GetIsolate()->GetCurrentContext(), v8_str("y"), v8_num(23))
18765 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018766 info.GetReturnValue().Set(v8_num(23));
Andrei Popescu402d9372010-02-26 13:31:12 +000018767}
18768
18769
Steve Block6ded16b2010-05-10 14:33:55 +010018770TEST(SetterOnConstructorPrototype) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018771 v8::Isolate* isolate = CcTest::isolate();
18772 v8::HandleScope scope(isolate);
18773 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
18774 templ->SetAccessor(v8_str("x"), GetterWhichReturns42,
Andrei Popescu402d9372010-02-26 13:31:12 +000018775 SetterWhichSetsYOnThisTo23);
18776 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018777 CHECK(context->Global()
18778 ->Set(context.local(), v8_str("P"),
18779 templ->NewInstance(context.local()).ToLocalChecked())
18780 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000018781 CompileRun("function C1() {"
18782 " this.x = 23;"
18783 "};"
18784 "C1.prototype = P;"
18785 "function C2() {"
18786 " this.x = 23"
18787 "};"
18788 "C2.prototype = { };"
18789 "C2.prototype.__proto__ = P;");
18790
18791 v8::Local<v8::Script> script;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018792 script = v8_compile("new C1();");
Andrei Popescu402d9372010-02-26 13:31:12 +000018793 for (int i = 0; i < 10; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018794 v8::Local<v8::Object> c1 = v8::Local<v8::Object>::Cast(
18795 script->Run(context.local()).ToLocalChecked());
18796 CHECK_EQ(42, c1->Get(context.local(), v8_str("x"))
18797 .ToLocalChecked()
18798 ->Int32Value(context.local())
18799 .FromJust());
18800 CHECK_EQ(23, c1->Get(context.local(), v8_str("y"))
18801 .ToLocalChecked()
18802 ->Int32Value(context.local())
18803 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000018804 }
18805
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018806 script = v8_compile("new C2();");
Andrei Popescu402d9372010-02-26 13:31:12 +000018807 for (int i = 0; i < 10; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018808 v8::Local<v8::Object> c2 = v8::Local<v8::Object>::Cast(
18809 script->Run(context.local()).ToLocalChecked());
18810 CHECK_EQ(42, c2->Get(context.local(), v8_str("x"))
18811 .ToLocalChecked()
18812 ->Int32Value(context.local())
18813 .FromJust());
18814 CHECK_EQ(23, c2->Get(context.local(), v8_str("y"))
18815 .ToLocalChecked()
18816 ->Int32Value(context.local())
18817 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000018818 }
18819}
18820
18821
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018822static void NamedPropertySetterWhichSetsYOnThisTo23(
Emily Bernierd0a1eb72015-03-24 16:35:39 -040018823 Local<Name> name, Local<Value> value,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018824 const v8::PropertyCallbackInfo<v8::Value>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018825 if (name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("x"))
18826 .FromJust()) {
18827 Local<Object>::Cast(info.This())
18828 ->Set(info.GetIsolate()->GetCurrentContext(), v8_str("y"), v8_num(23))
18829 .FromJust();
Andrei Popescu402d9372010-02-26 13:31:12 +000018830 }
Andrei Popescu402d9372010-02-26 13:31:12 +000018831}
18832
18833
18834THREADED_TEST(InterceptorOnConstructorPrototype) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018835 v8::Isolate* isolate = CcTest::isolate();
18836 v8::HandleScope scope(isolate);
18837 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040018838 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
18839 NamedPropertyGetterWhichReturns42,
18840 NamedPropertySetterWhichSetsYOnThisTo23));
Andrei Popescu402d9372010-02-26 13:31:12 +000018841 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018842 CHECK(context->Global()
18843 ->Set(context.local(), v8_str("P"),
18844 templ->NewInstance(context.local()).ToLocalChecked())
18845 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000018846 CompileRun("function C1() {"
18847 " this.x = 23;"
18848 "};"
18849 "C1.prototype = P;"
18850 "function C2() {"
18851 " this.x = 23"
18852 "};"
18853 "C2.prototype = { };"
18854 "C2.prototype.__proto__ = P;");
18855
18856 v8::Local<v8::Script> script;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018857 script = v8_compile("new C1();");
Andrei Popescu402d9372010-02-26 13:31:12 +000018858 for (int i = 0; i < 10; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018859 v8::Local<v8::Object> c1 = v8::Local<v8::Object>::Cast(
18860 script->Run(context.local()).ToLocalChecked());
18861 CHECK_EQ(23, c1->Get(context.local(), v8_str("x"))
18862 .ToLocalChecked()
18863 ->Int32Value(context.local())
18864 .FromJust());
18865 CHECK_EQ(42, c1->Get(context.local(), v8_str("y"))
18866 .ToLocalChecked()
18867 ->Int32Value(context.local())
18868 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000018869 }
18870
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018871 script = v8_compile("new C2();");
Andrei Popescu402d9372010-02-26 13:31:12 +000018872 for (int i = 0; i < 10; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018873 v8::Local<v8::Object> c2 = v8::Local<v8::Object>::Cast(
18874 script->Run(context.local()).ToLocalChecked());
18875 CHECK_EQ(23, c2->Get(context.local(), v8_str("x"))
18876 .ToLocalChecked()
18877 ->Int32Value(context.local())
18878 .FromJust());
18879 CHECK_EQ(42, c2->Get(context.local(), v8_str("y"))
18880 .ToLocalChecked()
18881 ->Int32Value(context.local())
18882 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000018883 }
18884}
Steve Block6ded16b2010-05-10 14:33:55 +010018885
18886
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018887TEST(Regress618) {
Steve Block6ded16b2010-05-10 14:33:55 +010018888 const char* source = "function C1() {"
18889 " this.x = 23;"
18890 "};"
18891 "C1.prototype = P;";
18892
Steve Block6ded16b2010-05-10 14:33:55 +010018893 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018894 v8::Isolate* isolate = context->GetIsolate();
18895 v8::HandleScope scope(isolate);
Steve Block6ded16b2010-05-10 14:33:55 +010018896 v8::Local<v8::Script> script;
18897
18898 // Use a simple object as prototype.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018899 v8::Local<v8::Object> prototype = v8::Object::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018900 prototype->Set(context.local(), v8_str("y"), v8_num(42)).FromJust();
18901 CHECK(context->Global()
18902 ->Set(context.local(), v8_str("P"), prototype)
18903 .FromJust());
Steve Block6ded16b2010-05-10 14:33:55 +010018904
18905 // This compile will add the code to the compilation cache.
18906 CompileRun(source);
18907
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018908 script = v8_compile("new C1();");
Kristian Monsen0d5e1162010-09-30 15:31:59 +010018909 // Allow enough iterations for the inobject slack tracking logic
18910 // to finalize instance size and install the fast construct stub.
18911 for (int i = 0; i < 256; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018912 v8::Local<v8::Object> c1 = v8::Local<v8::Object>::Cast(
18913 script->Run(context.local()).ToLocalChecked());
18914 CHECK_EQ(23, c1->Get(context.local(), v8_str("x"))
18915 .ToLocalChecked()
18916 ->Int32Value(context.local())
18917 .FromJust());
18918 CHECK_EQ(42, c1->Get(context.local(), v8_str("y"))
18919 .ToLocalChecked()
18920 ->Int32Value(context.local())
18921 .FromJust());
Steve Block6ded16b2010-05-10 14:33:55 +010018922 }
18923
18924 // Use an API object with accessors as prototype.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018925 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
18926 templ->SetAccessor(v8_str("x"), GetterWhichReturns42,
Steve Block6ded16b2010-05-10 14:33:55 +010018927 SetterWhichSetsYOnThisTo23);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018928 CHECK(context->Global()
18929 ->Set(context.local(), v8_str("P"),
18930 templ->NewInstance(context.local()).ToLocalChecked())
18931 .FromJust());
Steve Block6ded16b2010-05-10 14:33:55 +010018932
18933 // This compile will get the code from the compilation cache.
18934 CompileRun(source);
18935
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018936 script = v8_compile("new C1();");
Steve Block6ded16b2010-05-10 14:33:55 +010018937 for (int i = 0; i < 10; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018938 v8::Local<v8::Object> c1 = v8::Local<v8::Object>::Cast(
18939 script->Run(context.local()).ToLocalChecked());
18940 CHECK_EQ(42, c1->Get(context.local(), v8_str("x"))
18941 .ToLocalChecked()
18942 ->Int32Value(context.local())
18943 .FromJust());
18944 CHECK_EQ(23, c1->Get(context.local(), v8_str("y"))
18945 .ToLocalChecked()
18946 ->Int32Value(context.local())
18947 .FromJust());
Steve Block6ded16b2010-05-10 14:33:55 +010018948 }
18949}
18950
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018951v8::Isolate* gc_callbacks_isolate = NULL;
Steve Block6ded16b2010-05-10 14:33:55 +010018952int prologue_call_count = 0;
18953int epilogue_call_count = 0;
18954int prologue_call_count_second = 0;
18955int epilogue_call_count_second = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018956int prologue_call_count_alloc = 0;
18957int epilogue_call_count_alloc = 0;
Steve Block6ded16b2010-05-10 14:33:55 +010018958
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018959void PrologueCallback(v8::Isolate* isolate,
18960 v8::GCType,
18961 v8::GCCallbackFlags flags) {
18962 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
18963 CHECK_EQ(gc_callbacks_isolate, isolate);
18964 ++prologue_call_count;
18965}
18966
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018967void EpilogueCallback(v8::Isolate* isolate,
18968 v8::GCType,
18969 v8::GCCallbackFlags flags) {
18970 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
18971 CHECK_EQ(gc_callbacks_isolate, isolate);
18972 ++epilogue_call_count;
18973}
18974
18975
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018976void PrologueCallbackSecond(v8::Isolate* isolate,
18977 v8::GCType,
18978 v8::GCCallbackFlags flags) {
18979 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
18980 CHECK_EQ(gc_callbacks_isolate, isolate);
18981 ++prologue_call_count_second;
18982}
18983
18984
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018985void EpilogueCallbackSecond(v8::Isolate* isolate,
18986 v8::GCType,
18987 v8::GCCallbackFlags flags) {
18988 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
18989 CHECK_EQ(gc_callbacks_isolate, isolate);
18990 ++epilogue_call_count_second;
18991}
18992
18993
18994void PrologueCallbackAlloc(v8::Isolate* isolate,
18995 v8::GCType,
18996 v8::GCCallbackFlags flags) {
18997 v8::HandleScope scope(isolate);
18998
18999 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
19000 CHECK_EQ(gc_callbacks_isolate, isolate);
19001 ++prologue_call_count_alloc;
19002
19003 // Simulate full heap to see if we will reenter this callback
19004 SimulateFullSpace(CcTest::heap()->new_space());
19005
19006 Local<Object> obj = Object::New(isolate);
19007 CHECK(!obj.IsEmpty());
19008
19009 CcTest::heap()->CollectAllGarbage(
19010 i::Heap::kAbortIncrementalMarkingMask);
19011}
19012
19013
19014void EpilogueCallbackAlloc(v8::Isolate* isolate,
19015 v8::GCType,
19016 v8::GCCallbackFlags flags) {
19017 v8::HandleScope scope(isolate);
19018
19019 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
19020 CHECK_EQ(gc_callbacks_isolate, isolate);
19021 ++epilogue_call_count_alloc;
19022
19023 // Simulate full heap to see if we will reenter this callback
19024 SimulateFullSpace(CcTest::heap()->new_space());
19025
19026 Local<Object> obj = Object::New(isolate);
19027 CHECK(!obj.IsEmpty());
19028
19029 CcTest::heap()->CollectAllGarbage(
19030 i::Heap::kAbortIncrementalMarkingMask);
19031}
19032
19033
19034TEST(GCCallbacksOld) {
Steve Block6ded16b2010-05-10 14:33:55 +010019035 LocalContext context;
19036
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019037 gc_callbacks_isolate = context->GetIsolate();
19038
19039 context->GetIsolate()->AddGCPrologueCallback(PrologueCallback);
19040 context->GetIsolate()->AddGCEpilogueCallback(EpilogueCallback);
Steve Block6ded16b2010-05-10 14:33:55 +010019041 CHECK_EQ(0, prologue_call_count);
19042 CHECK_EQ(0, epilogue_call_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019043 CcTest::heap()->CollectAllGarbage();
Steve Block6ded16b2010-05-10 14:33:55 +010019044 CHECK_EQ(1, prologue_call_count);
19045 CHECK_EQ(1, epilogue_call_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019046 context->GetIsolate()->AddGCPrologueCallback(PrologueCallbackSecond);
19047 context->GetIsolate()->AddGCEpilogueCallback(EpilogueCallbackSecond);
19048 CcTest::heap()->CollectAllGarbage();
Steve Block6ded16b2010-05-10 14:33:55 +010019049 CHECK_EQ(2, prologue_call_count);
19050 CHECK_EQ(2, epilogue_call_count);
19051 CHECK_EQ(1, prologue_call_count_second);
19052 CHECK_EQ(1, epilogue_call_count_second);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019053 context->GetIsolate()->RemoveGCPrologueCallback(PrologueCallback);
19054 context->GetIsolate()->RemoveGCEpilogueCallback(EpilogueCallback);
19055 CcTest::heap()->CollectAllGarbage();
Steve Block6ded16b2010-05-10 14:33:55 +010019056 CHECK_EQ(2, prologue_call_count);
19057 CHECK_EQ(2, epilogue_call_count);
19058 CHECK_EQ(2, prologue_call_count_second);
19059 CHECK_EQ(2, epilogue_call_count_second);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019060 context->GetIsolate()->RemoveGCPrologueCallback(PrologueCallbackSecond);
19061 context->GetIsolate()->RemoveGCEpilogueCallback(EpilogueCallbackSecond);
19062 CcTest::heap()->CollectAllGarbage();
Steve Block6ded16b2010-05-10 14:33:55 +010019063 CHECK_EQ(2, prologue_call_count);
19064 CHECK_EQ(2, epilogue_call_count);
19065 CHECK_EQ(2, prologue_call_count_second);
19066 CHECK_EQ(2, epilogue_call_count_second);
19067}
Kristian Monsen25f61362010-05-21 11:50:48 +010019068
19069
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019070TEST(GCCallbacks) {
19071 LocalContext context;
19072 v8::Isolate* isolate = context->GetIsolate();
19073 gc_callbacks_isolate = isolate;
19074 isolate->AddGCPrologueCallback(PrologueCallback);
19075 isolate->AddGCEpilogueCallback(EpilogueCallback);
19076 CHECK_EQ(0, prologue_call_count);
19077 CHECK_EQ(0, epilogue_call_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019078 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019079 CHECK_EQ(1, prologue_call_count);
19080 CHECK_EQ(1, epilogue_call_count);
19081 isolate->AddGCPrologueCallback(PrologueCallbackSecond);
19082 isolate->AddGCEpilogueCallback(EpilogueCallbackSecond);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019083 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019084 CHECK_EQ(2, prologue_call_count);
19085 CHECK_EQ(2, epilogue_call_count);
19086 CHECK_EQ(1, prologue_call_count_second);
19087 CHECK_EQ(1, epilogue_call_count_second);
19088 isolate->RemoveGCPrologueCallback(PrologueCallback);
19089 isolate->RemoveGCEpilogueCallback(EpilogueCallback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019090 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019091 CHECK_EQ(2, prologue_call_count);
19092 CHECK_EQ(2, epilogue_call_count);
19093 CHECK_EQ(2, prologue_call_count_second);
19094 CHECK_EQ(2, epilogue_call_count_second);
19095 isolate->RemoveGCPrologueCallback(PrologueCallbackSecond);
19096 isolate->RemoveGCEpilogueCallback(EpilogueCallbackSecond);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019097 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019098 CHECK_EQ(2, prologue_call_count);
19099 CHECK_EQ(2, epilogue_call_count);
19100 CHECK_EQ(2, prologue_call_count_second);
19101 CHECK_EQ(2, epilogue_call_count_second);
19102
19103 CHECK_EQ(0, prologue_call_count_alloc);
19104 CHECK_EQ(0, epilogue_call_count_alloc);
19105 isolate->AddGCPrologueCallback(PrologueCallbackAlloc);
19106 isolate->AddGCEpilogueCallback(EpilogueCallbackAlloc);
19107 CcTest::heap()->CollectAllGarbage(
19108 i::Heap::kAbortIncrementalMarkingMask);
19109 CHECK_EQ(1, prologue_call_count_alloc);
19110 CHECK_EQ(1, epilogue_call_count_alloc);
19111 isolate->RemoveGCPrologueCallback(PrologueCallbackAlloc);
19112 isolate->RemoveGCEpilogueCallback(EpilogueCallbackAlloc);
19113}
19114
19115
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019116THREADED_TEST(TwoByteStringInOneByteCons) {
Steve Block8defd9f2010-07-08 12:39:36 +010019117 // See Chromium issue 47824.
Steve Block8defd9f2010-07-08 12:39:36 +010019118 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019119 v8::HandleScope scope(context->GetIsolate());
19120
Steve Block8defd9f2010-07-08 12:39:36 +010019121 const char* init_code =
19122 "var str1 = 'abelspendabel';"
19123 "var str2 = str1 + str1 + str1;"
19124 "str2;";
19125 Local<Value> result = CompileRun(init_code);
19126
Ben Murdoch69a99ed2011-11-30 16:03:39 +000019127 Local<Value> indexof = CompileRun("str2.indexOf('els')");
19128 Local<Value> lastindexof = CompileRun("str2.lastIndexOf('dab')");
19129
Steve Block8defd9f2010-07-08 12:39:36 +010019130 CHECK(result->IsString());
19131 i::Handle<i::String> string = v8::Utils::OpenHandle(String::Cast(*result));
19132 int length = string->length();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019133 CHECK(string->IsOneByteRepresentation());
Steve Block8defd9f2010-07-08 12:39:36 +010019134
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019135 i::Handle<i::String> flat_string = i::String::Flatten(string);
Steve Block8defd9f2010-07-08 12:39:36 +010019136
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019137 CHECK(string->IsOneByteRepresentation());
19138 CHECK(flat_string->IsOneByteRepresentation());
Steve Block8defd9f2010-07-08 12:39:36 +010019139
19140 // Create external resource.
19141 uint16_t* uc16_buffer = new uint16_t[length + 1];
19142
19143 i::String::WriteToFlat(*flat_string, uc16_buffer, 0, length);
19144 uc16_buffer[length] = 0;
19145
19146 TestResource resource(uc16_buffer);
19147
19148 flat_string->MakeExternal(&resource);
19149
19150 CHECK(flat_string->IsTwoByteRepresentation());
19151
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019152 // If the cons string has been short-circuited, skip the following checks.
19153 if (!string.is_identical_to(flat_string)) {
19154 // At this point, we should have a Cons string which is flat and one-byte,
19155 // with a first half that is a two-byte string (although it only contains
19156 // one-byte characters). This is a valid sequence of steps, and it can
19157 // happen in real pages.
19158 CHECK(string->IsOneByteRepresentation());
19159 i::ConsString* cons = i::ConsString::cast(*string);
19160 CHECK_EQ(0, cons->second()->length());
19161 CHECK(cons->first()->IsTwoByteRepresentation());
19162 }
Steve Block8defd9f2010-07-08 12:39:36 +010019163
19164 // Check that some string operations work.
19165
19166 // Atom RegExp.
19167 Local<Value> reresult = CompileRun("str2.match(/abel/g).length;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019168 CHECK_EQ(6, reresult->Int32Value(context.local()).FromJust());
Steve Block8defd9f2010-07-08 12:39:36 +010019169
19170 // Nonatom RegExp.
19171 reresult = CompileRun("str2.match(/abe./g).length;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019172 CHECK_EQ(6, reresult->Int32Value(context.local()).FromJust());
Steve Block8defd9f2010-07-08 12:39:36 +010019173
19174 reresult = CompileRun("str2.search(/bel/g);");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019175 CHECK_EQ(1, reresult->Int32Value(context.local()).FromJust());
Steve Block8defd9f2010-07-08 12:39:36 +010019176
19177 reresult = CompileRun("str2.search(/be./g);");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019178 CHECK_EQ(1, reresult->Int32Value(context.local()).FromJust());
Steve Block8defd9f2010-07-08 12:39:36 +010019179
19180 ExpectTrue("/bel/g.test(str2);");
19181
19182 ExpectTrue("/be./g.test(str2);");
19183
19184 reresult = CompileRun("/bel/g.exec(str2);");
19185 CHECK(!reresult->IsNull());
19186
19187 reresult = CompileRun("/be./g.exec(str2);");
19188 CHECK(!reresult->IsNull());
19189
19190 ExpectString("str2.substring(2, 10);", "elspenda");
19191
19192 ExpectString("str2.substring(2, 20);", "elspendabelabelspe");
19193
19194 ExpectString("str2.charAt(2);", "e");
19195
Ben Murdoch69a99ed2011-11-30 16:03:39 +000019196 ExpectObject("str2.indexOf('els');", indexof);
19197
19198 ExpectObject("str2.lastIndexOf('dab');", lastindexof);
19199
Steve Block8defd9f2010-07-08 12:39:36 +010019200 reresult = CompileRun("str2.charCodeAt(2);");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019201 CHECK_EQ(static_cast<int32_t>('e'),
19202 reresult->Int32Value(context.local()).FromJust());
Steve Block8defd9f2010-07-08 12:39:36 +010019203}
Iain Merrick75681382010-08-19 15:07:18 +010019204
19205
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019206TEST(ContainsOnlyOneByte) {
19207 v8::V8::Initialize();
19208 v8::Isolate* isolate = CcTest::isolate();
19209 v8::HandleScope scope(isolate);
19210 // Make a buffer long enough that it won't automatically be converted.
19211 const int length = 512;
19212 // Ensure word aligned assignment.
19213 const int aligned_length = length*sizeof(uintptr_t)/sizeof(uint16_t);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019214 v8::base::SmartArrayPointer<uintptr_t> aligned_contents(
19215 new uintptr_t[aligned_length]);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019216 uint16_t* string_contents =
19217 reinterpret_cast<uint16_t*>(aligned_contents.get());
19218 // Set to contain only one byte.
19219 for (int i = 0; i < length-1; i++) {
19220 string_contents[i] = 0x41;
19221 }
19222 string_contents[length-1] = 0;
19223 // Simple case.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019224 Local<String> string =
19225 String::NewExternalTwoByte(isolate,
19226 new TestResource(string_contents, NULL, false))
19227 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019228 CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
19229 // Counter example.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019230 string = String::NewFromTwoByte(isolate, string_contents,
19231 v8::NewStringType::kNormal)
19232 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019233 CHECK(string->IsOneByte() && string->ContainsOnlyOneByte());
19234 // Test left right and balanced cons strings.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019235 Local<String> base = v8_str("a");
19236 Local<String> left = base;
19237 Local<String> right = base;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019238 for (int i = 0; i < 1000; i++) {
19239 left = String::Concat(base, left);
19240 right = String::Concat(right, base);
19241 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019242 Local<String> balanced = String::Concat(left, base);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019243 balanced = String::Concat(balanced, right);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019244 Local<String> cons_strings[] = {left, balanced, right};
19245 Local<String> two_byte =
19246 String::NewExternalTwoByte(isolate,
19247 new TestResource(string_contents, NULL, false))
19248 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019249 USE(two_byte); USE(cons_strings);
19250 for (size_t i = 0; i < arraysize(cons_strings); i++) {
19251 // Base assumptions.
19252 string = cons_strings[i];
19253 CHECK(string->IsOneByte() && string->ContainsOnlyOneByte());
19254 // Test left and right concatentation.
19255 string = String::Concat(two_byte, cons_strings[i]);
19256 CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
19257 string = String::Concat(cons_strings[i], two_byte);
19258 CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
19259 }
19260 // Set bits in different positions
19261 // for strings of different lengths and alignments.
19262 for (int alignment = 0; alignment < 7; alignment++) {
19263 for (int size = 2; alignment + size < length; size *= 2) {
19264 int zero_offset = size + alignment;
19265 string_contents[zero_offset] = 0;
19266 for (int i = 0; i < size; i++) {
19267 int shift = 8 + (i % 7);
19268 string_contents[alignment + i] = 1 << shift;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019269 string = String::NewExternalTwoByte(
19270 isolate,
19271 new TestResource(string_contents + alignment, NULL, false))
19272 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019273 CHECK_EQ(size, string->Length());
19274 CHECK(!string->ContainsOnlyOneByte());
19275 string_contents[alignment + i] = 0x41;
19276 }
19277 string_contents[zero_offset] = 0x41;
19278 }
19279 }
19280}
19281
19282
Iain Merrick75681382010-08-19 15:07:18 +010019283// Failed access check callback that performs a GC on each invocation.
19284void FailedAccessCheckCallbackGC(Local<v8::Object> target,
19285 v8::AccessType type,
19286 Local<v8::Value> data) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019287 CcTest::heap()->CollectAllGarbage();
19288 CcTest::isolate()->ThrowException(
19289 v8::Exception::Error(v8_str("cross context")));
Iain Merrick75681382010-08-19 15:07:18 +010019290}
19291
19292
19293TEST(GCInFailedAccessCheckCallback) {
19294 // Install a failed access check callback that performs a GC on each
19295 // invocation. Then force the callback to be called from va
19296
19297 v8::V8::Initialize();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019298 v8::Isolate* isolate = CcTest::isolate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019299
19300 isolate->SetFailedAccessCheckCallbackFunction(&FailedAccessCheckCallbackGC);
19301
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019302 v8::HandleScope scope(isolate);
Iain Merrick75681382010-08-19 15:07:18 +010019303
19304 // Create an ObjectTemplate for global objects and install access
19305 // check callbacks that will block access.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019306 v8::Local<v8::ObjectTemplate> global_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019307 v8::ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019308 global_template->SetAccessCheckCallback(AccessAlwaysBlocked);
Iain Merrick75681382010-08-19 15:07:18 +010019309
19310 // Create a context and set an x property on it's global object.
19311 LocalContext context0(NULL, global_template);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019312 CHECK(context0->Global()
19313 ->Set(context0.local(), v8_str("x"), v8_num(42))
19314 .FromJust());
19315 v8::Local<v8::Object> global0 = context0->Global();
Iain Merrick75681382010-08-19 15:07:18 +010019316
19317 // Create a context with a different security token so that the
19318 // failed access check callback will be called on each access.
19319 LocalContext context1(NULL, global_template);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019320 CHECK(context1->Global()
19321 ->Set(context1.local(), v8_str("other"), global0)
19322 .FromJust());
19323
19324 v8::TryCatch try_catch(isolate);
Iain Merrick75681382010-08-19 15:07:18 +010019325
19326 // Get property with failed access check.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019327 CHECK(CompileRun("other.x").IsEmpty());
19328 CHECK(try_catch.HasCaught());
19329 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010019330
19331 // Get element with failed access check.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019332 CHECK(CompileRun("other[0]").IsEmpty());
19333 CHECK(try_catch.HasCaught());
19334 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010019335
19336 // Set property with failed access check.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019337 CHECK(CompileRun("other.x = new Object()").IsEmpty());
19338 CHECK(try_catch.HasCaught());
19339 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010019340
19341 // Set element with failed access check.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019342 CHECK(CompileRun("other[0] = new Object()").IsEmpty());
19343 CHECK(try_catch.HasCaught());
19344 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010019345
19346 // Get property attribute with failed access check.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019347 CHECK(CompileRun("\'x\' in other").IsEmpty());
19348 CHECK(try_catch.HasCaught());
19349 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010019350
19351 // Get property attribute for element with failed access check.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019352 CHECK(CompileRun("0 in other").IsEmpty());
19353 CHECK(try_catch.HasCaught());
19354 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010019355
19356 // Delete property.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019357 CHECK(CompileRun("delete other.x").IsEmpty());
19358 CHECK(try_catch.HasCaught());
19359 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010019360
19361 // Delete element.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019362 CHECK(global0->Delete(context1.local(), 0).IsNothing());
19363 CHECK(try_catch.HasCaught());
19364 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010019365
19366 // DefineAccessor.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019367 CHECK(global0->SetAccessor(context1.local(), v8_str("x"), GetXValue, NULL,
19368 v8_str("x"))
19369 .IsNothing());
19370 CHECK(try_catch.HasCaught());
19371 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010019372
19373 // Define JavaScript accessor.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019374 CHECK(CompileRun(
19375 "Object.prototype.__defineGetter__.call("
19376 " other, \'x\', function() { return 42; })").IsEmpty());
19377 CHECK(try_catch.HasCaught());
19378 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010019379
19380 // LookupAccessor.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019381 CHECK(CompileRun(
19382 "Object.prototype.__lookupGetter__.call("
19383 " other, \'x\')").IsEmpty());
19384 CHECK(try_catch.HasCaught());
19385 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010019386
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019387 // HasOwnElement.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019388 CHECK(CompileRun(
19389 "Object.prototype.hasOwnProperty.call("
19390 "other, \'0\')").IsEmpty());
19391 CHECK(try_catch.HasCaught());
19392 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010019393
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019394 CHECK(global0->HasRealIndexedProperty(context1.local(), 0).IsNothing());
19395 CHECK(try_catch.HasCaught());
19396 try_catch.Reset();
19397
19398 CHECK(
19399 global0->HasRealNamedProperty(context1.local(), v8_str("x")).IsNothing());
19400 CHECK(try_catch.HasCaught());
19401 try_catch.Reset();
19402
19403 CHECK(global0->HasRealNamedCallbackProperty(context1.local(), v8_str("x"))
19404 .IsNothing());
19405 CHECK(try_catch.HasCaught());
19406 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010019407
19408 // Reset the failed access check callback so it does not influence
19409 // the other tests.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019410 isolate->SetFailedAccessCheckCallbackFunction(NULL);
Iain Merrick75681382010-08-19 15:07:18 +010019411}
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019412
Steve Block44f0eee2011-05-26 01:26:41 +010019413
19414TEST(IsolateNewDispose) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019415 v8::Isolate* current_isolate = CcTest::isolate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019416 v8::Isolate::CreateParams create_params;
19417 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
19418 v8::Isolate* isolate = v8::Isolate::New(create_params);
Steve Block44f0eee2011-05-26 01:26:41 +010019419 CHECK(isolate != NULL);
Steve Block44f0eee2011-05-26 01:26:41 +010019420 CHECK(current_isolate != isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019421 CHECK(current_isolate == CcTest::isolate());
Steve Block44f0eee2011-05-26 01:26:41 +010019422
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019423 isolate->SetFatalErrorHandler(StoringErrorCallback);
Steve Block44f0eee2011-05-26 01:26:41 +010019424 last_location = last_message = NULL;
19425 isolate->Dispose();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019426 CHECK(!last_location);
19427 CHECK(!last_message);
Steve Block44f0eee2011-05-26 01:26:41 +010019428}
19429
Steve Block44f0eee2011-05-26 01:26:41 +010019430
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019431UNINITIALIZED_TEST(DisposeIsolateWhenInUse) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019432 v8::Isolate::CreateParams create_params;
19433 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
19434 v8::Isolate* isolate = v8::Isolate::New(create_params);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019435 {
19436 v8::Isolate::Scope i_scope(isolate);
19437 v8::HandleScope scope(isolate);
19438 LocalContext context(isolate);
19439 // Run something in this isolate.
19440 ExpectTrue("true");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019441 isolate->SetFatalErrorHandler(StoringErrorCallback);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019442 last_location = last_message = NULL;
19443 // Still entered, should fail.
19444 isolate->Dispose();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019445 CHECK(last_location);
19446 CHECK(last_message);
Steve Block44f0eee2011-05-26 01:26:41 +010019447 }
Steve Block44f0eee2011-05-26 01:26:41 +010019448 isolate->Dispose();
Steve Block44f0eee2011-05-26 01:26:41 +010019449}
19450
Steve Block44f0eee2011-05-26 01:26:41 +010019451
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019452static void BreakArrayGuarantees(const char* script) {
19453 v8::Isolate::CreateParams create_params;
19454 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
19455 v8::Isolate* isolate1 = v8::Isolate::New(create_params);
19456 isolate1->Enter();
19457 v8::Persistent<v8::Context> context1;
19458 {
19459 v8::HandleScope scope(isolate1);
19460 context1.Reset(isolate1, Context::New(isolate1));
19461 }
19462
19463 {
19464 v8::HandleScope scope(isolate1);
19465 v8::Local<v8::Context> context =
19466 v8::Local<v8::Context>::New(isolate1, context1);
19467 v8::Context::Scope context_scope(context);
19468 v8::internal::Isolate* i_isolate =
19469 reinterpret_cast<v8::internal::Isolate*>(isolate1);
19470 CHECK_EQ(true, i_isolate->IsFastArrayConstructorPrototypeChainIntact());
19471 // Run something in new isolate.
19472 CompileRun(script);
19473 CHECK_EQ(false, i_isolate->IsFastArrayConstructorPrototypeChainIntact());
19474 }
19475 isolate1->Exit();
19476 isolate1->Dispose();
19477}
19478
19479
19480TEST(VerifyArrayPrototypeGuarantees) {
19481 // Break fast array hole handling by element changes.
19482 BreakArrayGuarantees("[].__proto__[1] = 3;");
19483 BreakArrayGuarantees("Object.prototype[3] = 'three';");
19484 BreakArrayGuarantees("Array.prototype.push(1);");
19485 BreakArrayGuarantees("Array.prototype.unshift(1);");
19486 // Break fast array hole handling by changing length.
19487 BreakArrayGuarantees("Array.prototype.length = 30;");
19488 // Break fast array hole handling by prototype structure changes.
19489 BreakArrayGuarantees("[].__proto__.__proto__ = { funny: true };");
19490 // By sending elements to dictionary mode.
19491 BreakArrayGuarantees(
19492 "Object.defineProperty(Array.prototype, 0, {"
19493 " get: function() { return 3; }});");
19494 BreakArrayGuarantees(
19495 "Object.defineProperty(Object.prototype, 0, {"
19496 " get: function() { return 3; }});");
19497}
19498
19499
Steve Block44f0eee2011-05-26 01:26:41 +010019500TEST(RunTwoIsolatesOnSingleThread) {
19501 // Run isolate 1.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019502 v8::Isolate::CreateParams create_params;
19503 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
19504 v8::Isolate* isolate1 = v8::Isolate::New(create_params);
Steve Block44f0eee2011-05-26 01:26:41 +010019505 isolate1->Enter();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019506 v8::Persistent<v8::Context> context1;
19507 {
19508 v8::HandleScope scope(isolate1);
19509 context1.Reset(isolate1, Context::New(isolate1));
19510 }
Steve Block44f0eee2011-05-26 01:26:41 +010019511
19512 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019513 v8::HandleScope scope(isolate1);
19514 v8::Local<v8::Context> context =
19515 v8::Local<v8::Context>::New(isolate1, context1);
19516 v8::Context::Scope context_scope(context);
Steve Block44f0eee2011-05-26 01:26:41 +010019517 // Run something in new isolate.
19518 CompileRun("var foo = 'isolate 1';");
19519 ExpectString("function f() { return foo; }; f()", "isolate 1");
19520 }
19521
19522 // Run isolate 2.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019523 v8::Isolate* isolate2 = v8::Isolate::New(create_params);
Steve Block44f0eee2011-05-26 01:26:41 +010019524 v8::Persistent<v8::Context> context2;
19525
19526 {
19527 v8::Isolate::Scope iscope(isolate2);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019528 v8::HandleScope scope(isolate2);
19529 context2.Reset(isolate2, Context::New(isolate2));
19530 v8::Local<v8::Context> context =
19531 v8::Local<v8::Context>::New(isolate2, context2);
19532 v8::Context::Scope context_scope(context);
Steve Block44f0eee2011-05-26 01:26:41 +010019533
19534 // Run something in new isolate.
19535 CompileRun("var foo = 'isolate 2';");
19536 ExpectString("function f() { return foo; }; f()", "isolate 2");
19537 }
19538
19539 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019540 v8::HandleScope scope(isolate1);
19541 v8::Local<v8::Context> context =
19542 v8::Local<v8::Context>::New(isolate1, context1);
19543 v8::Context::Scope context_scope(context);
Steve Block44f0eee2011-05-26 01:26:41 +010019544 // Now again in isolate 1
19545 ExpectString("function f() { return foo; }; f()", "isolate 1");
19546 }
19547
19548 isolate1->Exit();
19549
19550 // Run some stuff in default isolate.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019551 v8::Persistent<v8::Context> context_default;
19552 {
19553 v8::Isolate* isolate = CcTest::isolate();
19554 v8::Isolate::Scope iscope(isolate);
19555 v8::HandleScope scope(isolate);
19556 context_default.Reset(isolate, Context::New(isolate));
19557 }
Steve Block44f0eee2011-05-26 01:26:41 +010019558
19559 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019560 v8::HandleScope scope(CcTest::isolate());
19561 v8::Local<v8::Context> context =
19562 v8::Local<v8::Context>::New(CcTest::isolate(), context_default);
19563 v8::Context::Scope context_scope(context);
Steve Block44f0eee2011-05-26 01:26:41 +010019564 // Variables in other isolates should be not available, verify there
19565 // is an exception.
19566 ExpectTrue("function f() {"
19567 " try {"
19568 " foo;"
19569 " return false;"
19570 " } catch(e) {"
19571 " return true;"
19572 " }"
19573 "};"
19574 "var isDefaultIsolate = true;"
19575 "f()");
19576 }
19577
19578 isolate1->Enter();
19579
19580 {
19581 v8::Isolate::Scope iscope(isolate2);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019582 v8::HandleScope scope(isolate2);
19583 v8::Local<v8::Context> context =
19584 v8::Local<v8::Context>::New(isolate2, context2);
19585 v8::Context::Scope context_scope(context);
Steve Block44f0eee2011-05-26 01:26:41 +010019586 ExpectString("function f() { return foo; }; f()", "isolate 2");
19587 }
19588
19589 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019590 v8::HandleScope scope(v8::Isolate::GetCurrent());
19591 v8::Local<v8::Context> context =
19592 v8::Local<v8::Context>::New(v8::Isolate::GetCurrent(), context1);
19593 v8::Context::Scope context_scope(context);
Steve Block44f0eee2011-05-26 01:26:41 +010019594 ExpectString("function f() { return foo; }; f()", "isolate 1");
19595 }
19596
19597 {
19598 v8::Isolate::Scope iscope(isolate2);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019599 context2.Reset();
Steve Block44f0eee2011-05-26 01:26:41 +010019600 }
19601
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019602 context1.Reset();
Steve Block44f0eee2011-05-26 01:26:41 +010019603 isolate1->Exit();
19604
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019605 isolate2->SetFatalErrorHandler(StoringErrorCallback);
Steve Block44f0eee2011-05-26 01:26:41 +010019606 last_location = last_message = NULL;
19607
19608 isolate1->Dispose();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019609 CHECK(!last_location);
19610 CHECK(!last_message);
Steve Block44f0eee2011-05-26 01:26:41 +010019611
19612 isolate2->Dispose();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019613 CHECK(!last_location);
19614 CHECK(!last_message);
Steve Block44f0eee2011-05-26 01:26:41 +010019615
19616 // Check that default isolate still runs.
19617 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019618 v8::HandleScope scope(CcTest::isolate());
19619 v8::Local<v8::Context> context =
19620 v8::Local<v8::Context>::New(CcTest::isolate(), context_default);
19621 v8::Context::Scope context_scope(context);
Steve Block44f0eee2011-05-26 01:26:41 +010019622 ExpectTrue("function f() { return isDefaultIsolate; }; f()");
19623 }
19624}
19625
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019626
Steve Block44f0eee2011-05-26 01:26:41 +010019627static int CalcFibonacci(v8::Isolate* isolate, int limit) {
19628 v8::Isolate::Scope isolate_scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019629 v8::HandleScope scope(isolate);
19630 LocalContext context(isolate);
Steve Block44f0eee2011-05-26 01:26:41 +010019631 i::ScopedVector<char> code(1024);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019632 i::SNPrintF(code, "function fib(n) {"
19633 " if (n <= 2) return 1;"
19634 " return fib(n-1) + fib(n-2);"
19635 "}"
19636 "fib(%d)", limit);
Steve Block44f0eee2011-05-26 01:26:41 +010019637 Local<Value> value = CompileRun(code.start());
19638 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019639 return static_cast<int>(value->NumberValue(context.local()).FromJust());
Steve Block44f0eee2011-05-26 01:26:41 +010019640}
19641
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019642class IsolateThread : public v8::base::Thread {
Steve Block44f0eee2011-05-26 01:26:41 +010019643 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019644 explicit IsolateThread(int fib_limit)
19645 : Thread(Options("IsolateThread")), fib_limit_(fib_limit), result_(0) {}
Steve Block44f0eee2011-05-26 01:26:41 +010019646
19647 void Run() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019648 v8::Isolate::CreateParams create_params;
19649 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
19650 v8::Isolate* isolate = v8::Isolate::New(create_params);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019651 result_ = CalcFibonacci(isolate, fib_limit_);
19652 isolate->Dispose();
Steve Block44f0eee2011-05-26 01:26:41 +010019653 }
19654
19655 int result() { return result_; }
19656
19657 private:
Steve Block44f0eee2011-05-26 01:26:41 +010019658 int fib_limit_;
19659 int result_;
19660};
19661
Steve Block44f0eee2011-05-26 01:26:41 +010019662
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019663TEST(MultipleIsolatesOnIndividualThreads) {
19664 IsolateThread thread1(21);
19665 IsolateThread thread2(12);
Steve Block44f0eee2011-05-26 01:26:41 +010019666
19667 // Compute some fibonacci numbers on 3 threads in 3 isolates.
19668 thread1.Start();
19669 thread2.Start();
19670
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019671 int result1 = CalcFibonacci(CcTest::isolate(), 21);
19672 int result2 = CalcFibonacci(CcTest::isolate(), 12);
Steve Block44f0eee2011-05-26 01:26:41 +010019673
19674 thread1.Join();
19675 thread2.Join();
19676
19677 // Compare results. The actual fibonacci numbers for 12 and 21 are taken
19678 // (I'm lazy!) from http://en.wikipedia.org/wiki/Fibonacci_number
19679 CHECK_EQ(result1, 10946);
19680 CHECK_EQ(result2, 144);
19681 CHECK_EQ(result1, thread1.result());
19682 CHECK_EQ(result2, thread2.result());
Steve Block44f0eee2011-05-26 01:26:41 +010019683}
19684
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019685
Ben Murdoch257744e2011-11-30 15:57:28 +000019686TEST(IsolateDifferentContexts) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019687 v8::Isolate::CreateParams create_params;
19688 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
19689 v8::Isolate* isolate = v8::Isolate::New(create_params);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019690 Local<v8::Context> context;
Ben Murdoch257744e2011-11-30 15:57:28 +000019691 {
19692 v8::Isolate::Scope isolate_scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019693 v8::HandleScope handle_scope(isolate);
19694 context = v8::Context::New(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000019695 v8::Context::Scope context_scope(context);
19696 Local<Value> v = CompileRun("2");
19697 CHECK(v->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019698 CHECK_EQ(2, static_cast<int>(v->NumberValue(context).FromJust()));
Ben Murdoch257744e2011-11-30 15:57:28 +000019699 }
19700 {
19701 v8::Isolate::Scope isolate_scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019702 v8::HandleScope handle_scope(isolate);
19703 context = v8::Context::New(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000019704 v8::Context::Scope context_scope(context);
19705 Local<Value> v = CompileRun("22");
19706 CHECK(v->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019707 CHECK_EQ(22, static_cast<int>(v->NumberValue(context).FromJust()));
Ben Murdoch257744e2011-11-30 15:57:28 +000019708 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019709 isolate->Dispose();
Ben Murdoch257744e2011-11-30 15:57:28 +000019710}
Steve Block44f0eee2011-05-26 01:26:41 +010019711
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019712class InitDefaultIsolateThread : public v8::base::Thread {
Steve Block44f0eee2011-05-26 01:26:41 +010019713 public:
19714 enum TestCase {
Steve Block44f0eee2011-05-26 01:26:41 +010019715 SetResourceConstraints,
19716 SetFatalHandler,
19717 SetCounterFunction,
19718 SetCreateHistogramFunction,
19719 SetAddHistogramSampleFunction
19720 };
19721
19722 explicit InitDefaultIsolateThread(TestCase testCase)
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019723 : Thread(Options("InitDefaultIsolateThread")),
Steve Block44f0eee2011-05-26 01:26:41 +010019724 testCase_(testCase),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019725 result_(false) {}
Steve Block44f0eee2011-05-26 01:26:41 +010019726
19727 void Run() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019728 v8::Isolate::CreateParams create_params;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019729 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
19730 const intptr_t pageSizeMult =
19731 v8::internal::Page::kPageSize / v8::internal::MB;
Steve Block44f0eee2011-05-26 01:26:41 +010019732 switch (testCase_) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019733 case SetResourceConstraints: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019734 create_params.constraints.set_max_semi_space_size(1 * pageSizeMult);
19735 create_params.constraints.set_max_old_space_size(4 * pageSizeMult);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019736 break;
19737 }
19738 default:
19739 break;
Steve Block44f0eee2011-05-26 01:26:41 +010019740 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019741 v8::Isolate* isolate = v8::Isolate::New(create_params);
19742 isolate->Enter();
19743 switch (testCase_) {
19744 case SetResourceConstraints:
19745 // Already handled in pre-Isolate-creation block.
19746 break;
Steve Block44f0eee2011-05-26 01:26:41 +010019747
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019748 case SetFatalHandler:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019749 isolate->SetFatalErrorHandler(NULL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019750 break;
Steve Block44f0eee2011-05-26 01:26:41 +010019751
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019752 case SetCounterFunction:
19753 CcTest::isolate()->SetCounterFunction(NULL);
19754 break;
Steve Block44f0eee2011-05-26 01:26:41 +010019755
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019756 case SetCreateHistogramFunction:
19757 CcTest::isolate()->SetCreateHistogramFunction(NULL);
19758 break;
Steve Block44f0eee2011-05-26 01:26:41 +010019759
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019760 case SetAddHistogramSampleFunction:
19761 CcTest::isolate()->SetAddHistogramSampleFunction(NULL);
19762 break;
Steve Block44f0eee2011-05-26 01:26:41 +010019763 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019764 isolate->Exit();
19765 isolate->Dispose();
Steve Block44f0eee2011-05-26 01:26:41 +010019766 result_ = true;
19767 }
19768
19769 bool result() { return result_; }
19770
19771 private:
19772 TestCase testCase_;
19773 bool result_;
19774};
19775
19776
19777static void InitializeTestHelper(InitDefaultIsolateThread::TestCase testCase) {
19778 InitDefaultIsolateThread thread(testCase);
19779 thread.Start();
19780 thread.Join();
19781 CHECK_EQ(thread.result(), true);
19782}
19783
Steve Block44f0eee2011-05-26 01:26:41 +010019784
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019785TEST(InitializeDefaultIsolateOnSecondaryThread1) {
Steve Block44f0eee2011-05-26 01:26:41 +010019786 InitializeTestHelper(InitDefaultIsolateThread::SetResourceConstraints);
19787}
19788
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019789
19790TEST(InitializeDefaultIsolateOnSecondaryThread2) {
Steve Block44f0eee2011-05-26 01:26:41 +010019791 InitializeTestHelper(InitDefaultIsolateThread::SetFatalHandler);
19792}
19793
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019794
19795TEST(InitializeDefaultIsolateOnSecondaryThread3) {
Steve Block44f0eee2011-05-26 01:26:41 +010019796 InitializeTestHelper(InitDefaultIsolateThread::SetCounterFunction);
19797}
19798
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019799
19800TEST(InitializeDefaultIsolateOnSecondaryThread4) {
Steve Block44f0eee2011-05-26 01:26:41 +010019801 InitializeTestHelper(InitDefaultIsolateThread::SetCreateHistogramFunction);
19802}
19803
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019804
19805TEST(InitializeDefaultIsolateOnSecondaryThread5) {
Steve Block44f0eee2011-05-26 01:26:41 +010019806 InitializeTestHelper(InitDefaultIsolateThread::SetAddHistogramSampleFunction);
19807}
19808
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019809
19810TEST(StringCheckMultipleContexts) {
19811 const char* code =
19812 "(function() { return \"a\".charAt(0); })()";
19813
19814 {
19815 // Run the code twice in the first context to initialize the call IC.
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019816 LocalContext context1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019817 v8::HandleScope scope(context1->GetIsolate());
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019818 ExpectString(code, "a");
19819 ExpectString(code, "a");
19820 }
19821
19822 {
19823 // Change the String.prototype in the second context and check
19824 // that the right function gets called.
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019825 LocalContext context2;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019826 v8::HandleScope scope(context2->GetIsolate());
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019827 CompileRun("String.prototype.charAt = function() { return \"not a\"; }");
19828 ExpectString(code, "not a");
19829 }
19830}
19831
19832
19833TEST(NumberCheckMultipleContexts) {
19834 const char* code =
19835 "(function() { return (42).toString(); })()";
19836
19837 {
19838 // Run the code twice in the first context to initialize the call IC.
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019839 LocalContext context1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019840 v8::HandleScope scope(context1->GetIsolate());
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019841 ExpectString(code, "42");
19842 ExpectString(code, "42");
19843 }
19844
19845 {
19846 // Change the Number.prototype in the second context and check
19847 // that the right function gets called.
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019848 LocalContext context2;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019849 v8::HandleScope scope(context2->GetIsolate());
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019850 CompileRun("Number.prototype.toString = function() { return \"not 42\"; }");
19851 ExpectString(code, "not 42");
19852 }
19853}
19854
19855
19856TEST(BooleanCheckMultipleContexts) {
19857 const char* code =
19858 "(function() { return true.toString(); })()";
19859
19860 {
19861 // Run the code twice in the first context to initialize the call IC.
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019862 LocalContext context1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019863 v8::HandleScope scope(context1->GetIsolate());
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019864 ExpectString(code, "true");
19865 ExpectString(code, "true");
19866 }
19867
19868 {
19869 // Change the Boolean.prototype in the second context and check
19870 // that the right function gets called.
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019871 LocalContext context2;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019872 v8::HandleScope scope(context2->GetIsolate());
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019873 CompileRun("Boolean.prototype.toString = function() { return \"\"; }");
19874 ExpectString(code, "");
19875 }
19876}
Ben Murdochf87a2032010-10-22 12:50:53 +010019877
19878
19879TEST(DontDeleteCellLoadIC) {
19880 const char* function_code =
19881 "function readCell() { while (true) { return cell; } }";
19882
19883 {
19884 // Run the code twice in the first context to initialize the load
19885 // IC for a don't delete cell.
Ben Murdochf87a2032010-10-22 12:50:53 +010019886 LocalContext context1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019887 v8::HandleScope scope(context1->GetIsolate());
Ben Murdochf87a2032010-10-22 12:50:53 +010019888 CompileRun("var cell = \"first\";");
19889 ExpectBoolean("delete cell", false);
19890 CompileRun(function_code);
19891 ExpectString("readCell()", "first");
19892 ExpectString("readCell()", "first");
19893 }
19894
19895 {
19896 // Use a deletable cell in the second context.
Ben Murdochf87a2032010-10-22 12:50:53 +010019897 LocalContext context2;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019898 v8::HandleScope scope(context2->GetIsolate());
Ben Murdochf87a2032010-10-22 12:50:53 +010019899 CompileRun("cell = \"second\";");
19900 CompileRun(function_code);
19901 ExpectString("readCell()", "second");
19902 ExpectBoolean("delete cell", true);
19903 ExpectString("(function() {"
19904 " try {"
19905 " return readCell();"
19906 " } catch(e) {"
19907 " return e.toString();"
19908 " }"
19909 "})()",
19910 "ReferenceError: cell is not defined");
19911 CompileRun("cell = \"new_second\";");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019912 CcTest::heap()->CollectAllGarbage();
Ben Murdochf87a2032010-10-22 12:50:53 +010019913 ExpectString("readCell()", "new_second");
19914 ExpectString("readCell()", "new_second");
19915 }
19916}
19917
19918
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019919class Visitor42 : public v8::PersistentHandleVisitor {
19920 public:
19921 explicit Visitor42(v8::Persistent<v8::Object>* object)
19922 : counter_(0), object_(object) { }
19923
19924 virtual void VisitPersistentHandle(Persistent<Value>* value,
19925 uint16_t class_id) {
19926 if (class_id != 42) return;
19927 CHECK_EQ(42, value->WrapperClassId());
19928 v8::Isolate* isolate = CcTest::isolate();
19929 v8::HandleScope handle_scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019930 v8::Local<v8::Value> handle = v8::Local<v8::Value>::New(isolate, *value);
19931 v8::Local<v8::Value> object = v8::Local<v8::Object>::New(isolate, *object_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019932 CHECK(handle->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019933 CHECK(Local<Object>::Cast(handle)
19934 ->Equals(isolate->GetCurrentContext(), object)
19935 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019936 ++counter_;
19937 }
19938
19939 int counter_;
19940 v8::Persistent<v8::Object>* object_;
19941};
19942
19943
19944TEST(PersistentHandleVisitor) {
Ben Murdochf87a2032010-10-22 12:50:53 +010019945 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019946 v8::Isolate* isolate = context->GetIsolate();
19947 v8::HandleScope scope(isolate);
19948 v8::Persistent<v8::Object> object(isolate, v8::Object::New(isolate));
19949 CHECK_EQ(0, object.WrapperClassId());
19950 object.SetWrapperClassId(42);
19951 CHECK_EQ(42, object.WrapperClassId());
19952
19953 Visitor42 visitor(&object);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019954 isolate->VisitHandlesWithClassIds(&visitor);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019955 CHECK_EQ(1, visitor.counter_);
19956
19957 object.Reset();
19958}
19959
19960
19961TEST(WrapperClassId) {
19962 LocalContext context;
19963 v8::Isolate* isolate = context->GetIsolate();
19964 v8::HandleScope scope(isolate);
19965 v8::Persistent<v8::Object> object(isolate, v8::Object::New(isolate));
19966 CHECK_EQ(0, object.WrapperClassId());
19967 object.SetWrapperClassId(65535);
19968 CHECK_EQ(65535, object.WrapperClassId());
19969 object.Reset();
19970}
19971
19972
19973TEST(PersistentHandleInNewSpaceVisitor) {
19974 LocalContext context;
19975 v8::Isolate* isolate = context->GetIsolate();
19976 v8::HandleScope scope(isolate);
19977 v8::Persistent<v8::Object> object1(isolate, v8::Object::New(isolate));
19978 CHECK_EQ(0, object1.WrapperClassId());
19979 object1.SetWrapperClassId(42);
19980 CHECK_EQ(42, object1.WrapperClassId());
19981
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019982 CcTest::heap()->CollectAllGarbage();
19983 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019984
19985 v8::Persistent<v8::Object> object2(isolate, v8::Object::New(isolate));
19986 CHECK_EQ(0, object2.WrapperClassId());
19987 object2.SetWrapperClassId(42);
19988 CHECK_EQ(42, object2.WrapperClassId());
19989
19990 Visitor42 visitor(&object2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019991 isolate->VisitHandlesForPartialDependence(&visitor);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019992 CHECK_EQ(1, visitor.counter_);
19993
19994 object1.Reset();
19995 object2.Reset();
19996}
19997
19998
19999TEST(RegExp) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020000 i::FLAG_harmony_unicode_regexps = true;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020001 LocalContext context;
20002 v8::HandleScope scope(context->GetIsolate());
Ben Murdochf87a2032010-10-22 12:50:53 +010020003
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020004 v8::Local<v8::RegExp> re =
20005 v8::RegExp::New(context.local(), v8_str("foo"), v8::RegExp::kNone)
20006 .ToLocalChecked();
Ben Murdochf87a2032010-10-22 12:50:53 +010020007 CHECK(re->IsRegExp());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020008 CHECK(re->GetSource()->Equals(context.local(), v8_str("foo")).FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020009 CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
Ben Murdochf87a2032010-10-22 12:50:53 +010020010
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020011 re = v8::RegExp::New(context.local(), v8_str("bar"),
Ben Murdochf87a2032010-10-22 12:50:53 +010020012 static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020013 v8::RegExp::kGlobal))
20014 .ToLocalChecked();
Ben Murdochf87a2032010-10-22 12:50:53 +010020015 CHECK(re->IsRegExp());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020016 CHECK(re->GetSource()->Equals(context.local(), v8_str("bar")).FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020017 CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kGlobal,
20018 static_cast<int>(re->GetFlags()));
Ben Murdochf87a2032010-10-22 12:50:53 +010020019
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020020 re = v8::RegExp::New(context.local(), v8_str("baz"),
Ben Murdochf87a2032010-10-22 12:50:53 +010020021 static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020022 v8::RegExp::kMultiline))
20023 .ToLocalChecked();
Ben Murdochf87a2032010-10-22 12:50:53 +010020024 CHECK(re->IsRegExp());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020025 CHECK(re->GetSource()->Equals(context.local(), v8_str("baz")).FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020026 CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
20027 static_cast<int>(re->GetFlags()));
Ben Murdochf87a2032010-10-22 12:50:53 +010020028
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020029 re = v8::RegExp::New(context.local(), v8_str("baz"),
20030 static_cast<v8::RegExp::Flags>(v8::RegExp::kUnicode |
20031 v8::RegExp::kSticky))
20032 .ToLocalChecked();
20033 CHECK(re->IsRegExp());
20034 CHECK(re->GetSource()->Equals(context.local(), v8_str("baz")).FromJust());
20035 CHECK_EQ(v8::RegExp::kUnicode | v8::RegExp::kSticky,
20036 static_cast<int>(re->GetFlags()));
20037
Ben Murdochf87a2032010-10-22 12:50:53 +010020038 re = CompileRun("/quux/").As<v8::RegExp>();
20039 CHECK(re->IsRegExp());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020040 CHECK(re->GetSource()->Equals(context.local(), v8_str("quux")).FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020041 CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
Ben Murdochf87a2032010-10-22 12:50:53 +010020042
20043 re = CompileRun("/quux/gm").As<v8::RegExp>();
20044 CHECK(re->IsRegExp());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020045 CHECK(re->GetSource()->Equals(context.local(), v8_str("quux")).FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020046 CHECK_EQ(v8::RegExp::kGlobal | v8::RegExp::kMultiline,
20047 static_cast<int>(re->GetFlags()));
Ben Murdochf87a2032010-10-22 12:50:53 +010020048
20049 // Override the RegExp constructor and check the API constructor
20050 // still works.
20051 CompileRun("RegExp = function() {}");
20052
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020053 re = v8::RegExp::New(context.local(), v8_str("foobar"), v8::RegExp::kNone)
20054 .ToLocalChecked();
Ben Murdochf87a2032010-10-22 12:50:53 +010020055 CHECK(re->IsRegExp());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020056 CHECK(re->GetSource()->Equals(context.local(), v8_str("foobar")).FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020057 CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
Ben Murdochf87a2032010-10-22 12:50:53 +010020058
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020059 re = v8::RegExp::New(context.local(), v8_str("foobarbaz"),
Ben Murdochf87a2032010-10-22 12:50:53 +010020060 static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020061 v8::RegExp::kMultiline))
20062 .ToLocalChecked();
Ben Murdochf87a2032010-10-22 12:50:53 +010020063 CHECK(re->IsRegExp());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020064 CHECK(
20065 re->GetSource()->Equals(context.local(), v8_str("foobarbaz")).FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020066 CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
20067 static_cast<int>(re->GetFlags()));
Ben Murdochf87a2032010-10-22 12:50:53 +010020068
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020069 CHECK(context->Global()->Set(context.local(), v8_str("re"), re).FromJust());
Ben Murdochf87a2032010-10-22 12:50:53 +010020070 ExpectTrue("re.test('FoobarbaZ')");
20071
Ben Murdoch257744e2011-11-30 15:57:28 +000020072 // RegExps are objects on which you can set properties.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020073 re->Set(context.local(), v8_str("property"),
20074 v8::Integer::New(context->GetIsolate(), 32))
20075 .FromJust();
20076 v8::Local<v8::Value> value(CompileRun("re.property"));
20077 CHECK_EQ(32, value->Int32Value(context.local()).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000020078
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020079 v8::TryCatch try_catch(context->GetIsolate());
20080 CHECK(v8::RegExp::New(context.local(), v8_str("foo["), v8::RegExp::kNone)
20081 .IsEmpty());
Ben Murdochf87a2032010-10-22 12:50:53 +010020082 CHECK(try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020083 CHECK(context->Global()
20084 ->Set(context.local(), v8_str("ex"), try_catch.Exception())
20085 .FromJust());
Ben Murdochf87a2032010-10-22 12:50:53 +010020086 ExpectTrue("ex instanceof SyntaxError");
20087}
20088
20089
Steve Block1e0659c2011-05-24 12:43:12 +010020090THREADED_TEST(Equals) {
Steve Block1e0659c2011-05-24 12:43:12 +010020091 LocalContext localContext;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020092 v8::HandleScope handleScope(localContext->GetIsolate());
Steve Block1e0659c2011-05-24 12:43:12 +010020093
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020094 v8::Local<v8::Object> globalProxy = localContext->Global();
20095 v8::Local<Value> global = globalProxy->GetPrototype();
Steve Block1e0659c2011-05-24 12:43:12 +010020096
20097 CHECK(global->StrictEquals(global));
20098 CHECK(!global->StrictEquals(globalProxy));
20099 CHECK(!globalProxy->StrictEquals(global));
20100 CHECK(globalProxy->StrictEquals(globalProxy));
20101
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020102 CHECK(global->Equals(localContext.local(), global).FromJust());
20103 CHECK(!global->Equals(localContext.local(), globalProxy).FromJust());
20104 CHECK(!globalProxy->Equals(localContext.local(), global).FromJust());
20105 CHECK(globalProxy->Equals(localContext.local(), globalProxy).FromJust());
Steve Block1e0659c2011-05-24 12:43:12 +010020106}
20107
20108
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020109static void Getter(v8::Local<v8::Name> property,
20110 const v8::PropertyCallbackInfo<v8::Value>& info) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020111 info.GetReturnValue().Set(v8_str("42!"));
Ben Murdochf87a2032010-10-22 12:50:53 +010020112}
20113
20114
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020115static void Enumerator(const v8::PropertyCallbackInfo<v8::Array>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020116 v8::Local<v8::Array> result = v8::Array::New(info.GetIsolate());
20117 result->Set(info.GetIsolate()->GetCurrentContext(), 0,
20118 v8_str("universalAnswer"))
20119 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020120 info.GetReturnValue().Set(result);
Ben Murdochf87a2032010-10-22 12:50:53 +010020121}
20122
20123
20124TEST(NamedEnumeratorAndForIn) {
Ben Murdochf87a2032010-10-22 12:50:53 +010020125 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020126 v8::Isolate* isolate = context->GetIsolate();
20127 v8::HandleScope handle_scope(isolate);
Ben Murdochf87a2032010-10-22 12:50:53 +010020128 v8::Context::Scope context_scope(context.local());
20129
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020130 v8::Local<v8::ObjectTemplate> tmpl = v8::ObjectTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020131 tmpl->SetHandler(v8::NamedPropertyHandlerConfiguration(Getter, NULL, NULL,
20132 NULL, Enumerator));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020133 CHECK(context->Global()
20134 ->Set(context.local(), v8_str("o"),
20135 tmpl->NewInstance(context.local()).ToLocalChecked())
20136 .FromJust());
20137 v8::Local<v8::Array> result = v8::Local<v8::Array>::Cast(
20138 CompileRun("var result = []; for (var k in o) result.push(k); result"));
20139 CHECK_EQ(1u, result->Length());
20140 CHECK(v8_str("universalAnswer")
20141 ->Equals(context.local(),
20142 result->Get(context.local(), 0).ToLocalChecked())
20143 .FromJust());
Ben Murdochf87a2032010-10-22 12:50:53 +010020144}
Steve Block1e0659c2011-05-24 12:43:12 +010020145
20146
20147TEST(DefinePropertyPostDetach) {
Steve Block1e0659c2011-05-24 12:43:12 +010020148 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020149 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020150 v8::Local<v8::Object> proxy = context->Global();
20151 v8::Local<v8::Function> define_property =
20152 CompileRun(
20153 "(function() {"
20154 " Object.defineProperty("
20155 " this,"
20156 " 1,"
20157 " { configurable: true, enumerable: true, value: 3 });"
20158 "})")
20159 .As<Function>();
Steve Block1e0659c2011-05-24 12:43:12 +010020160 context->DetachGlobal();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020161 CHECK(define_property->Call(context.local(), proxy, 0, NULL).IsEmpty());
Steve Block1e0659c2011-05-24 12:43:12 +010020162}
Ben Murdoch8b112d22011-06-08 16:22:53 +010020163
20164
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020165static void InstallContextId(v8::Local<Context> context, int id) {
Ben Murdoch8b112d22011-06-08 16:22:53 +010020166 Context::Scope scope(context);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020167 CHECK(CompileRun("Object.prototype")
20168 .As<Object>()
20169 ->Set(context, v8_str("context_id"),
20170 v8::Integer::New(context->GetIsolate(), id))
20171 .FromJust());
Ben Murdoch8b112d22011-06-08 16:22:53 +010020172}
20173
20174
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020175static void CheckContextId(v8::Local<Object> object, int expected) {
20176 v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
20177 CHECK_EQ(expected, object->Get(context, v8_str("context_id"))
20178 .ToLocalChecked()
20179 ->Int32Value(context)
20180 .FromJust());
Ben Murdoch8b112d22011-06-08 16:22:53 +010020181}
20182
20183
20184THREADED_TEST(CreationContext) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020185 v8::Isolate* isolate = CcTest::isolate();
20186 HandleScope handle_scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020187 Local<Context> context1 = Context::New(isolate);
Ben Murdoch8b112d22011-06-08 16:22:53 +010020188 InstallContextId(context1, 1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020189 Local<Context> context2 = Context::New(isolate);
Ben Murdoch8b112d22011-06-08 16:22:53 +010020190 InstallContextId(context2, 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020191 Local<Context> context3 = Context::New(isolate);
Ben Murdoch8b112d22011-06-08 16:22:53 +010020192 InstallContextId(context3, 3);
20193
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020194 Local<v8::FunctionTemplate> tmpl = v8::FunctionTemplate::New(isolate);
Ben Murdoch8b112d22011-06-08 16:22:53 +010020195
20196 Local<Object> object1;
20197 Local<Function> func1;
20198 {
20199 Context::Scope scope(context1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020200 object1 = Object::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020201 func1 = tmpl->GetFunction(context1).ToLocalChecked();
Ben Murdoch8b112d22011-06-08 16:22:53 +010020202 }
20203
20204 Local<Object> object2;
20205 Local<Function> func2;
20206 {
20207 Context::Scope scope(context2);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020208 object2 = Object::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020209 func2 = tmpl->GetFunction(context2).ToLocalChecked();
Ben Murdoch8b112d22011-06-08 16:22:53 +010020210 }
20211
20212 Local<Object> instance1;
20213 Local<Object> instance2;
20214
20215 {
20216 Context::Scope scope(context3);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020217 instance1 = func1->NewInstance(context3).ToLocalChecked();
20218 instance2 = func2->NewInstance(context3).ToLocalChecked();
Ben Murdoch8b112d22011-06-08 16:22:53 +010020219 }
20220
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020221 {
20222 Local<Context> other_context = Context::New(isolate);
20223 Context::Scope scope(other_context);
20224 CHECK(object1->CreationContext() == context1);
20225 CheckContextId(object1, 1);
20226 CHECK(func1->CreationContext() == context1);
20227 CheckContextId(func1, 1);
20228 CHECK(instance1->CreationContext() == context1);
20229 CheckContextId(instance1, 1);
20230 CHECK(object2->CreationContext() == context2);
20231 CheckContextId(object2, 2);
20232 CHECK(func2->CreationContext() == context2);
20233 CheckContextId(func2, 2);
20234 CHECK(instance2->CreationContext() == context2);
20235 CheckContextId(instance2, 2);
20236 }
Ben Murdoch8b112d22011-06-08 16:22:53 +010020237
20238 {
20239 Context::Scope scope(context1);
20240 CHECK(object1->CreationContext() == context1);
20241 CheckContextId(object1, 1);
20242 CHECK(func1->CreationContext() == context1);
20243 CheckContextId(func1, 1);
20244 CHECK(instance1->CreationContext() == context1);
20245 CheckContextId(instance1, 1);
20246 CHECK(object2->CreationContext() == context2);
20247 CheckContextId(object2, 2);
20248 CHECK(func2->CreationContext() == context2);
20249 CheckContextId(func2, 2);
20250 CHECK(instance2->CreationContext() == context2);
20251 CheckContextId(instance2, 2);
20252 }
20253
20254 {
20255 Context::Scope scope(context2);
20256 CHECK(object1->CreationContext() == context1);
20257 CheckContextId(object1, 1);
20258 CHECK(func1->CreationContext() == context1);
20259 CheckContextId(func1, 1);
20260 CHECK(instance1->CreationContext() == context1);
20261 CheckContextId(instance1, 1);
20262 CHECK(object2->CreationContext() == context2);
20263 CheckContextId(object2, 2);
20264 CHECK(func2->CreationContext() == context2);
20265 CheckContextId(func2, 2);
20266 CHECK(instance2->CreationContext() == context2);
20267 CheckContextId(instance2, 2);
20268 }
Ben Murdoch8b112d22011-06-08 16:22:53 +010020269}
Ben Murdoch257744e2011-11-30 15:57:28 +000020270
20271
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020272THREADED_TEST(CreationContextOfJsFunction) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020273 HandleScope handle_scope(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020274 Local<Context> context = Context::New(CcTest::isolate());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020275 InstallContextId(context, 1);
20276
20277 Local<Object> function;
20278 {
20279 Context::Scope scope(context);
20280 function = CompileRun("function foo() {}; foo").As<Object>();
20281 }
20282
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020283 Local<Context> other_context = Context::New(CcTest::isolate());
20284 Context::Scope scope(other_context);
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020285 CHECK(function->CreationContext() == context);
20286 CheckContextId(function, 1);
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020287}
20288
20289
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020290THREADED_TEST(CreationContextOfJsBoundFunction) {
20291 HandleScope handle_scope(CcTest::isolate());
20292 Local<Context> context1 = Context::New(CcTest::isolate());
20293 InstallContextId(context1, 1);
20294 Local<Context> context2 = Context::New(CcTest::isolate());
20295 InstallContextId(context2, 2);
20296
20297 Local<Function> target_function;
20298 {
20299 Context::Scope scope(context1);
20300 target_function = CompileRun("function foo() {}; foo").As<Function>();
20301 }
20302
20303 Local<Function> bound_function1, bound_function2;
20304 {
20305 Context::Scope scope(context2);
20306 CHECK(context2->Global()
20307 ->Set(context2, v8_str("foo"), target_function)
20308 .FromJust());
20309 bound_function1 = CompileRun("foo.bind(1)").As<Function>();
20310 bound_function2 =
20311 CompileRun("Function.prototype.bind.call(foo, 2)").As<Function>();
20312 }
20313
20314 Local<Context> other_context = Context::New(CcTest::isolate());
20315 Context::Scope scope(other_context);
20316 CHECK(bound_function1->CreationContext() == context1);
20317 CheckContextId(bound_function1, 1);
Ben Murdoch097c5b22016-05-18 11:27:45 +010020318 CHECK(bound_function2->CreationContext() == context1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020319 CheckContextId(bound_function2, 1);
20320}
20321
20322
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020323void HasOwnPropertyIndexedPropertyGetter(
20324 uint32_t index,
20325 const v8::PropertyCallbackInfo<v8::Value>& info) {
20326 if (index == 42) info.GetReturnValue().Set(v8_str("yes"));
Ben Murdoch257744e2011-11-30 15:57:28 +000020327}
20328
20329
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020330void HasOwnPropertyNamedPropertyGetter(
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020331 Local<Name> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020332 if (property->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
20333 .FromJust()) {
20334 info.GetReturnValue().Set(v8_str("yes"));
20335 }
Ben Murdoch257744e2011-11-30 15:57:28 +000020336}
20337
20338
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020339void HasOwnPropertyIndexedPropertyQuery(
20340 uint32_t index, const v8::PropertyCallbackInfo<v8::Integer>& info) {
20341 if (index == 42) info.GetReturnValue().Set(1);
Ben Murdoch257744e2011-11-30 15:57:28 +000020342}
20343
20344
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020345void HasOwnPropertyNamedPropertyQuery(
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020346 Local<Name> property, const v8::PropertyCallbackInfo<v8::Integer>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020347 if (property->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
20348 .FromJust()) {
20349 info.GetReturnValue().Set(1);
20350 }
Ben Murdoch257744e2011-11-30 15:57:28 +000020351}
20352
20353
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020354void HasOwnPropertyNamedPropertyQuery2(
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020355 Local<Name> property, const v8::PropertyCallbackInfo<v8::Integer>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020356 if (property->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("bar"))
20357 .FromJust()) {
20358 info.GetReturnValue().Set(1);
20359 }
Ben Murdoch257744e2011-11-30 15:57:28 +000020360}
20361
20362
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020363void HasOwnPropertyAccessorGetter(
20364 Local<String> property,
20365 const v8::PropertyCallbackInfo<v8::Value>& info) {
20366 info.GetReturnValue().Set(v8_str("yes"));
Ben Murdoch257744e2011-11-30 15:57:28 +000020367}
20368
20369
20370TEST(HasOwnProperty) {
Ben Murdoch257744e2011-11-30 15:57:28 +000020371 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020372 v8::Isolate* isolate = env->GetIsolate();
20373 v8::HandleScope scope(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000020374 { // Check normal properties and defined getters.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020375 Local<Value> value = CompileRun(
Ben Murdoch257744e2011-11-30 15:57:28 +000020376 "function Foo() {"
20377 " this.foo = 11;"
20378 " this.__defineGetter__('baz', function() { return 1; });"
20379 "};"
20380 "function Bar() { "
20381 " this.bar = 13;"
20382 " this.__defineGetter__('bla', function() { return 2; });"
20383 "};"
20384 "Bar.prototype = new Foo();"
20385 "new Bar();");
20386 CHECK(value->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020387 Local<Object> object = value->ToObject(env.local()).ToLocalChecked();
20388 CHECK(object->Has(env.local(), v8_str("foo")).FromJust());
20389 CHECK(!object->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
20390 CHECK(object->HasOwnProperty(env.local(), v8_str("bar")).FromJust());
20391 CHECK(object->Has(env.local(), v8_str("baz")).FromJust());
20392 CHECK(!object->HasOwnProperty(env.local(), v8_str("baz")).FromJust());
20393 CHECK(object->HasOwnProperty(env.local(), v8_str("bla")).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000020394 }
20395 { // Check named getter interceptors.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020396 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020397 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
20398 HasOwnPropertyNamedPropertyGetter));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020399 Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
20400 CHECK(!instance->HasOwnProperty(env.local(), v8_str("42")).FromJust());
Ben Murdochc5610432016-08-08 18:44:38 +010020401 CHECK(!instance->HasOwnProperty(env.local(), 42).FromJust());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020402 CHECK(instance->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
20403 CHECK(!instance->HasOwnProperty(env.local(), v8_str("bar")).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000020404 }
20405 { // Check indexed getter interceptors.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020406 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020407 templ->SetHandler(v8::IndexedPropertyHandlerConfiguration(
20408 HasOwnPropertyIndexedPropertyGetter));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020409 Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
20410 CHECK(instance->HasOwnProperty(env.local(), v8_str("42")).FromJust());
Ben Murdochc5610432016-08-08 18:44:38 +010020411 CHECK(instance->HasOwnProperty(env.local(), 42).FromJust());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020412 CHECK(!instance->HasOwnProperty(env.local(), v8_str("43")).FromJust());
Ben Murdochc5610432016-08-08 18:44:38 +010020413 CHECK(!instance->HasOwnProperty(env.local(), 43).FromJust());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020414 CHECK(!instance->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000020415 }
20416 { // Check named query interceptors.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020417 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020418 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
20419 0, 0, HasOwnPropertyNamedPropertyQuery));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020420 Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
20421 CHECK(instance->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
20422 CHECK(!instance->HasOwnProperty(env.local(), v8_str("bar")).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000020423 }
20424 { // Check indexed query interceptors.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020425 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020426 templ->SetHandler(v8::IndexedPropertyHandlerConfiguration(
20427 0, 0, HasOwnPropertyIndexedPropertyQuery));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020428 Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
20429 CHECK(instance->HasOwnProperty(env.local(), v8_str("42")).FromJust());
Ben Murdochc5610432016-08-08 18:44:38 +010020430 CHECK(instance->HasOwnProperty(env.local(), 42).FromJust());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020431 CHECK(!instance->HasOwnProperty(env.local(), v8_str("41")).FromJust());
Ben Murdochc5610432016-08-08 18:44:38 +010020432 CHECK(!instance->HasOwnProperty(env.local(), 41).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000020433 }
20434 { // Check callbacks.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020435 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000020436 templ->SetAccessor(v8_str("foo"), HasOwnPropertyAccessorGetter);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020437 Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
20438 CHECK(instance->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
20439 CHECK(!instance->HasOwnProperty(env.local(), v8_str("bar")).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000020440 }
20441 { // Check that query wins on disagreement.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020442 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020443 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
20444 HasOwnPropertyNamedPropertyGetter, 0,
20445 HasOwnPropertyNamedPropertyQuery2));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020446 Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
20447 CHECK(!instance->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
20448 CHECK(instance->HasOwnProperty(env.local(), v8_str("bar")).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000020449 }
20450}
20451
20452
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020453TEST(IndexedInterceptorWithStringProto) {
20454 v8::Isolate* isolate = CcTest::isolate();
20455 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020456 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020457 templ->SetHandler(v8::IndexedPropertyHandlerConfiguration(
20458 NULL, NULL, HasOwnPropertyIndexedPropertyQuery));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020459 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020460 CHECK(context->Global()
20461 ->Set(context.local(), v8_str("obj"),
20462 templ->NewInstance(context.local()).ToLocalChecked())
20463 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020464 CompileRun("var s = new String('foobar'); obj.__proto__ = s;");
20465 // These should be intercepted.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020466 CHECK(CompileRun("42 in obj")->BooleanValue(context.local()).FromJust());
20467 CHECK(CompileRun("'42' in obj")->BooleanValue(context.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020468 // These should fall through to the String prototype.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020469 CHECK(CompileRun("0 in obj")->BooleanValue(context.local()).FromJust());
20470 CHECK(CompileRun("'0' in obj")->BooleanValue(context.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020471 // And these should both fail.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020472 CHECK(!CompileRun("32 in obj")->BooleanValue(context.local()).FromJust());
20473 CHECK(!CompileRun("'32' in obj")->BooleanValue(context.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020474}
20475
20476
Ben Murdoch257744e2011-11-30 15:57:28 +000020477void CheckCodeGenerationAllowed() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020478 Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
20479 Local<Value> result = CompileRun("eval('42')");
20480 CHECK_EQ(42, result->Int32Value(context).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000020481 result = CompileRun("(function(e) { return e('42'); })(eval)");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020482 CHECK_EQ(42, result->Int32Value(context).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000020483 result = CompileRun("var f = new Function('return 42'); f()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020484 CHECK_EQ(42, result->Int32Value(context).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000020485}
20486
20487
20488void CheckCodeGenerationDisallowed() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020489 TryCatch try_catch(CcTest::isolate());
Ben Murdoch257744e2011-11-30 15:57:28 +000020490
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020491 Local<Value> result = CompileRun("eval('42')");
Ben Murdoch257744e2011-11-30 15:57:28 +000020492 CHECK(result.IsEmpty());
20493 CHECK(try_catch.HasCaught());
20494 try_catch.Reset();
20495
20496 result = CompileRun("(function(e) { return e('42'); })(eval)");
20497 CHECK(result.IsEmpty());
20498 CHECK(try_catch.HasCaught());
20499 try_catch.Reset();
20500
20501 result = CompileRun("var f = new Function('return 42'); f()");
20502 CHECK(result.IsEmpty());
20503 CHECK(try_catch.HasCaught());
20504}
20505
20506
20507bool CodeGenerationAllowed(Local<Context> context) {
20508 ApiTestFuzzer::Fuzz();
20509 return true;
20510}
20511
20512
20513bool CodeGenerationDisallowed(Local<Context> context) {
20514 ApiTestFuzzer::Fuzz();
20515 return false;
20516}
20517
20518
20519THREADED_TEST(AllowCodeGenFromStrings) {
Ben Murdoch257744e2011-11-30 15:57:28 +000020520 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020521 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch257744e2011-11-30 15:57:28 +000020522
20523 // eval and the Function constructor allowed by default.
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020524 CHECK(context->IsCodeGenerationFromStringsAllowed());
Ben Murdoch257744e2011-11-30 15:57:28 +000020525 CheckCodeGenerationAllowed();
20526
20527 // Disallow eval and the Function constructor.
20528 context->AllowCodeGenerationFromStrings(false);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020529 CHECK(!context->IsCodeGenerationFromStringsAllowed());
Ben Murdoch257744e2011-11-30 15:57:28 +000020530 CheckCodeGenerationDisallowed();
20531
20532 // Allow again.
20533 context->AllowCodeGenerationFromStrings(true);
20534 CheckCodeGenerationAllowed();
20535
20536 // Disallow but setting a global callback that will allow the calls.
20537 context->AllowCodeGenerationFromStrings(false);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020538 context->GetIsolate()->SetAllowCodeGenerationFromStringsCallback(
20539 &CodeGenerationAllowed);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020540 CHECK(!context->IsCodeGenerationFromStringsAllowed());
Ben Murdoch257744e2011-11-30 15:57:28 +000020541 CheckCodeGenerationAllowed();
20542
20543 // Set a callback that disallows the code generation.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020544 context->GetIsolate()->SetAllowCodeGenerationFromStringsCallback(
20545 &CodeGenerationDisallowed);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020546 CHECK(!context->IsCodeGenerationFromStringsAllowed());
Ben Murdoch257744e2011-11-30 15:57:28 +000020547 CheckCodeGenerationDisallowed();
20548}
20549
20550
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020551TEST(SetErrorMessageForCodeGenFromStrings) {
20552 LocalContext context;
20553 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020554 TryCatch try_catch(context->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020555
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020556 Local<String> message = v8_str("Message");
20557 Local<String> expected_message = v8_str("Uncaught EvalError: Message");
20558 context->GetIsolate()->SetAllowCodeGenerationFromStringsCallback(
20559 &CodeGenerationDisallowed);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020560 context->AllowCodeGenerationFromStrings(false);
20561 context->SetErrorMessageForCodeGenerationFromStrings(message);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020562 Local<Value> result = CompileRun("eval('42')");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020563 CHECK(result.IsEmpty());
20564 CHECK(try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020565 Local<String> actual_message = try_catch.Message()->Get();
20566 CHECK(expected_message->Equals(context.local(), actual_message).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020567}
20568
20569
20570static void NonObjectThis(const v8::FunctionCallbackInfo<v8::Value>& args) {
Ben Murdoch257744e2011-11-30 15:57:28 +000020571}
20572
20573
20574THREADED_TEST(CallAPIFunctionOnNonObject) {
Ben Murdoch257744e2011-11-30 15:57:28 +000020575 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020576 v8::Isolate* isolate = context->GetIsolate();
20577 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020578 Local<FunctionTemplate> templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020579 v8::FunctionTemplate::New(isolate, NonObjectThis);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020580 Local<Function> function =
20581 templ->GetFunction(context.local()).ToLocalChecked();
20582 CHECK(context->Global()
20583 ->Set(context.local(), v8_str("f"), function)
20584 .FromJust());
20585 TryCatch try_catch(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000020586 CompileRun("f.call(2)");
20587}
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020588
20589
20590// Regression test for issue 1470.
20591THREADED_TEST(ReadOnlyIndexedProperties) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020592 v8::Isolate* isolate = CcTest::isolate();
20593 v8::HandleScope scope(isolate);
20594 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020595
20596 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020597 Local<v8::Object> obj = templ->NewInstance(context.local()).ToLocalChecked();
20598 CHECK(context->Global()->Set(context.local(), v8_str("obj"), obj).FromJust());
20599 obj->DefineOwnProperty(context.local(), v8_str("1"), v8_str("DONT_CHANGE"),
20600 v8::ReadOnly)
20601 .FromJust();
20602 obj->Set(context.local(), v8_str("1"), v8_str("foobar")).FromJust();
20603 CHECK(v8_str("DONT_CHANGE")
20604 ->Equals(context.local(),
20605 obj->Get(context.local(), v8_str("1")).ToLocalChecked())
20606 .FromJust());
20607 obj->DefineOwnProperty(context.local(), v8_str("2"), v8_str("DONT_CHANGE"),
20608 v8::ReadOnly)
20609 .FromJust();
20610 obj->Set(context.local(), v8_num(2), v8_str("foobar")).FromJust();
20611 CHECK(v8_str("DONT_CHANGE")
20612 ->Equals(context.local(),
20613 obj->Get(context.local(), v8_num(2)).ToLocalChecked())
20614 .FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020615
20616 // Test non-smi case.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020617 obj->DefineOwnProperty(context.local(), v8_str("2000000000"),
20618 v8_str("DONT_CHANGE"), v8::ReadOnly)
20619 .FromJust();
20620 obj->Set(context.local(), v8_str("2000000000"), v8_str("foobar")).FromJust();
20621 CHECK(v8_str("DONT_CHANGE")
20622 ->Equals(context.local(),
20623 obj->Get(context.local(), v8_str("2000000000"))
20624 .ToLocalChecked())
20625 .FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020626}
20627
20628
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020629static int CountLiveMapsInMapCache(i::Context* context) {
20630 i::FixedArray* map_cache = i::FixedArray::cast(context->map_cache());
20631 int length = map_cache->length();
20632 int count = 0;
20633 for (int i = 0; i < length; i++) {
20634 i::Object* value = map_cache->get(i);
20635 if (value->IsWeakCell() && !i::WeakCell::cast(value)->cleared()) count++;
20636 }
20637 return count;
20638}
20639
20640
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020641THREADED_TEST(Regress1516) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020642 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020643 v8::HandleScope scope(context->GetIsolate());
20644
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020645 // Object with 20 properties is not a common case, so it should be removed
20646 // from the cache after GC.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020647 { v8::HandleScope temp_scope(context->GetIsolate());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020648 CompileRun(
20649 "({"
20650 "'a00': 0, 'a01': 0, 'a02': 0, 'a03': 0, 'a04': 0, "
20651 "'a05': 0, 'a06': 0, 'a07': 0, 'a08': 0, 'a09': 0, "
20652 "'a10': 0, 'a11': 0, 'a12': 0, 'a13': 0, 'a14': 0, "
20653 "'a15': 0, 'a16': 0, 'a17': 0, 'a18': 0, 'a19': 0, "
20654 "})");
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020655 }
20656
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020657 int elements = CountLiveMapsInMapCache(CcTest::i_isolate()->context());
20658 CHECK_LE(1, elements);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020659
Ben Murdochda12d292016-06-02 14:46:10 +010020660 // We have to abort incremental marking here to abandon black pages.
20661 CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020662
20663 CHECK_GT(elements, CountLiveMapsInMapCache(CcTest::i_isolate()->context()));
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020664}
20665
20666
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020667THREADED_TEST(Regress93759) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020668 v8::Isolate* isolate = CcTest::isolate();
20669 HandleScope scope(isolate);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020670
20671 // Template for object with security check.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020672 Local<ObjectTemplate> no_proto_template = v8::ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020673 no_proto_template->SetAccessCheckCallback(AccessAlwaysBlocked);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020674
20675 // Templates for objects with hidden prototypes and possibly security check.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020676 Local<FunctionTemplate> hidden_proto_template =
20677 v8::FunctionTemplate::New(isolate);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020678 hidden_proto_template->SetHiddenPrototype(true);
20679
20680 Local<FunctionTemplate> protected_hidden_proto_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020681 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020682 protected_hidden_proto_template->InstanceTemplate()->SetAccessCheckCallback(
20683 AccessAlwaysBlocked);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020684 protected_hidden_proto_template->SetHiddenPrototype(true);
20685
20686 // Context for "foreign" objects used in test.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020687 Local<Context> context = v8::Context::New(isolate);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020688 context->Enter();
20689
20690 // Plain object, no security check.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020691 Local<Object> simple_object = Object::New(isolate);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020692
20693 // Object with explicit security check.
20694 Local<Object> protected_object =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020695 no_proto_template->NewInstance(context).ToLocalChecked();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020696
20697 // JSGlobalProxy object, always have security check.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020698 Local<Object> proxy_object = context->Global();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020699
20700 // Global object, the prototype of proxy_object. No security checks.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020701 Local<Object> global_object =
20702 proxy_object->GetPrototype()->ToObject(context).ToLocalChecked();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020703
20704 // Hidden prototype without security check.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020705 Local<Object> hidden_prototype = hidden_proto_template->GetFunction(context)
20706 .ToLocalChecked()
20707 ->NewInstance(context)
20708 .ToLocalChecked();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020709 Local<Object> object_with_hidden =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020710 Object::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020711 object_with_hidden->SetPrototype(context, hidden_prototype).FromJust();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020712
20713 context->Exit();
20714
Ben Murdoch097c5b22016-05-18 11:27:45 +010020715 LocalContext context2;
20716 v8::Local<v8::Object> global = context2->Global();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020717
Ben Murdoch097c5b22016-05-18 11:27:45 +010020718 // Setup global variables.
20719 CHECK(global->Set(context2.local(), v8_str("simple"), simple_object)
20720 .FromJust());
20721 CHECK(global->Set(context2.local(), v8_str("protected"), protected_object)
20722 .FromJust());
20723 CHECK(global->Set(context2.local(), v8_str("global"), global_object)
20724 .FromJust());
20725 CHECK(
20726 global->Set(context2.local(), v8_str("proxy"), proxy_object).FromJust());
20727 CHECK(global->Set(context2.local(), v8_str("hidden"), object_with_hidden)
20728 .FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020729
20730 Local<Value> result1 = CompileRun("Object.getPrototypeOf(simple)");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020731 CHECK(result1->Equals(context2.local(), simple_object->GetPrototype())
20732 .FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020733
20734 Local<Value> result2 = CompileRun("Object.getPrototypeOf(protected)");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020735 CHECK(result2->IsNull());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020736
20737 Local<Value> result3 = CompileRun("Object.getPrototypeOf(global)");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020738 CHECK(result3->Equals(context2.local(), global_object->GetPrototype())
20739 .FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020740
20741 Local<Value> result4 = CompileRun("Object.getPrototypeOf(proxy)");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020742 CHECK(result4->IsNull());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020743
20744 Local<Value> result5 = CompileRun("Object.getPrototypeOf(hidden)");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020745 CHECK(result5->Equals(context2.local(), object_with_hidden->GetPrototype()
20746 ->ToObject(context2.local())
20747 .ToLocalChecked()
20748 ->GetPrototype())
20749 .FromJust());
Ben Murdoch5710cea2012-05-21 14:52:42 +010020750}
20751
20752
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020753static void TestReceiver(Local<Value> expected_result,
20754 Local<Value> expected_receiver,
20755 const char* code) {
20756 Local<Value> result = CompileRun(code);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020757 Local<Context> context = CcTest::isolate()->GetCurrentContext();
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020758 CHECK(result->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020759 CHECK(expected_receiver
20760 ->Equals(context,
20761 result.As<v8::Object>()->Get(context, 1).ToLocalChecked())
20762 .FromJust());
20763 CHECK(expected_result
20764 ->Equals(context,
20765 result.As<v8::Object>()->Get(context, 0).ToLocalChecked())
20766 .FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020767}
20768
20769
20770THREADED_TEST(ForeignFunctionReceiver) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020771 v8::Isolate* isolate = CcTest::isolate();
20772 HandleScope scope(isolate);
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020773
20774 // Create two contexts with different "id" properties ('i' and 'o').
20775 // Call a function both from its own context and from a the foreign
20776 // context, and see what "this" is bound to (returning both "this"
20777 // and "this.id" for comparison).
20778
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020779 Local<Context> foreign_context = v8::Context::New(isolate);
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020780 foreign_context->Enter();
20781 Local<Value> foreign_function =
20782 CompileRun("function func() { return { 0: this.id, "
20783 " 1: this, "
20784 " toString: function() { "
20785 " return this[0];"
20786 " }"
20787 " };"
20788 "}"
20789 "var id = 'i';"
20790 "func;");
20791 CHECK(foreign_function->IsFunction());
20792 foreign_context->Exit();
20793
20794 LocalContext context;
20795
20796 Local<String> password = v8_str("Password");
20797 // Don't get hit by security checks when accessing foreign_context's
20798 // global receiver (aka. global proxy).
20799 context->SetSecurityToken(password);
20800 foreign_context->SetSecurityToken(password);
20801
20802 Local<String> i = v8_str("i");
20803 Local<String> o = v8_str("o");
20804 Local<String> id = v8_str("id");
20805
20806 CompileRun("function ownfunc() { return { 0: this.id, "
20807 " 1: this, "
20808 " toString: function() { "
20809 " return this[0];"
20810 " }"
20811 " };"
20812 "}"
20813 "var id = 'o';"
20814 "ownfunc");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020815 CHECK(context->Global()
20816 ->Set(context.local(), v8_str("func"), foreign_function)
20817 .FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020818
20819 // Sanity check the contexts.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020820 CHECK(
20821 i->Equals(
20822 context.local(),
20823 foreign_context->Global()->Get(context.local(), id).ToLocalChecked())
20824 .FromJust());
20825 CHECK(o->Equals(context.local(),
20826 context->Global()->Get(context.local(), id).ToLocalChecked())
20827 .FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020828
20829 // Checking local function's receiver.
20830 // Calling function using its call/apply methods.
20831 TestReceiver(o, context->Global(), "ownfunc.call()");
20832 TestReceiver(o, context->Global(), "ownfunc.apply()");
20833 // Making calls through built-in functions.
20834 TestReceiver(o, context->Global(), "[1].map(ownfunc)[0]");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020835 CHECK(
20836 o->Equals(context.local(), CompileRun("'abcbd'.replace(/b/,ownfunc)[1]"))
20837 .FromJust());
20838 CHECK(
20839 o->Equals(context.local(), CompileRun("'abcbd'.replace(/b/g,ownfunc)[1]"))
20840 .FromJust());
20841 CHECK(
20842 o->Equals(context.local(), CompileRun("'abcbd'.replace(/b/g,ownfunc)[3]"))
20843 .FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020844 // Calling with environment record as base.
20845 TestReceiver(o, context->Global(), "ownfunc()");
20846 // Calling with no base.
20847 TestReceiver(o, context->Global(), "(1,ownfunc)()");
20848
20849 // Checking foreign function return value.
20850 // Calling function using its call/apply methods.
20851 TestReceiver(i, foreign_context->Global(), "func.call()");
20852 TestReceiver(i, foreign_context->Global(), "func.apply()");
20853 // Calling function using another context's call/apply methods.
20854 TestReceiver(i, foreign_context->Global(),
20855 "Function.prototype.call.call(func)");
20856 TestReceiver(i, foreign_context->Global(),
20857 "Function.prototype.call.apply(func)");
20858 TestReceiver(i, foreign_context->Global(),
20859 "Function.prototype.apply.call(func)");
20860 TestReceiver(i, foreign_context->Global(),
20861 "Function.prototype.apply.apply(func)");
20862 // Making calls through built-in functions.
20863 TestReceiver(i, foreign_context->Global(), "[1].map(func)[0]");
20864 // ToString(func()) is func()[0], i.e., the returned this.id.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020865 CHECK(i->Equals(context.local(), CompileRun("'abcbd'.replace(/b/,func)[1]"))
20866 .FromJust());
20867 CHECK(i->Equals(context.local(), CompileRun("'abcbd'.replace(/b/g,func)[1]"))
20868 .FromJust());
20869 CHECK(i->Equals(context.local(), CompileRun("'abcbd'.replace(/b/g,func)[3]"))
20870 .FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020871
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020872 // Calling with environment record as base.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020873 TestReceiver(i, foreign_context->Global(), "func()");
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020874 // Calling with no base.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020875 TestReceiver(i, foreign_context->Global(), "(1,func)()");
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020876}
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020877
20878
20879uint8_t callback_fired = 0;
Ben Murdoch097c5b22016-05-18 11:27:45 +010020880uint8_t before_call_entered_callback_count1 = 0;
20881uint8_t before_call_entered_callback_count2 = 0;
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020882
20883
Ben Murdoch097c5b22016-05-18 11:27:45 +010020884void CallCompletedCallback1(v8::Isolate*) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020885 v8::base::OS::Print("Firing callback 1.\n");
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020886 callback_fired ^= 1; // Toggle first bit.
20887}
20888
20889
Ben Murdoch097c5b22016-05-18 11:27:45 +010020890void CallCompletedCallback2(v8::Isolate*) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020891 v8::base::OS::Print("Firing callback 2.\n");
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020892 callback_fired ^= 2; // Toggle second bit.
20893}
20894
20895
Ben Murdoch097c5b22016-05-18 11:27:45 +010020896void BeforeCallEnteredCallback1(v8::Isolate*) {
20897 v8::base::OS::Print("Firing before call entered callback 1.\n");
20898 before_call_entered_callback_count1++;
20899}
20900
20901
20902void BeforeCallEnteredCallback2(v8::Isolate*) {
20903 v8::base::OS::Print("Firing before call entered callback 2.\n");
20904 before_call_entered_callback_count2++;
20905}
20906
20907
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020908void RecursiveCall(const v8::FunctionCallbackInfo<v8::Value>& args) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020909 int32_t level =
20910 args[0]->Int32Value(args.GetIsolate()->GetCurrentContext()).FromJust();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020911 if (level < 3) {
20912 level++;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020913 v8::base::OS::Print("Entering recursion level %d.\n", level);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020914 char script[64];
20915 i::Vector<char> script_vector(script, sizeof(script));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020916 i::SNPrintF(script_vector, "recursion(%d)", level);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020917 CompileRun(script_vector.start());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020918 v8::base::OS::Print("Leaving recursion level %d.\n", level);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020919 CHECK_EQ(0, callback_fired);
20920 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020921 v8::base::OS::Print("Recursion ends.\n");
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020922 CHECK_EQ(0, callback_fired);
20923 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020924}
20925
20926
20927TEST(CallCompletedCallback) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020928 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020929 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020930 v8::Local<v8::FunctionTemplate> recursive_runtime =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020931 v8::FunctionTemplate::New(env->GetIsolate(), RecursiveCall);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020932 env->Global()
20933 ->Set(env.local(), v8_str("recursion"),
20934 recursive_runtime->GetFunction(env.local()).ToLocalChecked())
20935 .FromJust();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020936 // Adding the same callback a second time has no effect.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020937 env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback1);
20938 env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback1);
20939 env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback2);
Ben Murdoch097c5b22016-05-18 11:27:45 +010020940 env->GetIsolate()->AddBeforeCallEnteredCallback(BeforeCallEnteredCallback1);
20941 env->GetIsolate()->AddBeforeCallEnteredCallback(BeforeCallEnteredCallback2);
20942 env->GetIsolate()->AddBeforeCallEnteredCallback(BeforeCallEnteredCallback1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020943 v8::base::OS::Print("--- Script (1) ---\n");
Ben Murdoch097c5b22016-05-18 11:27:45 +010020944 callback_fired = 0;
20945 before_call_entered_callback_count1 = 0;
20946 before_call_entered_callback_count2 = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020947 Local<Script> script =
20948 v8::Script::Compile(env.local(), v8_str("recursion(0)")).ToLocalChecked();
20949 script->Run(env.local()).ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020950 CHECK_EQ(3, callback_fired);
Ben Murdoch097c5b22016-05-18 11:27:45 +010020951 CHECK_EQ(4, before_call_entered_callback_count1);
20952 CHECK_EQ(4, before_call_entered_callback_count2);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020953
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020954 v8::base::OS::Print("\n--- Script (2) ---\n");
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020955 callback_fired = 0;
Ben Murdoch097c5b22016-05-18 11:27:45 +010020956 before_call_entered_callback_count1 = 0;
20957 before_call_entered_callback_count2 = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020958 env->GetIsolate()->RemoveCallCompletedCallback(CallCompletedCallback1);
Ben Murdoch097c5b22016-05-18 11:27:45 +010020959 env->GetIsolate()->RemoveBeforeCallEnteredCallback(
20960 BeforeCallEnteredCallback1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020961 script->Run(env.local()).ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020962 CHECK_EQ(2, callback_fired);
Ben Murdoch097c5b22016-05-18 11:27:45 +010020963 CHECK_EQ(0, before_call_entered_callback_count1);
20964 CHECK_EQ(4, before_call_entered_callback_count2);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020965
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020966 v8::base::OS::Print("\n--- Function ---\n");
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020967 callback_fired = 0;
Ben Murdoch097c5b22016-05-18 11:27:45 +010020968 before_call_entered_callback_count1 = 0;
20969 before_call_entered_callback_count2 = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020970 Local<Function> recursive_function = Local<Function>::Cast(
20971 env->Global()->Get(env.local(), v8_str("recursion")).ToLocalChecked());
20972 v8::Local<Value> args[] = {v8_num(0)};
20973 recursive_function->Call(env.local(), env->Global(), 1, args)
20974 .ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020975 CHECK_EQ(2, callback_fired);
Ben Murdoch097c5b22016-05-18 11:27:45 +010020976 CHECK_EQ(0, before_call_entered_callback_count1);
20977 CHECK_EQ(4, before_call_entered_callback_count2);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020978}
20979
20980
Ben Murdoch097c5b22016-05-18 11:27:45 +010020981void CallCompletedCallbackNoException(v8::Isolate*) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020982 v8::HandleScope scope(CcTest::isolate());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020983 CompileRun("1+1;");
20984}
20985
20986
Ben Murdoch097c5b22016-05-18 11:27:45 +010020987void CallCompletedCallbackException(v8::Isolate*) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020988 v8::HandleScope scope(CcTest::isolate());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020989 CompileRun("throw 'second exception';");
20990}
20991
20992
20993TEST(CallCompletedCallbackOneException) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020994 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020995 v8::HandleScope scope(env->GetIsolate());
20996 env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallbackNoException);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020997 CompileRun("throw 'exception';");
20998}
20999
21000
21001TEST(CallCompletedCallbackTwoExceptions) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010021002 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021003 v8::HandleScope scope(env->GetIsolate());
21004 env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallbackException);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010021005 CompileRun("throw 'first exception';");
21006}
21007
21008
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021009static void MicrotaskOne(const v8::FunctionCallbackInfo<Value>& info) {
Ben Murdochc5610432016-08-08 18:44:38 +010021010 CHECK(v8::MicrotasksScope::IsRunningMicrotasks(info.GetIsolate()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021011 v8::HandleScope scope(info.GetIsolate());
Ben Murdochda12d292016-06-02 14:46:10 +010021012 v8::MicrotasksScope microtasks(info.GetIsolate(),
21013 v8::MicrotasksScope::kDoNotRunMicrotasks);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021014 CompileRun("ext1Calls++;");
21015}
21016
21017
21018static void MicrotaskTwo(const v8::FunctionCallbackInfo<Value>& info) {
Ben Murdochc5610432016-08-08 18:44:38 +010021019 CHECK(v8::MicrotasksScope::IsRunningMicrotasks(info.GetIsolate()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021020 v8::HandleScope scope(info.GetIsolate());
Ben Murdochda12d292016-06-02 14:46:10 +010021021 v8::MicrotasksScope microtasks(info.GetIsolate(),
21022 v8::MicrotasksScope::kDoNotRunMicrotasks);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021023 CompileRun("ext2Calls++;");
21024}
21025
21026
21027void* g_passed_to_three = NULL;
21028
21029
21030static void MicrotaskThree(void* data) {
21031 g_passed_to_three = data;
21032}
21033
21034
21035TEST(EnqueueMicrotask) {
21036 LocalContext env;
21037 v8::HandleScope scope(env->GetIsolate());
Ben Murdochc5610432016-08-08 18:44:38 +010021038 CHECK(!v8::MicrotasksScope::IsRunningMicrotasks(env->GetIsolate()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021039 CompileRun(
21040 "var ext1Calls = 0;"
21041 "var ext2Calls = 0;");
21042 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021043 CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21044 CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021045
21046 env->GetIsolate()->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021047 Function::New(env.local(), MicrotaskOne).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021048 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021049 CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21050 CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021051
21052 env->GetIsolate()->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021053 Function::New(env.local(), MicrotaskOne).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021054 env->GetIsolate()->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021055 Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021056 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021057 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21058 CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021059
21060 env->GetIsolate()->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021061 Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021062 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021063 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21064 CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021065
21066 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021067 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21068 CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021069
21070 g_passed_to_three = NULL;
21071 env->GetIsolate()->EnqueueMicrotask(MicrotaskThree);
21072 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021073 CHECK(!g_passed_to_three);
21074 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21075 CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021076
21077 int dummy;
21078 env->GetIsolate()->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021079 Function::New(env.local(), MicrotaskOne).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021080 env->GetIsolate()->EnqueueMicrotask(MicrotaskThree, &dummy);
21081 env->GetIsolate()->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021082 Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021083 CompileRun("1+1;");
21084 CHECK_EQ(&dummy, g_passed_to_three);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021085 CHECK_EQ(3, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21086 CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021087 g_passed_to_three = NULL;
21088}
21089
21090
21091static void MicrotaskExceptionOne(
21092 const v8::FunctionCallbackInfo<Value>& info) {
21093 v8::HandleScope scope(info.GetIsolate());
21094 CompileRun("exception1Calls++;");
21095 info.GetIsolate()->ThrowException(
21096 v8::Exception::Error(v8_str("first")));
21097}
21098
21099
21100static void MicrotaskExceptionTwo(
21101 const v8::FunctionCallbackInfo<Value>& info) {
21102 v8::HandleScope scope(info.GetIsolate());
21103 CompileRun("exception2Calls++;");
21104 info.GetIsolate()->ThrowException(
21105 v8::Exception::Error(v8_str("second")));
21106}
21107
21108
21109TEST(RunMicrotasksIgnoresThrownExceptions) {
21110 LocalContext env;
21111 v8::Isolate* isolate = env->GetIsolate();
21112 v8::HandleScope scope(isolate);
21113 CompileRun(
21114 "var exception1Calls = 0;"
21115 "var exception2Calls = 0;");
21116 isolate->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021117 Function::New(env.local(), MicrotaskExceptionOne).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021118 isolate->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021119 Function::New(env.local(), MicrotaskExceptionTwo).ToLocalChecked());
21120 TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021121 CompileRun("1+1;");
21122 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021123 CHECK_EQ(1,
21124 CompileRun("exception1Calls")->Int32Value(env.local()).FromJust());
21125 CHECK_EQ(1,
21126 CompileRun("exception2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021127}
21128
21129
Ben Murdochda12d292016-06-02 14:46:10 +010021130uint8_t microtasks_completed_callback_count = 0;
21131
21132
21133static void MicrotasksCompletedCallback(v8::Isolate* isolate) {
21134 ++microtasks_completed_callback_count;
21135}
21136
21137
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021138TEST(SetAutorunMicrotasks) {
21139 LocalContext env;
21140 v8::HandleScope scope(env->GetIsolate());
Ben Murdochda12d292016-06-02 14:46:10 +010021141 env->GetIsolate()->AddMicrotasksCompletedCallback(
21142 &MicrotasksCompletedCallback);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021143 CompileRun(
21144 "var ext1Calls = 0;"
21145 "var ext2Calls = 0;");
21146 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021147 CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21148 CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochda12d292016-06-02 14:46:10 +010021149 CHECK_EQ(0u, microtasks_completed_callback_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021150
21151 env->GetIsolate()->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021152 Function::New(env.local(), MicrotaskOne).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021153 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021154 CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21155 CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochda12d292016-06-02 14:46:10 +010021156 CHECK_EQ(1u, microtasks_completed_callback_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021157
Ben Murdochda12d292016-06-02 14:46:10 +010021158 env->GetIsolate()->SetMicrotasksPolicy(v8::MicrotasksPolicy::kExplicit);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021159 env->GetIsolate()->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021160 Function::New(env.local(), MicrotaskOne).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021161 env->GetIsolate()->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021162 Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021163 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021164 CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21165 CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochda12d292016-06-02 14:46:10 +010021166 CHECK_EQ(1u, microtasks_completed_callback_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021167
21168 env->GetIsolate()->RunMicrotasks();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021169 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21170 CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochda12d292016-06-02 14:46:10 +010021171 CHECK_EQ(2u, microtasks_completed_callback_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021172
21173 env->GetIsolate()->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021174 Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021175 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021176 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21177 CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochda12d292016-06-02 14:46:10 +010021178 CHECK_EQ(2u, microtasks_completed_callback_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021179
21180 env->GetIsolate()->RunMicrotasks();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021181 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21182 CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochda12d292016-06-02 14:46:10 +010021183 CHECK_EQ(3u, microtasks_completed_callback_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021184
Ben Murdochda12d292016-06-02 14:46:10 +010021185 env->GetIsolate()->SetMicrotasksPolicy(v8::MicrotasksPolicy::kAuto);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021186 env->GetIsolate()->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021187 Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021188 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021189 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21190 CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochda12d292016-06-02 14:46:10 +010021191 CHECK_EQ(4u, microtasks_completed_callback_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021192
21193 env->GetIsolate()->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021194 Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021195 {
21196 v8::Isolate::SuppressMicrotaskExecutionScope scope(env->GetIsolate());
21197 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021198 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21199 CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochda12d292016-06-02 14:46:10 +010021200 CHECK_EQ(4u, microtasks_completed_callback_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021201 }
21202
21203 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021204 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21205 CHECK_EQ(4, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochda12d292016-06-02 14:46:10 +010021206 CHECK_EQ(5u, microtasks_completed_callback_count);
21207
21208 env->GetIsolate()->RemoveMicrotasksCompletedCallback(
21209 &MicrotasksCompletedCallback);
21210 env->GetIsolate()->EnqueueMicrotask(
21211 Function::New(env.local(), MicrotaskOne).ToLocalChecked());
21212 CompileRun("1+1;");
21213 CHECK_EQ(3, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21214 CHECK_EQ(4, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
21215 CHECK_EQ(5u, microtasks_completed_callback_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021216}
21217
21218
21219TEST(RunMicrotasksWithoutEnteringContext) {
21220 v8::Isolate* isolate = CcTest::isolate();
21221 HandleScope handle_scope(isolate);
Ben Murdochda12d292016-06-02 14:46:10 +010021222 isolate->SetMicrotasksPolicy(v8::MicrotasksPolicy::kExplicit);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021223 Local<Context> context = Context::New(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021224 {
21225 Context::Scope context_scope(context);
21226 CompileRun("var ext1Calls = 0;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021227 isolate->EnqueueMicrotask(
21228 Function::New(context, MicrotaskOne).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021229 }
21230 isolate->RunMicrotasks();
21231 {
21232 Context::Scope context_scope(context);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021233 CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(context).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021234 }
Ben Murdochda12d292016-06-02 14:46:10 +010021235 isolate->SetMicrotasksPolicy(v8::MicrotasksPolicy::kAuto);
21236}
21237
21238
21239TEST(ScopedMicrotasks) {
21240 LocalContext env;
21241 v8::HandleScope handles(env->GetIsolate());
21242 env->GetIsolate()->SetMicrotasksPolicy(v8::MicrotasksPolicy::kScoped);
21243 {
21244 v8::MicrotasksScope scope1(env->GetIsolate(),
21245 v8::MicrotasksScope::kDoNotRunMicrotasks);
21246 env->GetIsolate()->EnqueueMicrotask(
21247 Function::New(env.local(), MicrotaskOne).ToLocalChecked());
21248 CompileRun(
21249 "var ext1Calls = 0;"
21250 "var ext2Calls = 0;");
21251 CompileRun("1+1;");
21252 CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21253 CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
21254 {
21255 v8::MicrotasksScope scope2(env->GetIsolate(),
21256 v8::MicrotasksScope::kRunMicrotasks);
21257 CompileRun("1+1;");
21258 CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21259 CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
21260 {
21261 v8::MicrotasksScope scope3(env->GetIsolate(),
21262 v8::MicrotasksScope::kRunMicrotasks);
21263 CompileRun("1+1;");
21264 CHECK_EQ(0,
21265 CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21266 CHECK_EQ(0,
21267 CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
21268 }
21269 CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21270 CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
21271 }
21272 CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21273 CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
21274 env->GetIsolate()->EnqueueMicrotask(
21275 Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
21276 }
21277
21278 {
21279 v8::MicrotasksScope scope(env->GetIsolate(),
21280 v8::MicrotasksScope::kDoNotRunMicrotasks);
21281 CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21282 CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
21283 }
21284
21285 {
21286 v8::MicrotasksScope scope1(env->GetIsolate(),
21287 v8::MicrotasksScope::kRunMicrotasks);
21288 CompileRun("1+1;");
21289 CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21290 CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
21291 {
21292 v8::MicrotasksScope scope2(env->GetIsolate(),
21293 v8::MicrotasksScope::kDoNotRunMicrotasks);
21294 }
21295 CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21296 CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
21297 }
21298
21299 {
21300 v8::MicrotasksScope scope(env->GetIsolate(),
21301 v8::MicrotasksScope::kDoNotRunMicrotasks);
21302 CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21303 CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
21304 env->GetIsolate()->EnqueueMicrotask(
21305 Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
21306 }
21307
21308 {
21309 v8::Isolate::SuppressMicrotaskExecutionScope scope1(env->GetIsolate());
21310 {
21311 v8::MicrotasksScope scope2(env->GetIsolate(),
21312 v8::MicrotasksScope::kRunMicrotasks);
21313 }
21314 v8::MicrotasksScope scope3(env->GetIsolate(),
21315 v8::MicrotasksScope::kDoNotRunMicrotasks);
21316 CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21317 CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
21318 }
21319
21320 {
21321 v8::MicrotasksScope scope1(env->GetIsolate(),
21322 v8::MicrotasksScope::kRunMicrotasks);
21323 v8::MicrotasksScope::PerformCheckpoint(env->GetIsolate());
21324 CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21325 CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
21326 }
21327
21328 {
21329 v8::MicrotasksScope scope(env->GetIsolate(),
21330 v8::MicrotasksScope::kDoNotRunMicrotasks);
21331 CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21332 CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
21333 }
21334
21335 v8::MicrotasksScope::PerformCheckpoint(env->GetIsolate());
21336
21337 {
21338 v8::MicrotasksScope scope(env->GetIsolate(),
21339 v8::MicrotasksScope::kDoNotRunMicrotasks);
21340 CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21341 CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
21342 env->GetIsolate()->EnqueueMicrotask(
21343 Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
21344 }
21345
21346 v8::MicrotasksScope::PerformCheckpoint(env->GetIsolate());
21347
21348 {
21349 v8::MicrotasksScope scope(env->GetIsolate(),
21350 v8::MicrotasksScope::kDoNotRunMicrotasks);
21351 CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21352 CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
21353 }
21354
21355 env->GetIsolate()->EnqueueMicrotask(
21356 Function::New(env.local(), MicrotaskOne).ToLocalChecked());
21357 {
21358 v8::Isolate::SuppressMicrotaskExecutionScope scope1(env->GetIsolate());
21359 v8::MicrotasksScope::PerformCheckpoint(env->GetIsolate());
21360 v8::MicrotasksScope scope2(env->GetIsolate(),
21361 v8::MicrotasksScope::kDoNotRunMicrotasks);
21362 CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21363 CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
21364 }
21365
21366 v8::MicrotasksScope::PerformCheckpoint(env->GetIsolate());
21367
21368 {
21369 v8::MicrotasksScope scope(env->GetIsolate(),
21370 v8::MicrotasksScope::kDoNotRunMicrotasks);
21371 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21372 CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
21373 }
21374
21375 env->GetIsolate()->SetMicrotasksPolicy(v8::MicrotasksPolicy::kAuto);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021376}
21377
21378
Emily Bernierd0a1eb72015-03-24 16:35:39 -040021379#ifdef ENABLE_DISASSEMBLER
Ben Murdoch3ef787d2012-04-12 10:51:47 +010021380static int probes_counter = 0;
21381static int misses_counter = 0;
21382static int updates_counter = 0;
21383
21384
21385static int* LookupCounter(const char* name) {
21386 if (strcmp(name, "c:V8.MegamorphicStubCacheProbes") == 0) {
21387 return &probes_counter;
21388 } else if (strcmp(name, "c:V8.MegamorphicStubCacheMisses") == 0) {
21389 return &misses_counter;
21390 } else if (strcmp(name, "c:V8.MegamorphicStubCacheUpdates") == 0) {
21391 return &updates_counter;
21392 }
21393 return NULL;
21394}
21395
21396
21397static const char* kMegamorphicTestProgram =
21398 "function ClassA() { };"
21399 "function ClassB() { };"
21400 "ClassA.prototype.foo = function() { };"
21401 "ClassB.prototype.foo = function() { };"
21402 "function fooify(obj) { obj.foo(); };"
21403 "var a = new ClassA();"
21404 "var b = new ClassB();"
21405 "for (var i = 0; i < 10000; i++) {"
21406 " fooify(a);"
21407 " fooify(b);"
21408 "}";
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021409#endif
Ben Murdoch3ef787d2012-04-12 10:51:47 +010021410
21411
21412static void StubCacheHelper(bool primary) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040021413#ifdef ENABLE_DISASSEMBLER
Ben Murdoch3ef787d2012-04-12 10:51:47 +010021414 i::FLAG_native_code_counters = true;
21415 if (primary) {
21416 i::FLAG_test_primary_stub_cache = true;
21417 } else {
21418 i::FLAG_test_secondary_stub_cache = true;
21419 }
21420 i::FLAG_crankshaft = false;
Ben Murdoch3ef787d2012-04-12 10:51:47 +010021421 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021422 env->GetIsolate()->SetCounterFunction(LookupCounter);
21423 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010021424 int initial_probes = probes_counter;
21425 int initial_misses = misses_counter;
21426 int initial_updates = updates_counter;
21427 CompileRun(kMegamorphicTestProgram);
21428 int probes = probes_counter - initial_probes;
21429 int misses = misses_counter - initial_misses;
21430 int updates = updates_counter - initial_updates;
21431 CHECK_LT(updates, 10);
21432 CHECK_LT(misses, 10);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021433 // TODO(verwaest): Update this test to overflow the degree of polymorphism
21434 // before megamorphism. The number of probes will only work once we teach the
21435 // serializer to embed references to counters in the stubs, given that the
21436 // megamorphic_stub_cache_probes is updated in a snapshot-generated stub.
21437 CHECK_GE(probes, 0);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010021438#endif
21439}
21440
21441
21442TEST(SecondaryStubCache) {
21443 StubCacheHelper(true);
21444}
21445
21446
21447TEST(PrimaryStubCache) {
21448 StubCacheHelper(false);
21449}
21450
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021451
21452#ifdef DEBUG
21453static int cow_arrays_created_runtime = 0;
21454
21455
21456static int* LookupCounterCOWArrays(const char* name) {
21457 if (strcmp(name, "c:V8.COWArraysCreatedRuntime") == 0) {
21458 return &cow_arrays_created_runtime;
21459 }
21460 return NULL;
21461}
21462#endif
21463
21464
21465TEST(CheckCOWArraysCreatedRuntimeCounter) {
21466#ifdef DEBUG
21467 i::FLAG_native_code_counters = true;
21468 LocalContext env;
21469 env->GetIsolate()->SetCounterFunction(LookupCounterCOWArrays);
21470 v8::HandleScope scope(env->GetIsolate());
21471 int initial_cow_arrays = cow_arrays_created_runtime;
21472 CompileRun("var o = [1, 2, 3];");
21473 CHECK_EQ(1, cow_arrays_created_runtime - initial_cow_arrays);
21474 CompileRun("var o = {foo: [4, 5, 6], bar: [3, 0]};");
21475 CHECK_EQ(3, cow_arrays_created_runtime - initial_cow_arrays);
21476 CompileRun("var o = {foo: [1, 2, 3, [4, 5, 6]], bar: 'hi'};");
21477 CHECK_EQ(4, cow_arrays_created_runtime - initial_cow_arrays);
21478#endif
21479}
21480
21481
21482TEST(StaticGetters) {
21483 LocalContext context;
21484 i::Factory* factory = CcTest::i_isolate()->factory();
21485 v8::Isolate* isolate = CcTest::isolate();
21486 v8::HandleScope scope(isolate);
21487 i::Handle<i::Object> undefined_value = factory->undefined_value();
21488 CHECK(*v8::Utils::OpenHandle(*v8::Undefined(isolate)) == *undefined_value);
21489 i::Handle<i::Object> null_value = factory->null_value();
21490 CHECK(*v8::Utils::OpenHandle(*v8::Null(isolate)) == *null_value);
21491 i::Handle<i::Object> true_value = factory->true_value();
21492 CHECK(*v8::Utils::OpenHandle(*v8::True(isolate)) == *true_value);
21493 i::Handle<i::Object> false_value = factory->false_value();
21494 CHECK(*v8::Utils::OpenHandle(*v8::False(isolate)) == *false_value);
21495}
21496
21497
21498UNINITIALIZED_TEST(IsolateEmbedderData) {
21499 CcTest::DisableAutomaticDispose();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021500 v8::Isolate::CreateParams create_params;
21501 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
21502 v8::Isolate* isolate = v8::Isolate::New(create_params);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021503 isolate->Enter();
21504 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
21505 for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021506 CHECK(!isolate->GetData(slot));
21507 CHECK(!i_isolate->GetData(slot));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021508 }
21509 for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
21510 void* data = reinterpret_cast<void*>(0xacce55ed + slot);
21511 isolate->SetData(slot, data);
21512 }
21513 for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
21514 void* data = reinterpret_cast<void*>(0xacce55ed + slot);
21515 CHECK_EQ(data, isolate->GetData(slot));
21516 CHECK_EQ(data, i_isolate->GetData(slot));
21517 }
21518 for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
21519 void* data = reinterpret_cast<void*>(0xdecea5ed + slot);
21520 isolate->SetData(slot, data);
21521 }
21522 for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
21523 void* data = reinterpret_cast<void*>(0xdecea5ed + slot);
21524 CHECK_EQ(data, isolate->GetData(slot));
21525 CHECK_EQ(data, i_isolate->GetData(slot));
21526 }
21527 isolate->Exit();
21528 isolate->Dispose();
21529}
21530
21531
21532TEST(StringEmpty) {
21533 LocalContext context;
21534 i::Factory* factory = CcTest::i_isolate()->factory();
21535 v8::Isolate* isolate = CcTest::isolate();
21536 v8::HandleScope scope(isolate);
21537 i::Handle<i::Object> empty_string = factory->empty_string();
21538 CHECK(*v8::Utils::OpenHandle(*v8::String::Empty(isolate)) == *empty_string);
21539}
21540
21541
21542static int instance_checked_getter_count = 0;
21543static void InstanceCheckedGetter(
21544 Local<String> name,
21545 const v8::PropertyCallbackInfo<v8::Value>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021546 CHECK(name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
21547 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021548 instance_checked_getter_count++;
21549 info.GetReturnValue().Set(v8_num(11));
21550}
21551
21552
21553static int instance_checked_setter_count = 0;
21554static void InstanceCheckedSetter(Local<String> name,
21555 Local<Value> value,
21556 const v8::PropertyCallbackInfo<void>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021557 CHECK(name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
21558 .FromJust());
21559 CHECK(value->Equals(info.GetIsolate()->GetCurrentContext(), v8_num(23))
21560 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021561 instance_checked_setter_count++;
21562}
21563
21564
21565static void CheckInstanceCheckedResult(int getters, int setters,
21566 bool expects_callbacks,
21567 TryCatch* try_catch) {
21568 if (expects_callbacks) {
21569 CHECK(!try_catch->HasCaught());
21570 CHECK_EQ(getters, instance_checked_getter_count);
21571 CHECK_EQ(setters, instance_checked_setter_count);
21572 } else {
21573 CHECK(try_catch->HasCaught());
21574 CHECK_EQ(0, instance_checked_getter_count);
21575 CHECK_EQ(0, instance_checked_setter_count);
21576 }
21577 try_catch->Reset();
21578}
21579
21580
21581static void CheckInstanceCheckedAccessors(bool expects_callbacks) {
21582 instance_checked_getter_count = 0;
21583 instance_checked_setter_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021584 TryCatch try_catch(CcTest::isolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021585
21586 // Test path through generic runtime code.
21587 CompileRun("obj.foo");
21588 CheckInstanceCheckedResult(1, 0, expects_callbacks, &try_catch);
21589 CompileRun("obj.foo = 23");
21590 CheckInstanceCheckedResult(1, 1, expects_callbacks, &try_catch);
21591
21592 // Test path through generated LoadIC and StoredIC.
21593 CompileRun("function test_get(o) { o.foo; }"
21594 "test_get(obj);");
21595 CheckInstanceCheckedResult(2, 1, expects_callbacks, &try_catch);
21596 CompileRun("test_get(obj);");
21597 CheckInstanceCheckedResult(3, 1, expects_callbacks, &try_catch);
21598 CompileRun("test_get(obj);");
21599 CheckInstanceCheckedResult(4, 1, expects_callbacks, &try_catch);
21600 CompileRun("function test_set(o) { o.foo = 23; }"
21601 "test_set(obj);");
21602 CheckInstanceCheckedResult(4, 2, expects_callbacks, &try_catch);
21603 CompileRun("test_set(obj);");
21604 CheckInstanceCheckedResult(4, 3, expects_callbacks, &try_catch);
21605 CompileRun("test_set(obj);");
21606 CheckInstanceCheckedResult(4, 4, expects_callbacks, &try_catch);
21607
21608 // Test path through optimized code.
21609 CompileRun("%OptimizeFunctionOnNextCall(test_get);"
21610 "test_get(obj);");
21611 CheckInstanceCheckedResult(5, 4, expects_callbacks, &try_catch);
21612 CompileRun("%OptimizeFunctionOnNextCall(test_set);"
21613 "test_set(obj);");
21614 CheckInstanceCheckedResult(5, 5, expects_callbacks, &try_catch);
21615
21616 // Cleanup so that closures start out fresh in next check.
21617 CompileRun("%DeoptimizeFunction(test_get);"
21618 "%ClearFunctionTypeFeedback(test_get);"
21619 "%DeoptimizeFunction(test_set);"
21620 "%ClearFunctionTypeFeedback(test_set);");
21621}
21622
21623
21624THREADED_TEST(InstanceCheckOnInstanceAccessor) {
21625 v8::internal::FLAG_allow_natives_syntax = true;
21626 LocalContext context;
21627 v8::HandleScope scope(context->GetIsolate());
21628
21629 Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
21630 Local<ObjectTemplate> inst = templ->InstanceTemplate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021631 inst->SetAccessor(v8_str("foo"), InstanceCheckedGetter, InstanceCheckedSetter,
21632 Local<Value>(), v8::DEFAULT, v8::None,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021633 v8::AccessorSignature::New(context->GetIsolate(), templ));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021634 CHECK(context->Global()
21635 ->Set(context.local(), v8_str("f"),
21636 templ->GetFunction(context.local()).ToLocalChecked())
21637 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021638
21639 printf("Testing positive ...\n");
21640 CompileRun("var obj = new f();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021641 CHECK(templ->HasInstance(
21642 context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021643 CheckInstanceCheckedAccessors(true);
21644
21645 printf("Testing negative ...\n");
21646 CompileRun("var obj = {};"
21647 "obj.__proto__ = new f();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021648 CHECK(!templ->HasInstance(
21649 context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021650 CheckInstanceCheckedAccessors(false);
21651}
21652
21653
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021654static void EmptyInterceptorGetter(
21655 Local<String> name, const v8::PropertyCallbackInfo<v8::Value>& info) {}
21656
21657
21658static void EmptyInterceptorSetter(
21659 Local<String> name, Local<Value> value,
21660 const v8::PropertyCallbackInfo<v8::Value>& info) {}
21661
21662
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021663THREADED_TEST(InstanceCheckOnInstanceAccessorWithInterceptor) {
21664 v8::internal::FLAG_allow_natives_syntax = true;
21665 LocalContext context;
21666 v8::HandleScope scope(context->GetIsolate());
21667
21668 Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
21669 Local<ObjectTemplate> inst = templ->InstanceTemplate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021670 templ->InstanceTemplate()->SetNamedPropertyHandler(EmptyInterceptorGetter,
21671 EmptyInterceptorSetter);
21672 inst->SetAccessor(v8_str("foo"), InstanceCheckedGetter, InstanceCheckedSetter,
21673 Local<Value>(), v8::DEFAULT, v8::None,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021674 v8::AccessorSignature::New(context->GetIsolate(), templ));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021675 CHECK(context->Global()
21676 ->Set(context.local(), v8_str("f"),
21677 templ->GetFunction(context.local()).ToLocalChecked())
21678 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021679
21680 printf("Testing positive ...\n");
21681 CompileRun("var obj = new f();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021682 CHECK(templ->HasInstance(
21683 context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021684 CheckInstanceCheckedAccessors(true);
21685
21686 printf("Testing negative ...\n");
21687 CompileRun("var obj = {};"
21688 "obj.__proto__ = new f();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021689 CHECK(!templ->HasInstance(
21690 context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021691 CheckInstanceCheckedAccessors(false);
21692}
21693
21694
21695THREADED_TEST(InstanceCheckOnPrototypeAccessor) {
21696 v8::internal::FLAG_allow_natives_syntax = true;
21697 LocalContext context;
21698 v8::HandleScope scope(context->GetIsolate());
21699
21700 Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
21701 Local<ObjectTemplate> proto = templ->PrototypeTemplate();
21702 proto->SetAccessor(v8_str("foo"), InstanceCheckedGetter,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021703 InstanceCheckedSetter, Local<Value>(), v8::DEFAULT,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021704 v8::None,
21705 v8::AccessorSignature::New(context->GetIsolate(), templ));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021706 CHECK(context->Global()
21707 ->Set(context.local(), v8_str("f"),
21708 templ->GetFunction(context.local()).ToLocalChecked())
21709 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021710
21711 printf("Testing positive ...\n");
21712 CompileRun("var obj = new f();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021713 CHECK(templ->HasInstance(
21714 context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021715 CheckInstanceCheckedAccessors(true);
21716
21717 printf("Testing negative ...\n");
21718 CompileRun("var obj = {};"
21719 "obj.__proto__ = new f();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021720 CHECK(!templ->HasInstance(
21721 context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021722 CheckInstanceCheckedAccessors(false);
21723
21724 printf("Testing positive with modified prototype chain ...\n");
21725 CompileRun("var obj = new f();"
21726 "var pro = {};"
21727 "pro.__proto__ = obj.__proto__;"
21728 "obj.__proto__ = pro;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021729 CHECK(templ->HasInstance(
21730 context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021731 CheckInstanceCheckedAccessors(true);
21732}
21733
21734
21735TEST(TryFinallyMessage) {
21736 LocalContext context;
21737 v8::HandleScope scope(context->GetIsolate());
21738 {
21739 // Test that the original error message is not lost if there is a
21740 // recursive call into Javascript is done in the finally block, e.g. to
21741 // initialize an IC. (crbug.com/129171)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021742 TryCatch try_catch(context->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021743 const char* trigger_ic =
21744 "try { \n"
21745 " throw new Error('test'); \n"
21746 "} finally { \n"
21747 " var x = 0; \n"
21748 " x++; \n" // Trigger an IC initialization here.
21749 "} \n";
21750 CompileRun(trigger_ic);
21751 CHECK(try_catch.HasCaught());
21752 Local<Message> message = try_catch.Message();
21753 CHECK(!message.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021754 CHECK_EQ(2, message->GetLineNumber(context.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021755 }
21756
21757 {
21758 // Test that the original exception message is indeed overwritten if
21759 // a new error is thrown in the finally block.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021760 TryCatch try_catch(context->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021761 const char* throw_again =
21762 "try { \n"
21763 " throw new Error('test'); \n"
21764 "} finally { \n"
21765 " var x = 0; \n"
21766 " x++; \n"
21767 " throw new Error('again'); \n" // This is the new uncaught error.
21768 "} \n";
21769 CompileRun(throw_again);
21770 CHECK(try_catch.HasCaught());
21771 Local<Message> message = try_catch.Message();
21772 CHECK(!message.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021773 CHECK_EQ(6, message->GetLineNumber(context.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021774 }
21775}
21776
21777
21778static void Helper137002(bool do_store,
21779 bool polymorphic,
21780 bool remove_accessor,
21781 bool interceptor) {
21782 LocalContext context;
21783 Local<ObjectTemplate> templ = ObjectTemplate::New(context->GetIsolate());
21784 if (interceptor) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040021785 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(FooGetInterceptor,
21786 FooSetInterceptor));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021787 } else {
21788 templ->SetAccessor(v8_str("foo"),
21789 GetterWhichReturns42,
21790 SetterWhichSetsYOnThisTo23);
21791 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021792 CHECK(context->Global()
21793 ->Set(context.local(), v8_str("obj"),
21794 templ->NewInstance(context.local()).ToLocalChecked())
21795 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021796
21797 // Turn monomorphic on slow object with native accessor, then turn
21798 // polymorphic, finally optimize to create negative lookup and fail.
21799 CompileRun(do_store ?
21800 "function f(x) { x.foo = void 0; }" :
21801 "function f(x) { return x.foo; }");
21802 CompileRun("obj.y = void 0;");
21803 if (!interceptor) {
21804 CompileRun("%OptimizeObjectForAddingMultipleProperties(obj, 1);");
21805 }
21806 CompileRun("obj.__proto__ = null;"
21807 "f(obj); f(obj); f(obj);");
21808 if (polymorphic) {
21809 CompileRun("f({});");
21810 }
21811 CompileRun("obj.y = void 0;"
21812 "%OptimizeFunctionOnNextCall(f);");
21813 if (remove_accessor) {
21814 CompileRun("delete obj.foo;");
21815 }
21816 CompileRun("var result = f(obj);");
21817 if (do_store) {
21818 CompileRun("result = obj.y;");
21819 }
21820 if (remove_accessor && !interceptor) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021821 CHECK(context->Global()
21822 ->Get(context.local(), v8_str("result"))
21823 .ToLocalChecked()
21824 ->IsUndefined());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021825 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021826 CHECK_EQ(do_store ? 23 : 42, context->Global()
21827 ->Get(context.local(), v8_str("result"))
21828 .ToLocalChecked()
21829 ->Int32Value(context.local())
21830 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021831 }
21832}
21833
21834
21835THREADED_TEST(Regress137002a) {
21836 i::FLAG_allow_natives_syntax = true;
21837 i::FLAG_compilation_cache = false;
21838 v8::HandleScope scope(CcTest::isolate());
21839 for (int i = 0; i < 16; i++) {
21840 Helper137002(i & 8, i & 4, i & 2, i & 1);
21841 }
21842}
21843
21844
21845THREADED_TEST(Regress137002b) {
21846 i::FLAG_allow_natives_syntax = true;
21847 LocalContext context;
21848 v8::Isolate* isolate = context->GetIsolate();
21849 v8::HandleScope scope(isolate);
21850 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
21851 templ->SetAccessor(v8_str("foo"),
21852 GetterWhichReturns42,
21853 SetterWhichSetsYOnThisTo23);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021854 CHECK(context->Global()
21855 ->Set(context.local(), v8_str("obj"),
21856 templ->NewInstance(context.local()).ToLocalChecked())
21857 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021858
21859 // Turn monomorphic on slow object with native accessor, then just
21860 // delete the property and fail.
21861 CompileRun("function load(x) { return x.foo; }"
21862 "function store(x) { x.foo = void 0; }"
21863 "function keyed_load(x, key) { return x[key]; }"
21864 // Second version of function has a different source (add void 0)
21865 // so that it does not share code with the first version. This
21866 // ensures that the ICs are monomorphic.
21867 "function load2(x) { void 0; return x.foo; }"
21868 "function store2(x) { void 0; x.foo = void 0; }"
21869 "function keyed_load2(x, key) { void 0; return x[key]; }"
21870
21871 "obj.y = void 0;"
21872 "obj.__proto__ = null;"
21873 "var subobj = {};"
21874 "subobj.y = void 0;"
21875 "subobj.__proto__ = obj;"
21876 "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
21877
21878 // Make the ICs monomorphic.
21879 "load(obj); load(obj);"
21880 "load2(subobj); load2(subobj);"
21881 "store(obj); store(obj);"
21882 "store2(subobj); store2(subobj);"
21883 "keyed_load(obj, 'foo'); keyed_load(obj, 'foo');"
21884 "keyed_load2(subobj, 'foo'); keyed_load2(subobj, 'foo');"
21885
21886 // Actually test the shiny new ICs and better not crash. This
21887 // serves as a regression test for issue 142088 as well.
21888 "load(obj);"
21889 "load2(subobj);"
21890 "store(obj);"
21891 "store2(subobj);"
21892 "keyed_load(obj, 'foo');"
21893 "keyed_load2(subobj, 'foo');"
21894
21895 // Delete the accessor. It better not be called any more now.
21896 "delete obj.foo;"
21897 "obj.y = void 0;"
21898 "subobj.y = void 0;"
21899
21900 "var load_result = load(obj);"
21901 "var load_result2 = load2(subobj);"
21902 "var keyed_load_result = keyed_load(obj, 'foo');"
21903 "var keyed_load_result2 = keyed_load2(subobj, 'foo');"
21904 "store(obj);"
21905 "store2(subobj);"
21906 "var y_from_obj = obj.y;"
21907 "var y_from_subobj = subobj.y;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021908 CHECK(context->Global()
21909 ->Get(context.local(), v8_str("load_result"))
21910 .ToLocalChecked()
21911 ->IsUndefined());
21912 CHECK(context->Global()
21913 ->Get(context.local(), v8_str("load_result2"))
21914 .ToLocalChecked()
21915 ->IsUndefined());
21916 CHECK(context->Global()
21917 ->Get(context.local(), v8_str("keyed_load_result"))
21918 .ToLocalChecked()
21919 ->IsUndefined());
21920 CHECK(context->Global()
21921 ->Get(context.local(), v8_str("keyed_load_result2"))
21922 .ToLocalChecked()
21923 ->IsUndefined());
21924 CHECK(context->Global()
21925 ->Get(context.local(), v8_str("y_from_obj"))
21926 .ToLocalChecked()
21927 ->IsUndefined());
21928 CHECK(context->Global()
21929 ->Get(context.local(), v8_str("y_from_subobj"))
21930 .ToLocalChecked()
21931 ->IsUndefined());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021932}
21933
21934
21935THREADED_TEST(Regress142088) {
21936 i::FLAG_allow_natives_syntax = true;
21937 LocalContext context;
21938 v8::Isolate* isolate = context->GetIsolate();
21939 v8::HandleScope scope(isolate);
21940 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
21941 templ->SetAccessor(v8_str("foo"),
21942 GetterWhichReturns42,
21943 SetterWhichSetsYOnThisTo23);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021944 CHECK(context->Global()
21945 ->Set(context.local(), v8_str("obj"),
21946 templ->NewInstance(context.local()).ToLocalChecked())
21947 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021948
21949 CompileRun("function load(x) { return x.foo; }"
21950 "var o = Object.create(obj);"
21951 "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
21952 "load(o); load(o); load(o); load(o);");
21953}
21954
21955
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021956THREADED_TEST(Regress137496) {
21957 i::FLAG_expose_gc = true;
21958 LocalContext context;
21959 v8::HandleScope scope(context->GetIsolate());
21960
21961 // Compile a try-finally clause where the finally block causes a GC
21962 // while there still is a message pending for external reporting.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021963 TryCatch try_catch(context->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021964 try_catch.SetVerbose(true);
21965 CompileRun("try { throw new Error(); } finally { gc(); }");
21966 CHECK(try_catch.HasCaught());
21967}
21968
21969
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021970THREADED_TEST(Regress157124) {
21971 LocalContext context;
21972 v8::Isolate* isolate = context->GetIsolate();
21973 v8::HandleScope scope(isolate);
21974 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021975 Local<Object> obj = templ->NewInstance(context.local()).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021976 obj->GetIdentityHash();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021977 obj->DeletePrivate(context.local(),
21978 v8::Private::ForApi(isolate, v8_str("Bug")))
21979 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021980}
21981
21982
21983THREADED_TEST(Regress2535) {
21984 LocalContext context;
21985 v8::HandleScope scope(context->GetIsolate());
21986 Local<Value> set_value = CompileRun("new Set();");
21987 Local<Object> set_object(Local<Object>::Cast(set_value));
21988 CHECK_EQ(0, set_object->InternalFieldCount());
21989 Local<Value> map_value = CompileRun("new Map();");
21990 Local<Object> map_object(Local<Object>::Cast(map_value));
21991 CHECK_EQ(0, map_object->InternalFieldCount());
21992}
21993
21994
21995THREADED_TEST(Regress2746) {
21996 LocalContext context;
21997 v8::Isolate* isolate = context->GetIsolate();
21998 v8::HandleScope scope(isolate);
21999 Local<Object> obj = Object::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022000 Local<v8::Private> key = v8::Private::New(isolate, v8_str("key"));
22001 CHECK(
22002 obj->SetPrivate(context.local(), key, v8::Undefined(isolate)).FromJust());
22003 Local<Value> value = obj->GetPrivate(context.local(), key).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022004 CHECK(!value.IsEmpty());
22005 CHECK(value->IsUndefined());
22006}
22007
22008
22009THREADED_TEST(Regress260106) {
22010 LocalContext context;
22011 v8::Isolate* isolate = context->GetIsolate();
22012 v8::HandleScope scope(isolate);
22013 Local<FunctionTemplate> templ = FunctionTemplate::New(isolate,
22014 DummyCallHandler);
22015 CompileRun("for (var i = 0; i < 128; i++) Object.prototype[i] = 0;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022016 Local<Function> function =
22017 templ->GetFunction(context.local()).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022018 CHECK(!function.IsEmpty());
22019 CHECK(function->IsFunction());
22020}
22021
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022022THREADED_TEST(JSONParseObject) {
22023 LocalContext context;
22024 HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022025 Local<Value> obj =
Ben Murdochc5610432016-08-08 18:44:38 +010022026 v8::JSON::Parse(context.local(), v8_str("{\"x\":42}")).ToLocalChecked();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022027 Local<Object> global = context->Global();
22028 global->Set(context.local(), v8_str("obj"), obj).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022029 ExpectString("JSON.stringify(obj)", "{\"x\":42}");
22030}
22031
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022032THREADED_TEST(JSONParseNumber) {
22033 LocalContext context;
22034 HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022035 Local<Value> obj =
Ben Murdochc5610432016-08-08 18:44:38 +010022036 v8::JSON::Parse(context.local(), v8_str("42")).ToLocalChecked();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022037 Local<Object> global = context->Global();
22038 global->Set(context.local(), v8_str("obj"), obj).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022039 ExpectString("JSON.stringify(obj)", "42");
22040}
22041
Ben Murdochc5610432016-08-08 18:44:38 +010022042THREADED_TEST(JSONStringifyObject) {
22043 LocalContext context;
22044 HandleScope scope(context->GetIsolate());
22045 Local<Value> value =
22046 v8::JSON::Parse(context.local(), v8_str("{\"x\":42}")).ToLocalChecked();
22047 Local<Object> obj = value->ToObject(context.local()).ToLocalChecked();
22048 Local<Object> global = context->Global();
22049 global->Set(context.local(), v8_str("obj"), obj).FromJust();
22050 Local<String> json =
22051 v8::JSON::Stringify(context.local(), obj).ToLocalChecked();
22052 v8::String::Utf8Value utf8(json);
22053 ExpectString("JSON.stringify(obj)", *utf8);
22054}
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022055
22056#if V8_OS_POSIX && !V8_OS_NACL
22057class ThreadInterruptTest {
22058 public:
22059 ThreadInterruptTest() : sem_(0), sem_value_(0) { }
22060 ~ThreadInterruptTest() {}
22061
22062 void RunTest() {
22063 InterruptThread i_thread(this);
22064 i_thread.Start();
22065
22066 sem_.Wait();
22067 CHECK_EQ(kExpectedValue, sem_value_);
22068 }
22069
22070 private:
22071 static const int kExpectedValue = 1;
22072
22073 class InterruptThread : public v8::base::Thread {
22074 public:
22075 explicit InterruptThread(ThreadInterruptTest* test)
22076 : Thread(Options("InterruptThread")), test_(test) {}
22077
22078 virtual void Run() {
22079 struct sigaction action;
22080
22081 // Ensure that we'll enter waiting condition
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022082 v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(100));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022083
22084 // Setup signal handler
22085 memset(&action, 0, sizeof(action));
22086 action.sa_handler = SignalHandler;
22087 sigaction(SIGCHLD, &action, NULL);
22088
22089 // Send signal
22090 kill(getpid(), SIGCHLD);
22091
22092 // Ensure that if wait has returned because of error
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022093 v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(100));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022094
22095 // Set value and signal semaphore
22096 test_->sem_value_ = 1;
22097 test_->sem_.Signal();
22098 }
22099
22100 static void SignalHandler(int signal) {
22101 }
22102
22103 private:
22104 ThreadInterruptTest* test_;
22105 };
22106
22107 v8::base::Semaphore sem_;
22108 volatile int sem_value_;
22109};
22110
22111
22112THREADED_TEST(SemaphoreInterruption) {
22113 ThreadInterruptTest().RunTest();
22114}
22115
22116
22117#endif // V8_OS_POSIX
22118
22119
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022120void UnreachableCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
22121 CHECK(false);
22122}
22123
22124
22125TEST(JSONStringifyAccessCheck) {
22126 v8::V8::Initialize();
22127 v8::Isolate* isolate = CcTest::isolate();
22128 v8::HandleScope scope(isolate);
22129
22130 // Create an ObjectTemplate for global objects and install access
22131 // check callbacks that will block access.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022132 v8::Local<v8::ObjectTemplate> global_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022133 v8::ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022134 global_template->SetAccessCheckCallback(AccessAlwaysBlocked);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022135
22136 // Create a context and set an x property on it's global object.
22137 LocalContext context0(NULL, global_template);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022138 v8::Local<v8::Object> global0 = context0->Global();
22139 global0->Set(context0.local(), v8_str("x"), v8_num(42)).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022140 ExpectString("JSON.stringify(this)", "{\"x\":42}");
22141
22142 for (int i = 0; i < 2; i++) {
22143 if (i == 1) {
22144 // Install a toJSON function on the second run.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022145 v8::Local<v8::FunctionTemplate> toJSON =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022146 v8::FunctionTemplate::New(isolate, UnreachableCallback);
22147
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022148 global0->Set(context0.local(), v8_str("toJSON"),
22149 toJSON->GetFunction(context0.local()).ToLocalChecked())
22150 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022151 }
22152 // Create a context with a different security token so that the
22153 // failed access check callback will be called on each access.
22154 LocalContext context1(NULL, global_template);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022155 CHECK(context1->Global()
22156 ->Set(context1.local(), v8_str("other"), global0)
22157 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022158
22159 CHECK(CompileRun("JSON.stringify(other)").IsEmpty());
22160 CHECK(CompileRun("JSON.stringify({ 'a' : other, 'b' : ['c'] })").IsEmpty());
22161 CHECK(CompileRun("JSON.stringify([other, 'b', 'c'])").IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022162 }
22163}
22164
22165
22166bool access_check_fail_thrown = false;
22167bool catch_callback_called = false;
22168
22169
22170// Failed access check callback that performs a GC on each invocation.
22171void FailedAccessCheckThrows(Local<v8::Object> target,
22172 v8::AccessType type,
22173 Local<v8::Value> data) {
22174 access_check_fail_thrown = true;
22175 i::PrintF("Access check failed. Error thrown.\n");
22176 CcTest::isolate()->ThrowException(
22177 v8::Exception::Error(v8_str("cross context")));
22178}
22179
22180
22181void CatcherCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
22182 for (int i = 0; i < args.Length(); i++) {
22183 i::PrintF("%s\n", *String::Utf8Value(args[i]));
22184 }
22185 catch_callback_called = true;
22186}
22187
22188
22189void HasOwnPropertyCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022190 v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
22191 CHECK(
22192 args[0]
22193 ->ToObject(context)
22194 .ToLocalChecked()
22195 ->HasOwnProperty(context, args[1]->ToString(context).ToLocalChecked())
22196 .IsNothing());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022197}
22198
22199
22200void CheckCorrectThrow(const char* script) {
22201 // Test that the script, when wrapped into a try-catch, triggers the catch
22202 // clause due to failed access check throwing an exception.
22203 // The subsequent try-catch should run without any exception.
22204 access_check_fail_thrown = false;
22205 catch_callback_called = false;
22206 i::ScopedVector<char> source(1024);
22207 i::SNPrintF(source, "try { %s; } catch (e) { catcher(e); }", script);
22208 CompileRun(source.start());
22209 CHECK(access_check_fail_thrown);
22210 CHECK(catch_callback_called);
22211
22212 access_check_fail_thrown = false;
22213 catch_callback_called = false;
22214 CompileRun("try { [1, 2, 3].sort(); } catch (e) { catcher(e) };");
22215 CHECK(!access_check_fail_thrown);
22216 CHECK(!catch_callback_called);
22217}
22218
22219
22220TEST(AccessCheckThrows) {
22221 i::FLAG_allow_natives_syntax = true;
22222 v8::V8::Initialize();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022223 v8::Isolate* isolate = CcTest::isolate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022224 isolate->SetFailedAccessCheckCallbackFunction(&FailedAccessCheckThrows);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022225 v8::HandleScope scope(isolate);
22226
22227 // Create an ObjectTemplate for global objects and install access
22228 // check callbacks that will block access.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022229 v8::Local<v8::ObjectTemplate> global_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022230 v8::ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022231 global_template->SetAccessCheckCallback(AccessAlwaysBlocked);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022232
22233 // Create a context and set an x property on it's global object.
22234 LocalContext context0(NULL, global_template);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022235 v8::Local<v8::Object> global0 = context0->Global();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022236
22237 // Create a context with a different security token so that the
22238 // failed access check callback will be called on each access.
22239 LocalContext context1(NULL, global_template);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022240 CHECK(context1->Global()
22241 ->Set(context1.local(), v8_str("other"), global0)
22242 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022243
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022244 v8::Local<v8::FunctionTemplate> catcher_fun =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022245 v8::FunctionTemplate::New(isolate, CatcherCallback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022246 CHECK(context1->Global()
22247 ->Set(context1.local(), v8_str("catcher"),
22248 catcher_fun->GetFunction(context1.local()).ToLocalChecked())
22249 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022250
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022251 v8::Local<v8::FunctionTemplate> has_own_property_fun =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022252 v8::FunctionTemplate::New(isolate, HasOwnPropertyCallback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022253 CHECK(context1->Global()
22254 ->Set(context1.local(), v8_str("has_own_property"),
22255 has_own_property_fun->GetFunction(context1.local())
22256 .ToLocalChecked())
22257 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022258
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022259 {
22260 v8::TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022261 access_check_fail_thrown = false;
22262 CompileRun("other.x;");
22263 CHECK(access_check_fail_thrown);
22264 CHECK(try_catch.HasCaught());
22265 }
22266
22267 CheckCorrectThrow("other.x");
22268 CheckCorrectThrow("other[1]");
22269 CheckCorrectThrow("JSON.stringify(other)");
22270 CheckCorrectThrow("has_own_property(other, 'x')");
22271 CheckCorrectThrow("%GetProperty(other, 'x')");
22272 CheckCorrectThrow("%SetProperty(other, 'x', 'foo', 0)");
22273 CheckCorrectThrow("%AddNamedProperty(other, 'x', 'foo', 1)");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022274 CheckCorrectThrow("%DeleteProperty_Sloppy(other, 'x')");
22275 CheckCorrectThrow("%DeleteProperty_Strict(other, 'x')");
22276 CheckCorrectThrow("%DeleteProperty_Sloppy(other, '1')");
22277 CheckCorrectThrow("%DeleteProperty_Strict(other, '1')");
Ben Murdochda12d292016-06-02 14:46:10 +010022278 CheckCorrectThrow("Object.prototype.hasOwnProperty.call(other, 'x')");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022279 CheckCorrectThrow("%HasProperty('x', other)");
22280 CheckCorrectThrow("%PropertyIsEnumerable(other, 'x')");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022281 // PROPERTY_ATTRIBUTES_NONE = 0
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022282 CheckCorrectThrow("%DefineAccessorPropertyUnchecked("
22283 "other, 'x', null, null, 1)");
22284
22285 // Reset the failed access check callback so it does not influence
22286 // the other tests.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022287 isolate->SetFailedAccessCheckCallbackFunction(NULL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022288}
22289
22290
22291class RequestInterruptTestBase {
22292 public:
22293 RequestInterruptTestBase()
22294 : env_(),
22295 isolate_(env_->GetIsolate()),
22296 sem_(0),
22297 warmup_(20000),
22298 should_continue_(true) {
22299 }
22300
22301 virtual ~RequestInterruptTestBase() { }
22302
22303 virtual void StartInterruptThread() = 0;
22304
22305 virtual void TestBody() = 0;
22306
22307 void RunTest() {
22308 StartInterruptThread();
22309
22310 v8::HandleScope handle_scope(isolate_);
22311
22312 TestBody();
22313
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022314 // Verify we arrived here because interruptor was called
22315 // not due to a bug causing us to exit the loop too early.
22316 CHECK(!should_continue());
22317 }
22318
22319 void WakeUpInterruptor() {
22320 sem_.Signal();
22321 }
22322
22323 bool should_continue() const { return should_continue_; }
22324
22325 bool ShouldContinue() {
22326 if (warmup_ > 0) {
22327 if (--warmup_ == 0) {
22328 WakeUpInterruptor();
22329 }
22330 }
22331
22332 return should_continue_;
22333 }
22334
22335 static void ShouldContinueCallback(
22336 const v8::FunctionCallbackInfo<Value>& info) {
22337 RequestInterruptTestBase* test =
22338 reinterpret_cast<RequestInterruptTestBase*>(
22339 info.Data().As<v8::External>()->Value());
22340 info.GetReturnValue().Set(test->ShouldContinue());
22341 }
22342
22343 LocalContext env_;
22344 v8::Isolate* isolate_;
22345 v8::base::Semaphore sem_;
22346 int warmup_;
22347 bool should_continue_;
22348};
22349
22350
22351class RequestInterruptTestBaseWithSimpleInterrupt
22352 : public RequestInterruptTestBase {
22353 public:
22354 RequestInterruptTestBaseWithSimpleInterrupt() : i_thread(this) { }
22355
22356 virtual void StartInterruptThread() {
22357 i_thread.Start();
22358 }
22359
22360 private:
22361 class InterruptThread : public v8::base::Thread {
22362 public:
22363 explicit InterruptThread(RequestInterruptTestBase* test)
22364 : Thread(Options("RequestInterruptTest")), test_(test) {}
22365
22366 virtual void Run() {
22367 test_->sem_.Wait();
22368 test_->isolate_->RequestInterrupt(&OnInterrupt, test_);
22369 }
22370
22371 static void OnInterrupt(v8::Isolate* isolate, void* data) {
22372 reinterpret_cast<RequestInterruptTestBase*>(data)->
22373 should_continue_ = false;
22374 }
22375
22376 private:
22377 RequestInterruptTestBase* test_;
22378 };
22379
22380 InterruptThread i_thread;
22381};
22382
22383
22384class RequestInterruptTestWithFunctionCall
22385 : public RequestInterruptTestBaseWithSimpleInterrupt {
22386 public:
22387 virtual void TestBody() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022388 Local<Function> func = Function::New(env_.local(), ShouldContinueCallback,
22389 v8::External::New(isolate_, this))
22390 .ToLocalChecked();
22391 CHECK(env_->Global()
22392 ->Set(env_.local(), v8_str("ShouldContinue"), func)
22393 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022394
22395 CompileRun("while (ShouldContinue()) { }");
22396 }
22397};
22398
22399
22400class RequestInterruptTestWithMethodCall
22401 : public RequestInterruptTestBaseWithSimpleInterrupt {
22402 public:
22403 virtual void TestBody() {
22404 v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
22405 v8::Local<v8::Template> proto = t->PrototypeTemplate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022406 proto->Set(v8_str("shouldContinue"),
Ben Murdoch097c5b22016-05-18 11:27:45 +010022407 FunctionTemplate::New(isolate_, ShouldContinueCallback,
22408 v8::External::New(isolate_, this)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022409 CHECK(env_->Global()
22410 ->Set(env_.local(), v8_str("Klass"),
22411 t->GetFunction(env_.local()).ToLocalChecked())
22412 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022413
22414 CompileRun("var obj = new Klass; while (obj.shouldContinue()) { }");
22415 }
22416};
22417
22418
22419class RequestInterruptTestWithAccessor
22420 : public RequestInterruptTestBaseWithSimpleInterrupt {
22421 public:
22422 virtual void TestBody() {
22423 v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
22424 v8::Local<v8::Template> proto = t->PrototypeTemplate();
22425 proto->SetAccessorProperty(v8_str("shouldContinue"), FunctionTemplate::New(
22426 isolate_, ShouldContinueCallback, v8::External::New(isolate_, this)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022427 CHECK(env_->Global()
22428 ->Set(env_.local(), v8_str("Klass"),
22429 t->GetFunction(env_.local()).ToLocalChecked())
22430 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022431
22432 CompileRun("var obj = new Klass; while (obj.shouldContinue) { }");
22433 }
22434};
22435
22436
22437class RequestInterruptTestWithNativeAccessor
22438 : public RequestInterruptTestBaseWithSimpleInterrupt {
22439 public:
22440 virtual void TestBody() {
22441 v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
22442 t->InstanceTemplate()->SetNativeDataProperty(
22443 v8_str("shouldContinue"),
22444 &ShouldContinueNativeGetter,
22445 NULL,
22446 v8::External::New(isolate_, this));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022447 CHECK(env_->Global()
22448 ->Set(env_.local(), v8_str("Klass"),
22449 t->GetFunction(env_.local()).ToLocalChecked())
22450 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022451
22452 CompileRun("var obj = new Klass; while (obj.shouldContinue) { }");
22453 }
22454
22455 private:
22456 static void ShouldContinueNativeGetter(
22457 Local<String> property,
22458 const v8::PropertyCallbackInfo<v8::Value>& info) {
22459 RequestInterruptTestBase* test =
22460 reinterpret_cast<RequestInterruptTestBase*>(
22461 info.Data().As<v8::External>()->Value());
22462 info.GetReturnValue().Set(test->ShouldContinue());
22463 }
22464};
22465
22466
22467class RequestInterruptTestWithMethodCallAndInterceptor
22468 : public RequestInterruptTestBaseWithSimpleInterrupt {
22469 public:
22470 virtual void TestBody() {
22471 v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
22472 v8::Local<v8::Template> proto = t->PrototypeTemplate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022473 proto->Set(v8_str("shouldContinue"),
Ben Murdoch097c5b22016-05-18 11:27:45 +010022474 FunctionTemplate::New(isolate_, ShouldContinueCallback,
22475 v8::External::New(isolate_, this)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022476 v8::Local<v8::ObjectTemplate> instance_template = t->InstanceTemplate();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040022477 instance_template->SetHandler(
22478 v8::NamedPropertyHandlerConfiguration(EmptyInterceptor));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022479
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022480 CHECK(env_->Global()
22481 ->Set(env_.local(), v8_str("Klass"),
22482 t->GetFunction(env_.local()).ToLocalChecked())
22483 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022484
22485 CompileRun("var obj = new Klass; while (obj.shouldContinue()) { }");
22486 }
22487
22488 private:
22489 static void EmptyInterceptor(
Emily Bernierd0a1eb72015-03-24 16:35:39 -040022490 Local<Name> property, const v8::PropertyCallbackInfo<v8::Value>& info) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022491};
22492
22493
22494class RequestInterruptTestWithMathAbs
22495 : public RequestInterruptTestBaseWithSimpleInterrupt {
22496 public:
22497 virtual void TestBody() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022498 env_->Global()
22499 ->Set(env_.local(), v8_str("WakeUpInterruptor"),
22500 Function::New(env_.local(), WakeUpInterruptorCallback,
22501 v8::External::New(isolate_, this))
22502 .ToLocalChecked())
22503 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022504
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022505 env_->Global()
22506 ->Set(env_.local(), v8_str("ShouldContinue"),
22507 Function::New(env_.local(), ShouldContinueCallback,
22508 v8::External::New(isolate_, this))
22509 .ToLocalChecked())
22510 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022511
22512 i::FLAG_allow_natives_syntax = true;
22513 CompileRun("function loopish(o) {"
22514 " var pre = 10;"
22515 " while (o.abs(1) > 0) {"
22516 " if (o.abs(1) >= 0 && !ShouldContinue()) break;"
22517 " if (pre > 0) {"
22518 " if (--pre === 0) WakeUpInterruptor(o === Math);"
22519 " }"
22520 " }"
22521 "}"
22522 "var i = 50;"
22523 "var obj = {abs: function () { return i-- }, x: null};"
22524 "delete obj.x;"
22525 "loopish(obj);"
22526 "%OptimizeFunctionOnNextCall(loopish);"
22527 "loopish(Math);");
22528
22529 i::FLAG_allow_natives_syntax = false;
22530 }
22531
22532 private:
22533 static void WakeUpInterruptorCallback(
22534 const v8::FunctionCallbackInfo<Value>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022535 if (!info[0]
22536 ->BooleanValue(info.GetIsolate()->GetCurrentContext())
22537 .FromJust()) {
22538 return;
22539 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022540
22541 RequestInterruptTestBase* test =
22542 reinterpret_cast<RequestInterruptTestBase*>(
22543 info.Data().As<v8::External>()->Value());
22544 test->WakeUpInterruptor();
22545 }
22546
22547 static void ShouldContinueCallback(
22548 const v8::FunctionCallbackInfo<Value>& info) {
22549 RequestInterruptTestBase* test =
22550 reinterpret_cast<RequestInterruptTestBase*>(
22551 info.Data().As<v8::External>()->Value());
22552 info.GetReturnValue().Set(test->should_continue());
22553 }
22554};
22555
22556
22557TEST(RequestInterruptTestWithFunctionCall) {
22558 RequestInterruptTestWithFunctionCall().RunTest();
22559}
22560
22561
22562TEST(RequestInterruptTestWithMethodCall) {
22563 RequestInterruptTestWithMethodCall().RunTest();
22564}
22565
22566
22567TEST(RequestInterruptTestWithAccessor) {
22568 RequestInterruptTestWithAccessor().RunTest();
22569}
22570
22571
22572TEST(RequestInterruptTestWithNativeAccessor) {
22573 RequestInterruptTestWithNativeAccessor().RunTest();
22574}
22575
22576
22577TEST(RequestInterruptTestWithMethodCallAndInterceptor) {
22578 RequestInterruptTestWithMethodCallAndInterceptor().RunTest();
22579}
22580
22581
22582TEST(RequestInterruptTestWithMathAbs) {
22583 RequestInterruptTestWithMathAbs().RunTest();
22584}
22585
22586
Emily Bernierd0a1eb72015-03-24 16:35:39 -040022587class RequestMultipleInterrupts : public RequestInterruptTestBase {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022588 public:
Emily Bernierd0a1eb72015-03-24 16:35:39 -040022589 RequestMultipleInterrupts() : i_thread(this), counter_(0) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022590
22591 virtual void StartInterruptThread() {
22592 i_thread.Start();
22593 }
22594
22595 virtual void TestBody() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022596 Local<Function> func = Function::New(env_.local(), ShouldContinueCallback,
22597 v8::External::New(isolate_, this))
22598 .ToLocalChecked();
22599 CHECK(env_->Global()
22600 ->Set(env_.local(), v8_str("ShouldContinue"), func)
22601 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022602
22603 CompileRun("while (ShouldContinue()) { }");
22604 }
22605
22606 private:
22607 class InterruptThread : public v8::base::Thread {
22608 public:
Emily Bernierd0a1eb72015-03-24 16:35:39 -040022609 enum { NUM_INTERRUPTS = 10 };
22610 explicit InterruptThread(RequestMultipleInterrupts* test)
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022611 : Thread(Options("RequestInterruptTest")), test_(test) {}
22612
22613 virtual void Run() {
22614 test_->sem_.Wait();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040022615 for (int i = 0; i < NUM_INTERRUPTS; i++) {
22616 test_->isolate_->RequestInterrupt(&OnInterrupt, test_);
22617 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022618 }
22619
22620 static void OnInterrupt(v8::Isolate* isolate, void* data) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040022621 RequestMultipleInterrupts* test =
22622 reinterpret_cast<RequestMultipleInterrupts*>(data);
22623 test->should_continue_ = ++test->counter_ < NUM_INTERRUPTS;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022624 }
22625
22626 private:
Emily Bernierd0a1eb72015-03-24 16:35:39 -040022627 RequestMultipleInterrupts* test_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022628 };
22629
22630 InterruptThread i_thread;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040022631 int counter_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022632};
22633
22634
Emily Bernierd0a1eb72015-03-24 16:35:39 -040022635TEST(RequestMultipleInterrupts) { RequestMultipleInterrupts().RunTest(); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022636
22637
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022638static bool interrupt_was_called = false;
22639
22640
22641void SmallScriptsInterruptCallback(v8::Isolate* isolate, void* data) {
22642 interrupt_was_called = true;
22643}
22644
22645
22646TEST(RequestInterruptSmallScripts) {
22647 LocalContext env;
22648 v8::Isolate* isolate = CcTest::isolate();
22649 v8::HandleScope scope(isolate);
22650
22651 interrupt_was_called = false;
22652 isolate->RequestInterrupt(&SmallScriptsInterruptCallback, NULL);
22653 CompileRun("(function(x){return x;})(1);");
22654 CHECK(interrupt_was_called);
22655}
22656
22657
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022658static Local<Value> function_new_expected_env;
22659static void FunctionNewCallback(const v8::FunctionCallbackInfo<Value>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022660 CHECK(
22661 function_new_expected_env->Equals(info.GetIsolate()->GetCurrentContext(),
22662 info.Data())
22663 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022664 info.GetReturnValue().Set(17);
22665}
22666
22667
22668THREADED_TEST(FunctionNew) {
22669 LocalContext env;
22670 v8::Isolate* isolate = env->GetIsolate();
22671 v8::HandleScope scope(isolate);
22672 Local<Object> data = v8::Object::New(isolate);
22673 function_new_expected_env = data;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022674 Local<Function> func =
22675 Function::New(env.local(), FunctionNewCallback, data).ToLocalChecked();
22676 CHECK(env->Global()->Set(env.local(), v8_str("func"), func).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022677 Local<Value> result = CompileRun("func();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022678 CHECK(v8::Integer::New(isolate, 17)->Equals(env.local(), result).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022679 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022680 // Verify function not cached
22681 auto serial_number = handle(
22682 i::Smi::cast(i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(*func))
22683 ->shared()
22684 ->get_api_func_data()
22685 ->serial_number()),
22686 i_isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +010022687 auto cache = i_isolate->template_instantiations_cache();
Ben Murdochda12d292016-06-02 14:46:10 +010022688 CHECK(cache->FindEntry(static_cast<uint32_t>(serial_number->value())) ==
22689 i::UnseededNumberDictionary::kNotFound);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022690 // Verify that each Function::New creates a new function instance
22691 Local<Object> data2 = v8::Object::New(isolate);
22692 function_new_expected_env = data2;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022693 Local<Function> func2 =
22694 Function::New(env.local(), FunctionNewCallback, data2).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022695 CHECK(!func2->IsNull());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022696 CHECK(!func->Equals(env.local(), func2).FromJust());
22697 CHECK(env->Global()->Set(env.local(), v8_str("func2"), func2).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022698 Local<Value> result2 = CompileRun("func2();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022699 CHECK(v8::Integer::New(isolate, 17)->Equals(env.local(), result2).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022700}
22701
22702
22703TEST(EscapeableHandleScope) {
22704 HandleScope outer_scope(CcTest::isolate());
22705 LocalContext context;
22706 const int runs = 10;
22707 Local<String> values[runs];
22708 for (int i = 0; i < runs; i++) {
22709 v8::EscapableHandleScope inner_scope(CcTest::isolate());
22710 Local<String> value;
22711 if (i != 0) value = v8_str("escape value");
22712 values[i] = inner_scope.Escape(value);
22713 }
22714 for (int i = 0; i < runs; i++) {
22715 Local<String> expected;
22716 if (i != 0) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022717 CHECK(v8_str("escape value")
22718 ->Equals(context.local(), values[i])
22719 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022720 } else {
22721 CHECK(values[i].IsEmpty());
22722 }
22723 }
22724}
22725
22726
22727static void SetterWhichExpectsThisAndHolderToDiffer(
22728 Local<String>, Local<Value>, const v8::PropertyCallbackInfo<void>& info) {
22729 CHECK(info.Holder() != info.This());
22730}
22731
22732
22733TEST(Regress239669) {
22734 LocalContext context;
22735 v8::Isolate* isolate = context->GetIsolate();
22736 v8::HandleScope scope(isolate);
22737 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
22738 templ->SetAccessor(v8_str("x"), 0, SetterWhichExpectsThisAndHolderToDiffer);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022739 CHECK(context->Global()
22740 ->Set(context.local(), v8_str("P"),
22741 templ->NewInstance(context.local()).ToLocalChecked())
22742 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022743 CompileRun(
22744 "function C1() {"
22745 " this.x = 23;"
22746 "};"
22747 "C1.prototype = P;"
22748 "for (var i = 0; i < 4; i++ ) {"
22749 " new C1();"
22750 "}");
22751}
22752
22753
22754class ApiCallOptimizationChecker {
22755 private:
22756 static Local<Object> data;
22757 static Local<Object> receiver;
22758 static Local<Object> holder;
22759 static Local<Object> callee;
22760 static int count;
22761
22762 static void OptimizationCallback(
22763 const v8::FunctionCallbackInfo<v8::Value>& info) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022764 CHECK(data == info.Data());
22765 CHECK(receiver == info.This());
22766 if (info.Length() == 1) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022767 CHECK(v8_num(1)
22768 ->Equals(info.GetIsolate()->GetCurrentContext(), info[0])
22769 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022770 }
22771 CHECK(holder == info.Holder());
22772 count++;
22773 info.GetReturnValue().Set(v8_str("returned"));
22774 }
22775
22776 public:
22777 enum SignatureType {
22778 kNoSignature,
22779 kSignatureOnReceiver,
22780 kSignatureOnPrototype
22781 };
22782
22783 void RunAll() {
22784 SignatureType signature_types[] =
22785 {kNoSignature, kSignatureOnReceiver, kSignatureOnPrototype};
22786 for (unsigned i = 0; i < arraysize(signature_types); i++) {
22787 SignatureType signature_type = signature_types[i];
22788 for (int j = 0; j < 2; j++) {
22789 bool global = j == 0;
22790 int key = signature_type +
22791 arraysize(signature_types) * (global ? 1 : 0);
22792 Run(signature_type, global, key);
22793 }
22794 }
22795 }
22796
22797 void Run(SignatureType signature_type, bool global, int key) {
22798 v8::Isolate* isolate = CcTest::isolate();
22799 v8::HandleScope scope(isolate);
22800 // Build a template for signature checks.
22801 Local<v8::ObjectTemplate> signature_template;
22802 Local<v8::Signature> signature;
22803 {
22804 Local<v8::FunctionTemplate> parent_template =
22805 FunctionTemplate::New(isolate);
22806 parent_template->SetHiddenPrototype(true);
22807 Local<v8::FunctionTemplate> function_template
22808 = FunctionTemplate::New(isolate);
22809 function_template->Inherit(parent_template);
22810 switch (signature_type) {
22811 case kNoSignature:
22812 break;
22813 case kSignatureOnReceiver:
22814 signature = v8::Signature::New(isolate, function_template);
22815 break;
22816 case kSignatureOnPrototype:
22817 signature = v8::Signature::New(isolate, parent_template);
22818 break;
22819 }
22820 signature_template = function_template->InstanceTemplate();
22821 }
22822 // Global object must pass checks.
22823 Local<v8::Context> context =
22824 v8::Context::New(isolate, NULL, signature_template);
22825 v8::Context::Scope context_scope(context);
22826 // Install regular object that can pass signature checks.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022827 Local<Object> function_receiver =
22828 signature_template->NewInstance(context).ToLocalChecked();
22829 CHECK(context->Global()
22830 ->Set(context, v8_str("function_receiver"), function_receiver)
22831 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022832 // Get the holder objects.
22833 Local<Object> inner_global =
22834 Local<Object>::Cast(context->Global()->GetPrototype());
22835 // Install functions on hidden prototype object if there is one.
22836 data = Object::New(isolate);
22837 Local<FunctionTemplate> function_template = FunctionTemplate::New(
22838 isolate, OptimizationCallback, data, signature);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022839 Local<Function> function =
22840 function_template->GetFunction(context).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022841 Local<Object> global_holder = inner_global;
22842 Local<Object> function_holder = function_receiver;
22843 if (signature_type == kSignatureOnPrototype) {
22844 function_holder = Local<Object>::Cast(function_holder->GetPrototype());
22845 global_holder = Local<Object>::Cast(global_holder->GetPrototype());
22846 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022847 global_holder->Set(context, v8_str("g_f"), function).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022848 global_holder->SetAccessorProperty(v8_str("g_acc"), function, function);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022849 function_holder->Set(context, v8_str("f"), function).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022850 function_holder->SetAccessorProperty(v8_str("acc"), function, function);
22851 // Initialize expected values.
22852 callee = function;
22853 count = 0;
22854 if (global) {
22855 receiver = context->Global();
22856 holder = inner_global;
22857 } else {
22858 holder = function_receiver;
22859 // If not using a signature, add something else to the prototype chain
22860 // to test the case that holder != receiver
22861 if (signature_type == kNoSignature) {
22862 receiver = Local<Object>::Cast(CompileRun(
22863 "var receiver_subclass = {};\n"
22864 "receiver_subclass.__proto__ = function_receiver;\n"
22865 "receiver_subclass"));
22866 } else {
22867 receiver = Local<Object>::Cast(CompileRun(
22868 "var receiver_subclass = function_receiver;\n"
22869 "receiver_subclass"));
22870 }
22871 }
22872 // With no signature, the holder is not set.
22873 if (signature_type == kNoSignature) holder = receiver;
22874 // build wrap_function
22875 i::ScopedVector<char> wrap_function(200);
22876 if (global) {
22877 i::SNPrintF(
22878 wrap_function,
22879 "function wrap_f_%d() { var f = g_f; return f(); }\n"
22880 "function wrap_get_%d() { return this.g_acc; }\n"
22881 "function wrap_set_%d() { return this.g_acc = 1; }\n",
22882 key, key, key);
22883 } else {
22884 i::SNPrintF(
22885 wrap_function,
22886 "function wrap_f_%d() { return receiver_subclass.f(); }\n"
22887 "function wrap_get_%d() { return receiver_subclass.acc; }\n"
22888 "function wrap_set_%d() { return receiver_subclass.acc = 1; }\n",
22889 key, key, key);
22890 }
22891 // build source string
22892 i::ScopedVector<char> source(1000);
22893 i::SNPrintF(
22894 source,
22895 "%s\n" // wrap functions
22896 "function wrap_f() { return wrap_f_%d(); }\n"
22897 "function wrap_get() { return wrap_get_%d(); }\n"
22898 "function wrap_set() { return wrap_set_%d(); }\n"
22899 "check = function(returned) {\n"
22900 " if (returned !== 'returned') { throw returned; }\n"
22901 "}\n"
22902 "\n"
22903 "check(wrap_f());\n"
22904 "check(wrap_f());\n"
22905 "%%OptimizeFunctionOnNextCall(wrap_f_%d);\n"
22906 "check(wrap_f());\n"
22907 "\n"
22908 "check(wrap_get());\n"
22909 "check(wrap_get());\n"
22910 "%%OptimizeFunctionOnNextCall(wrap_get_%d);\n"
22911 "check(wrap_get());\n"
22912 "\n"
22913 "check = function(returned) {\n"
22914 " if (returned !== 1) { throw returned; }\n"
22915 "}\n"
22916 "check(wrap_set());\n"
22917 "check(wrap_set());\n"
22918 "%%OptimizeFunctionOnNextCall(wrap_set_%d);\n"
22919 "check(wrap_set());\n",
22920 wrap_function.start(), key, key, key, key, key, key);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022921 v8::TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022922 CompileRun(source.start());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022923 CHECK(!try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022924 CHECK_EQ(9, count);
22925 }
22926};
22927
22928
22929Local<Object> ApiCallOptimizationChecker::data;
22930Local<Object> ApiCallOptimizationChecker::receiver;
22931Local<Object> ApiCallOptimizationChecker::holder;
22932Local<Object> ApiCallOptimizationChecker::callee;
22933int ApiCallOptimizationChecker::count = 0;
22934
22935
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022936TEST(FunctionCallOptimization) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022937 i::FLAG_allow_natives_syntax = true;
22938 ApiCallOptimizationChecker checker;
22939 checker.RunAll();
22940}
22941
22942
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022943TEST(FunctionCallOptimizationMultipleArgs) {
22944 i::FLAG_allow_natives_syntax = true;
22945 LocalContext context;
22946 v8::Isolate* isolate = context->GetIsolate();
22947 v8::HandleScope scope(isolate);
22948 Local<Object> global = context->Global();
22949 Local<v8::Function> function =
22950 Function::New(context.local(), Returns42).ToLocalChecked();
22951 global->Set(context.local(), v8_str("x"), function).FromJust();
22952 CompileRun(
22953 "function x_wrap() {\n"
22954 " for (var i = 0; i < 5; i++) {\n"
22955 " x(1,2,3);\n"
22956 " }\n"
22957 "}\n"
22958 "x_wrap();\n"
22959 "%OptimizeFunctionOnNextCall(x_wrap);"
22960 "x_wrap();\n");
22961}
22962
22963
22964static void ReturnsSymbolCallback(
22965 const v8::FunctionCallbackInfo<v8::Value>& info) {
22966 info.GetReturnValue().Set(v8::Symbol::New(info.GetIsolate()));
22967}
22968
22969
22970TEST(ApiCallbackCanReturnSymbols) {
22971 i::FLAG_allow_natives_syntax = true;
22972 LocalContext context;
22973 v8::Isolate* isolate = context->GetIsolate();
22974 v8::HandleScope scope(isolate);
22975 Local<Object> global = context->Global();
22976 Local<v8::Function> function =
22977 Function::New(context.local(), ReturnsSymbolCallback).ToLocalChecked();
22978 global->Set(context.local(), v8_str("x"), function).FromJust();
22979 CompileRun(
22980 "function x_wrap() {\n"
22981 " for (var i = 0; i < 5; i++) {\n"
22982 " x();\n"
22983 " }\n"
22984 "}\n"
22985 "x_wrap();\n"
22986 "%OptimizeFunctionOnNextCall(x_wrap);"
22987 "x_wrap();\n");
22988}
22989
22990
22991TEST(EmptyApiCallback) {
22992 LocalContext context;
22993 auto isolate = context->GetIsolate();
22994 v8::HandleScope scope(isolate);
22995 auto global = context->Global();
22996 auto function = FunctionTemplate::New(isolate)
22997 ->GetFunction(context.local())
22998 .ToLocalChecked();
22999 global->Set(context.local(), v8_str("x"), function).FromJust();
23000
23001 auto result = CompileRun("x()");
23002 CHECK(v8::Utils::OpenHandle(*result)->IsJSGlobalProxy());
23003
23004 result = CompileRun("x(1,2,3)");
23005 CHECK(v8::Utils::OpenHandle(*result)->IsJSGlobalProxy());
23006
23007 result = CompileRun("x.call(undefined)");
23008 CHECK(v8::Utils::OpenHandle(*result)->IsJSGlobalProxy());
23009
23010 result = CompileRun("x.call(null)");
23011 CHECK(v8::Utils::OpenHandle(*result)->IsJSGlobalProxy());
23012
23013 result = CompileRun("7 + x.call(3) + 11");
23014 CHECK(result->IsInt32());
23015 CHECK_EQ(21, result->Int32Value(context.local()).FromJust());
23016
23017 result = CompileRun("7 + x.call(3, 101, 102, 103, 104) + 11");
23018 CHECK(result->IsInt32());
23019 CHECK_EQ(21, result->Int32Value(context.local()).FromJust());
23020
23021 result = CompileRun("var y = []; x.call(y)");
23022 CHECK(result->IsArray());
23023
23024 result = CompileRun("x.call(y, 1, 2, 3, 4)");
23025 CHECK(result->IsArray());
23026}
23027
23028
23029TEST(SimpleSignatureCheck) {
23030 LocalContext context;
23031 auto isolate = context->GetIsolate();
23032 v8::HandleScope scope(isolate);
23033 auto global = context->Global();
23034 auto sig_obj = FunctionTemplate::New(isolate);
23035 auto sig = v8::Signature::New(isolate, sig_obj);
23036 auto x = FunctionTemplate::New(isolate, Returns42, Local<Value>(), sig);
23037 global->Set(context.local(), v8_str("sig_obj"),
23038 sig_obj->GetFunction(context.local()).ToLocalChecked())
23039 .FromJust();
23040 global->Set(context.local(), v8_str("x"),
23041 x->GetFunction(context.local()).ToLocalChecked())
23042 .FromJust();
23043 CompileRun("var s = new sig_obj();");
23044 {
23045 TryCatch try_catch(isolate);
23046 CompileRun("x()");
23047 CHECK(try_catch.HasCaught());
23048 }
23049 {
23050 TryCatch try_catch(isolate);
23051 CompileRun("x.call(1)");
23052 CHECK(try_catch.HasCaught());
23053 }
23054 {
23055 TryCatch try_catch(isolate);
23056 auto result = CompileRun("s.x = x; s.x()");
23057 CHECK(!try_catch.HasCaught());
23058 CHECK_EQ(42, result->Int32Value(context.local()).FromJust());
23059 }
23060 {
23061 TryCatch try_catch(isolate);
23062 auto result = CompileRun("x.call(s)");
23063 CHECK(!try_catch.HasCaught());
23064 CHECK_EQ(42, result->Int32Value(context.local()).FromJust());
23065 }
23066}
23067
23068
23069TEST(ChainSignatureCheck) {
23070 LocalContext context;
23071 auto isolate = context->GetIsolate();
23072 v8::HandleScope scope(isolate);
23073 auto global = context->Global();
23074 auto sig_obj = FunctionTemplate::New(isolate);
23075 auto sig = v8::Signature::New(isolate, sig_obj);
23076 for (int i = 0; i < 4; ++i) {
23077 auto temp = FunctionTemplate::New(isolate);
23078 temp->Inherit(sig_obj);
23079 sig_obj = temp;
23080 }
23081 auto x = FunctionTemplate::New(isolate, Returns42, Local<Value>(), sig);
23082 global->Set(context.local(), v8_str("sig_obj"),
23083 sig_obj->GetFunction(context.local()).ToLocalChecked())
23084 .FromJust();
23085 global->Set(context.local(), v8_str("x"),
23086 x->GetFunction(context.local()).ToLocalChecked())
23087 .FromJust();
23088 CompileRun("var s = new sig_obj();");
23089 {
23090 TryCatch try_catch(isolate);
23091 CompileRun("x()");
23092 CHECK(try_catch.HasCaught());
23093 }
23094 {
23095 TryCatch try_catch(isolate);
23096 CompileRun("x.call(1)");
23097 CHECK(try_catch.HasCaught());
23098 }
23099 {
23100 TryCatch try_catch(isolate);
23101 auto result = CompileRun("s.x = x; s.x()");
23102 CHECK(!try_catch.HasCaught());
23103 CHECK_EQ(42, result->Int32Value(context.local()).FromJust());
23104 }
23105 {
23106 TryCatch try_catch(isolate);
23107 auto result = CompileRun("x.call(s)");
23108 CHECK(!try_catch.HasCaught());
23109 CHECK_EQ(42, result->Int32Value(context.local()).FromJust());
23110 }
23111}
23112
23113
23114TEST(PrototypeSignatureCheck) {
23115 LocalContext context;
23116 auto isolate = context->GetIsolate();
23117 v8::HandleScope scope(isolate);
23118 auto global = context->Global();
23119 auto sig_obj = FunctionTemplate::New(isolate);
23120 sig_obj->SetHiddenPrototype(true);
23121 auto sig = v8::Signature::New(isolate, sig_obj);
23122 auto x = FunctionTemplate::New(isolate, Returns42, Local<Value>(), sig);
23123 global->Set(context.local(), v8_str("sig_obj"),
23124 sig_obj->GetFunction(context.local()).ToLocalChecked())
23125 .FromJust();
23126 global->Set(context.local(), v8_str("x"),
23127 x->GetFunction(context.local()).ToLocalChecked())
23128 .FromJust();
23129 CompileRun("s = {}; s.__proto__ = new sig_obj();");
23130 {
23131 TryCatch try_catch(isolate);
23132 CompileRun("x()");
23133 CHECK(try_catch.HasCaught());
23134 }
23135 {
23136 TryCatch try_catch(isolate);
23137 CompileRun("x.call(1)");
23138 CHECK(try_catch.HasCaught());
23139 }
23140 {
23141 TryCatch try_catch(isolate);
23142 auto result = CompileRun("s.x = x; s.x()");
23143 CHECK(!try_catch.HasCaught());
23144 CHECK_EQ(42, result->Int32Value(context.local()).FromJust());
23145 }
23146 {
23147 TryCatch try_catch(isolate);
23148 auto result = CompileRun("x.call(s)");
23149 CHECK(!try_catch.HasCaught());
23150 CHECK_EQ(42, result->Int32Value(context.local()).FromJust());
23151 }
23152}
23153
23154
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023155static const char* last_event_message;
23156static int last_event_status;
23157void StoringEventLoggerCallback(const char* message, int status) {
23158 last_event_message = message;
23159 last_event_status = status;
23160}
23161
23162
23163TEST(EventLogging) {
23164 v8::Isolate* isolate = CcTest::isolate();
23165 isolate->SetEventLogger(StoringEventLoggerCallback);
23166 v8::internal::HistogramTimer histogramTimer(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023167 "V8.Test", 0, 10000, v8::internal::HistogramTimer::MILLISECOND, 50,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023168 reinterpret_cast<v8::internal::Isolate*>(isolate));
23169 histogramTimer.Start();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023170 CHECK_EQ(0, strcmp("V8.Test", last_event_message));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023171 CHECK_EQ(0, last_event_status);
23172 histogramTimer.Stop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023173 CHECK_EQ(0, strcmp("V8.Test", last_event_message));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023174 CHECK_EQ(1, last_event_status);
23175}
23176
23177
23178TEST(Promises) {
23179 LocalContext context;
23180 v8::Isolate* isolate = context->GetIsolate();
23181 v8::HandleScope scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023182
23183 // Creation.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023184 Local<v8::Promise::Resolver> pr =
23185 v8::Promise::Resolver::New(context.local()).ToLocalChecked();
23186 Local<v8::Promise::Resolver> rr =
23187 v8::Promise::Resolver::New(context.local()).ToLocalChecked();
23188 Local<v8::Promise> p = pr->GetPromise();
23189 Local<v8::Promise> r = rr->GetPromise();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023190
23191 // IsPromise predicate.
23192 CHECK(p->IsPromise());
23193 CHECK(r->IsPromise());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023194 Local<Value> o = v8::Object::New(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023195 CHECK(!o->IsPromise());
23196
23197 // Resolution and rejection.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023198 pr->Resolve(context.local(), v8::Integer::New(isolate, 1)).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023199 CHECK(p->IsPromise());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023200 rr->Reject(context.local(), v8::Integer::New(isolate, 2)).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023201 CHECK(r->IsPromise());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023202}
23203
23204
23205TEST(PromiseThen) {
23206 LocalContext context;
23207 v8::Isolate* isolate = context->GetIsolate();
23208 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023209 Local<Object> global = context->Global();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023210
23211 // Creation.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023212 Local<v8::Promise::Resolver> pr =
23213 v8::Promise::Resolver::New(context.local()).ToLocalChecked();
23214 Local<v8::Promise::Resolver> qr =
23215 v8::Promise::Resolver::New(context.local()).ToLocalChecked();
23216 Local<v8::Promise> p = pr->GetPromise();
23217 Local<v8::Promise> q = qr->GetPromise();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023218
23219 CHECK(p->IsPromise());
23220 CHECK(q->IsPromise());
23221
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023222 pr->Resolve(context.local(), v8::Integer::New(isolate, 1)).FromJust();
23223 qr->Resolve(context.local(), p).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023224
23225 // Chaining non-pending promises.
23226 CompileRun(
23227 "var x1 = 0;\n"
23228 "var x2 = 0;\n"
23229 "function f1(x) { x1 = x; return x+1 };\n"
23230 "function f2(x) { x2 = x; return x+1 };\n");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023231 Local<Function> f1 = Local<Function>::Cast(
23232 global->Get(context.local(), v8_str("f1")).ToLocalChecked());
23233 Local<Function> f2 = Local<Function>::Cast(
23234 global->Get(context.local(), v8_str("f2")).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023235
23236 // Then
23237 CompileRun("x1 = x2 = 0;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023238 q->Then(context.local(), f1).ToLocalChecked();
23239 CHECK_EQ(0, global->Get(context.local(), v8_str("x1"))
23240 .ToLocalChecked()
23241 ->Int32Value(context.local())
23242 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023243 isolate->RunMicrotasks();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023244 CHECK_EQ(1, global->Get(context.local(), v8_str("x1"))
23245 .ToLocalChecked()
23246 ->Int32Value(context.local())
23247 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023248
23249 // Then
23250 CompileRun("x1 = x2 = 0;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023251 pr = v8::Promise::Resolver::New(context.local()).ToLocalChecked();
23252 qr = v8::Promise::Resolver::New(context.local()).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023253
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023254 qr->Resolve(context.local(), pr).FromJust();
23255 qr->GetPromise()
23256 ->Then(context.local(), f1)
23257 .ToLocalChecked()
23258 ->Then(context.local(), f2)
23259 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023260
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023261 CHECK_EQ(0, global->Get(context.local(), v8_str("x1"))
23262 .ToLocalChecked()
23263 ->Int32Value(context.local())
23264 .FromJust());
23265 CHECK_EQ(0, global->Get(context.local(), v8_str("x2"))
23266 .ToLocalChecked()
23267 ->Int32Value(context.local())
23268 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023269 isolate->RunMicrotasks();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023270 CHECK_EQ(0, global->Get(context.local(), v8_str("x1"))
23271 .ToLocalChecked()
23272 ->Int32Value(context.local())
23273 .FromJust());
23274 CHECK_EQ(0, global->Get(context.local(), v8_str("x2"))
23275 .ToLocalChecked()
23276 ->Int32Value(context.local())
23277 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023278
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023279 pr->Resolve(context.local(), v8::Integer::New(isolate, 3)).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023280
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023281 CHECK_EQ(0, global->Get(context.local(), v8_str("x1"))
23282 .ToLocalChecked()
23283 ->Int32Value(context.local())
23284 .FromJust());
23285 CHECK_EQ(0, global->Get(context.local(), v8_str("x2"))
23286 .ToLocalChecked()
23287 ->Int32Value(context.local())
23288 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023289 isolate->RunMicrotasks();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023290 CHECK_EQ(3, global->Get(context.local(), v8_str("x1"))
23291 .ToLocalChecked()
23292 ->Int32Value(context.local())
23293 .FromJust());
23294 CHECK_EQ(4, global->Get(context.local(), v8_str("x2"))
23295 .ToLocalChecked()
23296 ->Int32Value(context.local())
23297 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023298}
23299
23300
23301TEST(DisallowJavascriptExecutionScope) {
23302 LocalContext context;
23303 v8::Isolate* isolate = context->GetIsolate();
23304 v8::HandleScope scope(isolate);
23305 v8::Isolate::DisallowJavascriptExecutionScope no_js(
23306 isolate, v8::Isolate::DisallowJavascriptExecutionScope::CRASH_ON_FAILURE);
23307 CompileRun("2+2");
23308}
23309
23310
23311TEST(AllowJavascriptExecutionScope) {
23312 LocalContext context;
23313 v8::Isolate* isolate = context->GetIsolate();
23314 v8::HandleScope scope(isolate);
23315 v8::Isolate::DisallowJavascriptExecutionScope no_js(
23316 isolate, v8::Isolate::DisallowJavascriptExecutionScope::CRASH_ON_FAILURE);
23317 v8::Isolate::DisallowJavascriptExecutionScope throw_js(
23318 isolate, v8::Isolate::DisallowJavascriptExecutionScope::THROW_ON_FAILURE);
23319 { v8::Isolate::AllowJavascriptExecutionScope yes_js(isolate);
23320 CompileRun("1+1");
23321 }
23322}
23323
23324
23325TEST(ThrowOnJavascriptExecution) {
23326 LocalContext context;
23327 v8::Isolate* isolate = context->GetIsolate();
23328 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023329 v8::TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023330 v8::Isolate::DisallowJavascriptExecutionScope throw_js(
23331 isolate, v8::Isolate::DisallowJavascriptExecutionScope::THROW_ON_FAILURE);
23332 CompileRun("1+1");
23333 CHECK(try_catch.HasCaught());
23334}
23335
23336
23337TEST(Regress354123) {
23338 LocalContext current;
23339 v8::Isolate* isolate = current->GetIsolate();
23340 v8::HandleScope scope(isolate);
23341
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023342 v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
23343 templ->SetAccessCheckCallback(AccessCounter);
23344 CHECK(current->Global()
23345 ->Set(current.local(), v8_str("friend"),
23346 templ->NewInstance(current.local()).ToLocalChecked())
23347 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023348
23349 // Test access using __proto__ from the prototype chain.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023350 access_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023351 CompileRun("friend.__proto__ = {};");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023352 CHECK_EQ(2, access_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023353 CompileRun("friend.__proto__;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023354 CHECK_EQ(4, access_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023355
23356 // Test access using __proto__ as a hijacked function (A).
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023357 access_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023358 CompileRun("var p = Object.prototype;"
23359 "var f = Object.getOwnPropertyDescriptor(p, '__proto__').set;"
23360 "f.call(friend, {});");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023361 CHECK_EQ(1, access_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023362 CompileRun("var p = Object.prototype;"
23363 "var f = Object.getOwnPropertyDescriptor(p, '__proto__').get;"
23364 "f.call(friend);");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023365 CHECK_EQ(2, access_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023366
23367 // Test access using __proto__ as a hijacked function (B).
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023368 access_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023369 CompileRun("var f = Object.prototype.__lookupSetter__('__proto__');"
23370 "f.call(friend, {});");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023371 CHECK_EQ(1, access_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023372 CompileRun("var f = Object.prototype.__lookupGetter__('__proto__');"
23373 "f.call(friend);");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023374 CHECK_EQ(2, access_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023375
23376 // Test access using Object.setPrototypeOf reflective method.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023377 access_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023378 CompileRun("Object.setPrototypeOf(friend, {});");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023379 CHECK_EQ(1, access_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023380 CompileRun("Object.getPrototypeOf(friend);");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023381 CHECK_EQ(2, access_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023382}
23383
23384
23385TEST(CaptureStackTraceForStackOverflow) {
23386 v8::internal::FLAG_stack_size = 150;
23387 LocalContext current;
23388 v8::Isolate* isolate = current->GetIsolate();
23389 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023390 isolate->SetCaptureStackTraceForUncaughtExceptions(true, 10,
23391 v8::StackTrace::kDetailed);
23392 v8::TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023393 CompileRun("(function f(x) { f(x+1); })(0)");
23394 CHECK(try_catch.HasCaught());
23395}
23396
23397
23398TEST(ScriptNameAndLineNumber) {
23399 LocalContext env;
23400 v8::Isolate* isolate = env->GetIsolate();
23401 v8::HandleScope scope(isolate);
23402 const char* url = "http://www.foo.com/foo.js";
23403 v8::ScriptOrigin origin(v8_str(url), v8::Integer::New(isolate, 13));
23404 v8::ScriptCompiler::Source script_source(v8_str("var foo;"), origin);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023405 Local<Script> script =
23406 v8::ScriptCompiler::Compile(env.local(), &script_source).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023407 Local<Value> script_name = script->GetUnboundScript()->GetScriptName();
23408 CHECK(!script_name.IsEmpty());
23409 CHECK(script_name->IsString());
23410 String::Utf8Value utf8_name(script_name);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023411 CHECK_EQ(0, strcmp(url, *utf8_name));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023412 int line_number = script->GetUnboundScript()->GetLineNumber(0);
23413 CHECK_EQ(13, line_number);
23414}
23415
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023416void CheckMagicComments(Local<Script> script, const char* expected_source_url,
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023417 const char* expected_source_mapping_url) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023418 if (expected_source_url != NULL) {
23419 v8::String::Utf8Value url(script->GetUnboundScript()->GetSourceURL());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023420 CHECK_EQ(0, strcmp(expected_source_url, *url));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023421 } else {
23422 CHECK(script->GetUnboundScript()->GetSourceURL()->IsUndefined());
23423 }
23424 if (expected_source_mapping_url != NULL) {
23425 v8::String::Utf8Value url(
23426 script->GetUnboundScript()->GetSourceMappingURL());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023427 CHECK_EQ(0, strcmp(expected_source_mapping_url, *url));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023428 } else {
23429 CHECK(script->GetUnboundScript()->GetSourceMappingURL()->IsUndefined());
23430 }
23431}
23432
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023433void SourceURLHelper(const char* source, const char* expected_source_url,
23434 const char* expected_source_mapping_url) {
23435 Local<Script> script = v8_compile(source);
23436 CheckMagicComments(script, expected_source_url, expected_source_mapping_url);
23437}
23438
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023439
23440TEST(ScriptSourceURLAndSourceMappingURL) {
23441 LocalContext env;
23442 v8::Isolate* isolate = env->GetIsolate();
23443 v8::HandleScope scope(isolate);
23444 SourceURLHelper("function foo() {}\n"
23445 "//# sourceURL=bar1.js\n", "bar1.js", NULL);
23446 SourceURLHelper("function foo() {}\n"
23447 "//# sourceMappingURL=bar2.js\n", NULL, "bar2.js");
23448
23449 // Both sourceURL and sourceMappingURL.
23450 SourceURLHelper("function foo() {}\n"
23451 "//# sourceURL=bar3.js\n"
23452 "//# sourceMappingURL=bar4.js\n", "bar3.js", "bar4.js");
23453
23454 // Two source URLs; the first one is ignored.
23455 SourceURLHelper("function foo() {}\n"
23456 "//# sourceURL=ignoreme.js\n"
23457 "//# sourceURL=bar5.js\n", "bar5.js", NULL);
23458 SourceURLHelper("function foo() {}\n"
23459 "//# sourceMappingURL=ignoreme.js\n"
23460 "//# sourceMappingURL=bar6.js\n", NULL, "bar6.js");
23461
23462 // SourceURL or sourceMappingURL in the middle of the script.
23463 SourceURLHelper("function foo() {}\n"
23464 "//# sourceURL=bar7.js\n"
23465 "function baz() {}\n", "bar7.js", NULL);
23466 SourceURLHelper("function foo() {}\n"
23467 "//# sourceMappingURL=bar8.js\n"
23468 "function baz() {}\n", NULL, "bar8.js");
23469
23470 // Too much whitespace.
23471 SourceURLHelper("function foo() {}\n"
23472 "//# sourceURL=bar9.js\n"
23473 "//# sourceMappingURL=bar10.js\n", NULL, NULL);
23474 SourceURLHelper("function foo() {}\n"
23475 "//# sourceURL =bar11.js\n"
23476 "//# sourceMappingURL =bar12.js\n", NULL, NULL);
23477
23478 // Disallowed characters in value.
23479 SourceURLHelper("function foo() {}\n"
23480 "//# sourceURL=bar13 .js \n"
23481 "//# sourceMappingURL=bar14 .js \n",
23482 NULL, NULL);
23483 SourceURLHelper("function foo() {}\n"
23484 "//# sourceURL=bar15\t.js \n"
23485 "//# sourceMappingURL=bar16\t.js \n",
23486 NULL, NULL);
23487 SourceURLHelper("function foo() {}\n"
23488 "//# sourceURL=bar17'.js \n"
23489 "//# sourceMappingURL=bar18'.js \n",
23490 NULL, NULL);
23491 SourceURLHelper("function foo() {}\n"
23492 "//# sourceURL=bar19\".js \n"
23493 "//# sourceMappingURL=bar20\".js \n",
23494 NULL, NULL);
23495
23496 // Not too much whitespace.
23497 SourceURLHelper("function foo() {}\n"
23498 "//# sourceURL= bar21.js \n"
23499 "//# sourceMappingURL= bar22.js \n", "bar21.js", "bar22.js");
23500}
23501
23502
23503TEST(GetOwnPropertyDescriptor) {
23504 LocalContext env;
23505 v8::Isolate* isolate = env->GetIsolate();
23506 v8::HandleScope scope(isolate);
23507 CompileRun(
23508 "var x = { value : 13};"
23509 "Object.defineProperty(x, 'p0', {value : 12});"
23510 "Object.defineProperty(x, 'p1', {"
23511 " set : function(value) { this.value = value; },"
23512 " get : function() { return this.value; },"
23513 "});");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023514 Local<Object> x = Local<Object>::Cast(
23515 env->Global()->Get(env.local(), v8_str("x")).ToLocalChecked());
23516 Local<Value> desc =
23517 x->GetOwnPropertyDescriptor(env.local(), v8_str("no_prop"))
23518 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023519 CHECK(desc->IsUndefined());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023520 desc =
23521 x->GetOwnPropertyDescriptor(env.local(), v8_str("p0")).ToLocalChecked();
23522 CHECK(v8_num(12)
23523 ->Equals(env.local(), Local<Object>::Cast(desc)
23524 ->Get(env.local(), v8_str("value"))
23525 .ToLocalChecked())
23526 .FromJust());
23527 desc =
23528 x->GetOwnPropertyDescriptor(env.local(), v8_str("p1")).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023529 Local<Function> set =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023530 Local<Function>::Cast(Local<Object>::Cast(desc)
23531 ->Get(env.local(), v8_str("set"))
23532 .ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023533 Local<Function> get =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023534 Local<Function>::Cast(Local<Object>::Cast(desc)
23535 ->Get(env.local(), v8_str("get"))
23536 .ToLocalChecked());
23537 CHECK(v8_num(13)
23538 ->Equals(env.local(),
23539 get->Call(env.local(), x, 0, NULL).ToLocalChecked())
23540 .FromJust());
23541 Local<Value> args[] = {v8_num(14)};
23542 set->Call(env.local(), x, 1, args).ToLocalChecked();
23543 CHECK(v8_num(14)
23544 ->Equals(env.local(),
23545 get->Call(env.local(), x, 0, NULL).ToLocalChecked())
23546 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023547}
23548
23549
23550TEST(Regress411877) {
23551 v8::Isolate* isolate = CcTest::isolate();
23552 v8::HandleScope handle_scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023553 v8::Local<v8::ObjectTemplate> object_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023554 v8::ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023555 object_template->SetAccessCheckCallback(AccessCounter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023556
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023557 v8::Local<Context> context = Context::New(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023558 v8::Context::Scope context_scope(context);
23559
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023560 CHECK(context->Global()
23561 ->Set(context, v8_str("o"),
23562 object_template->NewInstance(context).ToLocalChecked())
23563 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023564 CompileRun("Object.getOwnPropertyNames(o)");
23565}
23566
23567
23568TEST(GetHiddenPropertyTableAfterAccessCheck) {
23569 v8::Isolate* isolate = CcTest::isolate();
23570 v8::HandleScope handle_scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023571 v8::Local<v8::ObjectTemplate> object_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023572 v8::ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023573 object_template->SetAccessCheckCallback(AccessCounter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023574
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023575 v8::Local<Context> context = Context::New(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023576 v8::Context::Scope context_scope(context);
23577
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023578 v8::Local<v8::Object> obj =
23579 object_template->NewInstance(context).ToLocalChecked();
23580 obj->Set(context, v8_str("key"), v8_str("value")).FromJust();
23581 obj->Delete(context, v8_str("key")).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023582
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023583 obj->SetPrivate(context, v8::Private::New(isolate, v8_str("hidden key 2")),
23584 v8_str("hidden value 2"))
23585 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023586}
23587
23588
23589TEST(Regress411793) {
23590 v8::Isolate* isolate = CcTest::isolate();
23591 v8::HandleScope handle_scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023592 v8::Local<v8::ObjectTemplate> object_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023593 v8::ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023594 object_template->SetAccessCheckCallback(AccessCounter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023595
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023596 v8::Local<Context> context = Context::New(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023597 v8::Context::Scope context_scope(context);
23598
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023599 CHECK(context->Global()
23600 ->Set(context, v8_str("o"),
23601 object_template->NewInstance(context).ToLocalChecked())
23602 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023603 CompileRun(
23604 "Object.defineProperty(o, 'key', "
23605 " { get: function() {}, set: function() {} });");
23606}
23607
23608class TestSourceStream : public v8::ScriptCompiler::ExternalSourceStream {
23609 public:
23610 explicit TestSourceStream(const char** chunks) : chunks_(chunks), index_(0) {}
23611
23612 virtual size_t GetMoreData(const uint8_t** src) {
23613 // Unlike in real use cases, this function will never block.
23614 if (chunks_[index_] == NULL) {
23615 return 0;
23616 }
23617 // Copy the data, since the caller takes ownership of it.
23618 size_t len = strlen(chunks_[index_]);
23619 // We don't need to zero-terminate since we return the length.
23620 uint8_t* copy = new uint8_t[len];
23621 memcpy(copy, chunks_[index_], len);
23622 *src = copy;
23623 ++index_;
23624 return len;
23625 }
23626
23627 // Helper for constructing a string from chunks (the compilation needs it
23628 // too).
23629 static char* FullSourceString(const char** chunks) {
23630 size_t total_len = 0;
23631 for (size_t i = 0; chunks[i] != NULL; ++i) {
23632 total_len += strlen(chunks[i]);
23633 }
23634 char* full_string = new char[total_len + 1];
23635 size_t offset = 0;
23636 for (size_t i = 0; chunks[i] != NULL; ++i) {
23637 size_t len = strlen(chunks[i]);
23638 memcpy(full_string + offset, chunks[i], len);
23639 offset += len;
23640 }
23641 full_string[total_len] = 0;
23642 return full_string;
23643 }
23644
23645 private:
23646 const char** chunks_;
23647 unsigned index_;
23648};
23649
23650
23651// Helper function for running streaming tests.
23652void RunStreamingTest(const char** chunks,
23653 v8::ScriptCompiler::StreamedSource::Encoding encoding =
23654 v8::ScriptCompiler::StreamedSource::ONE_BYTE,
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023655 bool expected_success = true,
23656 const char* expected_source_url = NULL,
23657 const char* expected_source_mapping_url = NULL) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023658 LocalContext env;
23659 v8::Isolate* isolate = env->GetIsolate();
23660 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023661 v8::TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023662
23663 v8::ScriptCompiler::StreamedSource source(new TestSourceStream(chunks),
23664 encoding);
23665 v8::ScriptCompiler::ScriptStreamingTask* task =
23666 v8::ScriptCompiler::StartStreamingScript(isolate, &source);
23667
23668 // TestSourceStream::GetMoreData won't block, so it's OK to just run the
23669 // task here in the main thread.
23670 task->Run();
23671 delete task;
23672
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023673 // Possible errors are only produced while compiling.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023674 CHECK_EQ(false, try_catch.HasCaught());
23675
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023676 v8::ScriptOrigin origin(v8_str("http://foo.com"));
23677 char* full_source = TestSourceStream::FullSourceString(chunks);
23678 v8::MaybeLocal<Script> script = v8::ScriptCompiler::Compile(
23679 env.local(), &source, v8_str(full_source), origin);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023680 if (expected_success) {
23681 CHECK(!script.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023682 v8::Local<Value> result(
23683 script.ToLocalChecked()->Run(env.local()).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023684 // All scripts are supposed to return the fixed value 13 when ran.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023685 CHECK_EQ(13, result->Int32Value(env.local()).FromJust());
23686 CheckMagicComments(script.ToLocalChecked(), expected_source_url,
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023687 expected_source_mapping_url);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023688 } else {
23689 CHECK(script.IsEmpty());
23690 CHECK(try_catch.HasCaught());
23691 }
23692 delete[] full_source;
23693}
23694
23695
23696TEST(StreamingSimpleScript) {
23697 // This script is unrealistically small, since no one chunk is enough to fill
23698 // the backing buffer of Scanner, let alone overflow it.
23699 const char* chunks[] = {"function foo() { ret", "urn 13; } f", "oo(); ",
23700 NULL};
23701 RunStreamingTest(chunks);
23702}
23703
23704
23705TEST(StreamingBiggerScript) {
23706 const char* chunk1 =
23707 "function foo() {\n"
23708 " // Make this chunk sufficiently long so that it will overflow the\n"
23709 " // backing buffer of the Scanner.\n"
23710 " var i = 0;\n"
23711 " var result = 0;\n"
23712 " for (i = 0; i < 13; ++i) { result = result + 1; }\n"
23713 " result = 0;\n"
23714 " for (i = 0; i < 13; ++i) { result = result + 1; }\n"
23715 " result = 0;\n"
23716 " for (i = 0; i < 13; ++i) { result = result + 1; }\n"
23717 " result = 0;\n"
23718 " for (i = 0; i < 13; ++i) { result = result + 1; }\n"
23719 " return result;\n"
23720 "}\n";
23721 const char* chunks[] = {chunk1, "foo(); ", NULL};
23722 RunStreamingTest(chunks);
23723}
23724
23725
23726TEST(StreamingScriptWithParseError) {
23727 // Test that parse errors from streamed scripts are propagated correctly.
23728 {
23729 char chunk1[] =
23730 " // This will result in a parse error.\n"
23731 " var if else then foo";
23732 char chunk2[] = " 13\n";
23733 const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
23734
23735 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::ONE_BYTE,
23736 false);
23737 }
23738 // Test that the next script succeeds normally.
23739 {
23740 char chunk1[] =
23741 " // This will be parsed successfully.\n"
23742 " function foo() { return ";
23743 char chunk2[] = " 13; }\n";
23744 const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
23745
23746 RunStreamingTest(chunks);
23747 }
23748}
23749
23750
23751TEST(StreamingUtf8Script) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023752 // We'd want to write \uc481 instead of \xec\x92\x81, but Windows compilers
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023753 // don't like it.
23754 const char* chunk1 =
23755 "function foo() {\n"
23756 " // This function will contain an UTF-8 character which is not in\n"
23757 " // ASCII.\n"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023758 " var foob\xec\x92\x81r = 13;\n"
23759 " return foob\xec\x92\x81r;\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023760 "}\n";
23761 const char* chunks[] = {chunk1, "foo(); ", NULL};
23762 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
23763}
23764
23765
23766TEST(StreamingUtf8ScriptWithSplitCharactersSanityCheck) {
23767 // A sanity check to prove that the approach of splitting UTF-8
23768 // characters is correct. Here is an UTF-8 character which will take three
23769 // bytes.
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023770 const char* reference = "\xec\x92\x81";
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023771 CHECK(3u == strlen(reference)); // NOLINT - no CHECK_EQ for unsigned.
23772
23773 char chunk1[] =
23774 "function foo() {\n"
23775 " // This function will contain an UTF-8 character which is not in\n"
23776 " // ASCII.\n"
23777 " var foob";
23778 char chunk2[] =
23779 "XXXr = 13;\n"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023780 " return foob\xec\x92\x81r;\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023781 "}\n";
23782 for (int i = 0; i < 3; ++i) {
23783 chunk2[i] = reference[i];
23784 }
23785 const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
23786 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
23787}
23788
23789
23790TEST(StreamingUtf8ScriptWithSplitCharacters) {
23791 // Stream data where a multi-byte UTF-8 character is split between two data
23792 // chunks.
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023793 const char* reference = "\xec\x92\x81";
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023794 char chunk1[] =
23795 "function foo() {\n"
23796 " // This function will contain an UTF-8 character which is not in\n"
23797 " // ASCII.\n"
23798 " var foobX";
23799 char chunk2[] =
23800 "XXr = 13;\n"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023801 " return foob\xec\x92\x81r;\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023802 "}\n";
23803 chunk1[strlen(chunk1) - 1] = reference[0];
23804 chunk2[0] = reference[1];
23805 chunk2[1] = reference[2];
23806 const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
23807 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
23808}
23809
23810
23811TEST(StreamingUtf8ScriptWithSplitCharactersValidEdgeCases) {
23812 // Tests edge cases which should still be decoded correctly.
23813
23814 // Case 1: a chunk contains only bytes for a split character (and no other
23815 // data). This kind of a chunk would be exceptionally small, but we should
23816 // still decode it correctly.
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023817 const char* reference = "\xec\x92\x81";
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023818 // The small chunk is at the beginning of the split character
23819 {
23820 char chunk1[] =
23821 "function foo() {\n"
23822 " // This function will contain an UTF-8 character which is not in\n"
23823 " // ASCII.\n"
23824 " var foob";
23825 char chunk2[] = "XX";
23826 char chunk3[] =
23827 "Xr = 13;\n"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023828 " return foob\xec\x92\x81r;\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023829 "}\n";
23830 chunk2[0] = reference[0];
23831 chunk2[1] = reference[1];
23832 chunk3[0] = reference[2];
23833 const char* chunks[] = {chunk1, chunk2, chunk3, "foo();", NULL};
23834 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
23835 }
23836 // The small chunk is at the end of a character
23837 {
23838 char chunk1[] =
23839 "function foo() {\n"
23840 " // This function will contain an UTF-8 character which is not in\n"
23841 " // ASCII.\n"
23842 " var foobX";
23843 char chunk2[] = "XX";
23844 char chunk3[] =
23845 "r = 13;\n"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023846 " return foob\xec\x92\x81r;\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023847 "}\n";
23848 chunk1[strlen(chunk1) - 1] = reference[0];
23849 chunk2[0] = reference[1];
23850 chunk2[1] = reference[2];
23851 const char* chunks[] = {chunk1, chunk2, chunk3, "foo();", NULL};
23852 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
23853 }
23854 // Case 2: the script ends with a multi-byte character. Make sure that it's
23855 // decoded correctly and not just ignored.
23856 {
23857 char chunk1[] =
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023858 "var foob\xec\x92\x81 = 13;\n"
23859 "foob\xec\x92\x81";
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023860 const char* chunks[] = {chunk1, NULL};
23861 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
23862 }
23863}
23864
23865
23866TEST(StreamingUtf8ScriptWithSplitCharactersInvalidEdgeCases) {
23867 // Test cases where a UTF-8 character is split over several chunks. Those
23868 // cases are not supported (the embedder should give the data in big enough
23869 // chunks), but we shouldn't crash, just produce a parse error.
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023870 const char* reference = "\xec\x92\x81";
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023871 char chunk1[] =
23872 "function foo() {\n"
23873 " // This function will contain an UTF-8 character which is not in\n"
23874 " // ASCII.\n"
23875 " var foobX";
23876 char chunk2[] = "X";
23877 char chunk3[] =
23878 "Xr = 13;\n"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023879 " return foob\xec\x92\x81r;\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023880 "}\n";
23881 chunk1[strlen(chunk1) - 1] = reference[0];
23882 chunk2[0] = reference[1];
23883 chunk3[0] = reference[2];
23884 const char* chunks[] = {chunk1, chunk2, chunk3, "foo();", NULL};
23885
23886 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, false);
23887}
23888
23889
23890TEST(StreamingProducesParserCache) {
23891 i::FLAG_min_preparse_length = 0;
23892 const char* chunks[] = {"function foo() { ret", "urn 13; } f", "oo(); ",
23893 NULL};
23894
23895 LocalContext env;
23896 v8::Isolate* isolate = env->GetIsolate();
23897 v8::HandleScope scope(isolate);
23898
23899 v8::ScriptCompiler::StreamedSource source(
23900 new TestSourceStream(chunks),
23901 v8::ScriptCompiler::StreamedSource::ONE_BYTE);
23902 v8::ScriptCompiler::ScriptStreamingTask* task =
23903 v8::ScriptCompiler::StartStreamingScript(
23904 isolate, &source, v8::ScriptCompiler::kProduceParserCache);
23905
23906 // TestSourceStream::GetMoreData won't block, so it's OK to just run the
23907 // task here in the main thread.
23908 task->Run();
23909 delete task;
23910
23911 const v8::ScriptCompiler::CachedData* cached_data = source.GetCachedData();
23912 CHECK(cached_data != NULL);
23913 CHECK(cached_data->data != NULL);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023914 CHECK(!cached_data->rejected);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023915 CHECK_GT(cached_data->length, 0);
23916}
23917
23918
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023919TEST(StreamingWithDebuggingEnabledLate) {
23920 // The streaming parser can only parse lazily, i.e. inner functions are not
23921 // fully parsed. However, we may compile inner functions eagerly when
23922 // debugging. Make sure that we can deal with this when turning on debugging
23923 // after streaming parser has already finished parsing.
23924 i::FLAG_min_preparse_length = 0;
23925 const char* chunks[] = {"with({x:1}) {",
23926 " var foo = function foo(y) {",
23927 " return x + y;",
23928 " };",
23929 " foo(2);",
23930 "}",
23931 NULL};
23932
23933 LocalContext env;
23934 v8::Isolate* isolate = env->GetIsolate();
23935 v8::HandleScope scope(isolate);
23936 v8::TryCatch try_catch(isolate);
23937
23938 v8::ScriptCompiler::StreamedSource source(
23939 new TestSourceStream(chunks),
23940 v8::ScriptCompiler::StreamedSource::ONE_BYTE);
23941 v8::ScriptCompiler::ScriptStreamingTask* task =
23942 v8::ScriptCompiler::StartStreamingScript(isolate, &source);
23943
23944 task->Run();
23945 delete task;
23946
23947 CHECK(!try_catch.HasCaught());
23948
23949 v8::ScriptOrigin origin(v8_str("http://foo.com"));
23950 char* full_source = TestSourceStream::FullSourceString(chunks);
23951
23952 EnableDebugger(isolate);
23953
23954 v8::Local<Script> script =
23955 v8::ScriptCompiler::Compile(env.local(), &source, v8_str(full_source),
23956 origin)
23957 .ToLocalChecked();
23958
23959 Maybe<uint32_t> result =
23960 script->Run(env.local()).ToLocalChecked()->Uint32Value(env.local());
23961 CHECK_EQ(3U, result.FromMaybe(0));
23962
23963 delete[] full_source;
23964
23965 DisableDebugger(isolate);
23966}
23967
23968
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023969TEST(StreamingScriptWithInvalidUtf8) {
23970 // Regression test for a crash: test that invalid UTF-8 bytes in the end of a
23971 // chunk don't produce a crash.
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023972 const char* reference = "\xec\x92\x81\x80\x80";
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023973 char chunk1[] =
23974 "function foo() {\n"
23975 " // This function will contain an UTF-8 character which is not in\n"
23976 " // ASCII.\n"
23977 " var foobXXXXX"; // Too many bytes which look like incomplete chars!
23978 char chunk2[] =
23979 "r = 13;\n"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023980 " return foob\xec\x92\x81\x80\x80r;\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023981 "}\n";
23982 for (int i = 0; i < 5; ++i) chunk1[strlen(chunk1) - 5 + i] = reference[i];
23983
23984 const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
23985 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, false);
23986}
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023987
23988
23989TEST(StreamingUtf8ScriptWithMultipleMultibyteCharactersSomeSplit) {
23990 // Regression test: Stream data where there are several multi-byte UTF-8
23991 // characters in a sequence and one of them is split between two data chunks.
23992 const char* reference = "\xec\x92\x81";
23993 char chunk1[] =
23994 "function foo() {\n"
23995 " // This function will contain an UTF-8 character which is not in\n"
23996 " // ASCII.\n"
23997 " var foob\xec\x92\x81X";
23998 char chunk2[] =
23999 "XXr = 13;\n"
24000 " return foob\xec\x92\x81\xec\x92\x81r;\n"
24001 "}\n";
24002 chunk1[strlen(chunk1) - 1] = reference[0];
24003 chunk2[0] = reference[1];
24004 chunk2[1] = reference[2];
24005 const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
24006 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
24007}
24008
24009
24010TEST(StreamingUtf8ScriptWithMultipleMultibyteCharactersSomeSplit2) {
24011 // Another regression test, similar to the previous one. The difference is
24012 // that the split character is not the last one in the sequence.
24013 const char* reference = "\xec\x92\x81";
24014 char chunk1[] =
24015 "function foo() {\n"
24016 " // This function will contain an UTF-8 character which is not in\n"
24017 " // ASCII.\n"
24018 " var foobX";
24019 char chunk2[] =
24020 "XX\xec\x92\x81r = 13;\n"
24021 " return foob\xec\x92\x81\xec\x92\x81r;\n"
24022 "}\n";
24023 chunk1[strlen(chunk1) - 1] = reference[0];
24024 chunk2[0] = reference[1];
24025 chunk2[1] = reference[2];
24026 const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
24027 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
24028}
24029
24030
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024031TEST(StreamingWithHarmonyScopes) {
24032 // Don't use RunStreamingTest here so that both scripts get to use the same
24033 // LocalContext and HandleScope.
24034 LocalContext env;
24035 v8::Isolate* isolate = env->GetIsolate();
24036 v8::HandleScope scope(isolate);
24037
24038 // First, run a script with a let variable.
24039 CompileRun("\"use strict\"; let x = 1;");
24040
24041 // Then stream a script which (erroneously) tries to introduce the same
24042 // variable again.
24043 const char* chunks[] = {"\"use strict\"; let x = 2;", NULL};
24044
24045 v8::TryCatch try_catch(isolate);
24046 v8::ScriptCompiler::StreamedSource source(
24047 new TestSourceStream(chunks),
24048 v8::ScriptCompiler::StreamedSource::ONE_BYTE);
24049 v8::ScriptCompiler::ScriptStreamingTask* task =
24050 v8::ScriptCompiler::StartStreamingScript(isolate, &source);
24051 task->Run();
24052 delete task;
24053
24054 // Parsing should succeed (the script will be parsed and compiled in a context
24055 // independent way, so the error is not detected).
24056 CHECK_EQ(false, try_catch.HasCaught());
24057
24058 v8::ScriptOrigin origin(v8_str("http://foo.com"));
24059 char* full_source = TestSourceStream::FullSourceString(chunks);
24060 v8::Local<Script> script =
24061 v8::ScriptCompiler::Compile(env.local(), &source, v8_str(full_source),
24062 origin)
24063 .ToLocalChecked();
24064 CHECK(!script.IsEmpty());
24065 CHECK_EQ(false, try_catch.HasCaught());
24066
24067 // Running the script exposes the error.
24068 CHECK(script->Run(env.local()).IsEmpty());
24069 CHECK(try_catch.HasCaught());
24070 delete[] full_source;
24071}
24072
24073
24074TEST(CodeCache) {
24075 v8::Isolate::CreateParams create_params;
24076 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
24077
24078 const char* source = "Math.sqrt(4)";
24079 const char* origin = "code cache test";
24080 v8::ScriptCompiler::CachedData* cache;
24081
24082 v8::Isolate* isolate1 = v8::Isolate::New(create_params);
24083 {
24084 v8::Isolate::Scope iscope(isolate1);
24085 v8::HandleScope scope(isolate1);
24086 v8::Local<v8::Context> context = v8::Context::New(isolate1);
24087 v8::Context::Scope cscope(context);
24088 v8::Local<v8::String> source_string = v8_str(source);
24089 v8::ScriptOrigin script_origin(v8_str(origin));
24090 v8::ScriptCompiler::Source source(source_string, script_origin);
24091 v8::ScriptCompiler::CompileOptions option =
24092 v8::ScriptCompiler::kProduceCodeCache;
24093 v8::ScriptCompiler::Compile(context, &source, option).ToLocalChecked();
24094 int length = source.GetCachedData()->length;
24095 uint8_t* cache_data = new uint8_t[length];
24096 memcpy(cache_data, source.GetCachedData()->data, length);
24097 cache = new v8::ScriptCompiler::CachedData(
24098 cache_data, length, v8::ScriptCompiler::CachedData::BufferOwned);
24099 }
24100 isolate1->Dispose();
24101
24102 v8::Isolate* isolate2 = v8::Isolate::New(create_params);
24103 {
24104 v8::Isolate::Scope iscope(isolate2);
24105 v8::HandleScope scope(isolate2);
24106 v8::Local<v8::Context> context = v8::Context::New(isolate2);
24107 v8::Context::Scope cscope(context);
24108 v8::Local<v8::String> source_string = v8_str(source);
24109 v8::ScriptOrigin script_origin(v8_str(origin));
24110 v8::ScriptCompiler::Source source(source_string, script_origin, cache);
24111 v8::ScriptCompiler::CompileOptions option =
24112 v8::ScriptCompiler::kConsumeCodeCache;
24113 v8::Local<v8::Script> script;
24114 {
24115 i::DisallowCompilation no_compile(
24116 reinterpret_cast<i::Isolate*>(isolate2));
24117 script = v8::ScriptCompiler::Compile(context, &source, option)
24118 .ToLocalChecked();
24119 }
24120 CHECK_EQ(2, script->Run(context)
24121 .ToLocalChecked()
24122 ->ToInt32(context)
24123 .ToLocalChecked()
24124 ->Int32Value(context)
24125 .FromJust());
24126 }
24127 isolate2->Dispose();
24128}
24129
24130
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024131void TestInvalidCacheData(v8::ScriptCompiler::CompileOptions option) {
24132 const char* garbage = "garbage garbage garbage garbage garbage garbage";
24133 const uint8_t* data = reinterpret_cast<const uint8_t*>(garbage);
24134 int length = 16;
24135 v8::ScriptCompiler::CachedData* cached_data =
24136 new v8::ScriptCompiler::CachedData(data, length);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024137 CHECK(!cached_data->rejected);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024138 v8::ScriptOrigin origin(v8_str("origin"));
24139 v8::ScriptCompiler::Source source(v8_str("42"), origin, cached_data);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024140 v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
24141 v8::Local<v8::Script> script =
24142 v8::ScriptCompiler::Compile(context, &source, option).ToLocalChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024143 CHECK(cached_data->rejected);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024144 CHECK_EQ(
24145 42,
24146 script->Run(context).ToLocalChecked()->Int32Value(context).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024147}
24148
Ben Murdochc5610432016-08-08 18:44:38 +010024149TEST(InvalidParserCacheData) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024150 v8::V8::Initialize();
24151 v8::HandleScope scope(CcTest::isolate());
24152 LocalContext context;
Ben Murdochda12d292016-06-02 14:46:10 +010024153 if (i::FLAG_lazy && !(i::FLAG_ignition && i::FLAG_ignition_eager)) {
24154 // Cached parser data is not consumed while parsing eagerly.
24155 TestInvalidCacheData(v8::ScriptCompiler::kConsumeParserCache);
24156 }
Ben Murdochc5610432016-08-08 18:44:38 +010024157}
24158
24159TEST(InvalidCodeCacheData) {
24160 v8::V8::Initialize();
24161 v8::HandleScope scope(CcTest::isolate());
24162 LocalContext context;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024163 TestInvalidCacheData(v8::ScriptCompiler::kConsumeCodeCache);
24164}
24165
24166
24167TEST(ParserCacheRejectedGracefully) {
Ben Murdochda12d292016-06-02 14:46:10 +010024168 // Producing cached parser data while parsing eagerly is not supported.
24169 if (!i::FLAG_lazy || (i::FLAG_ignition && i::FLAG_ignition_eager)) return;
24170
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024171 i::FLAG_min_preparse_length = 0;
24172 v8::V8::Initialize();
24173 v8::HandleScope scope(CcTest::isolate());
24174 LocalContext context;
24175 // Produce valid cached data.
24176 v8::ScriptOrigin origin(v8_str("origin"));
24177 v8::Local<v8::String> source_str = v8_str("function foo() {}");
24178 v8::ScriptCompiler::Source source(source_str, origin);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024179 v8::Local<v8::Script> script =
24180 v8::ScriptCompiler::Compile(context.local(), &source,
24181 v8::ScriptCompiler::kProduceParserCache)
24182 .ToLocalChecked();
24183 USE(script);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024184 const v8::ScriptCompiler::CachedData* original_cached_data =
24185 source.GetCachedData();
24186 CHECK(original_cached_data != NULL);
24187 CHECK(original_cached_data->data != NULL);
24188 CHECK(!original_cached_data->rejected);
24189 CHECK_GT(original_cached_data->length, 0);
24190 // Recompiling the same script with it won't reject the data.
24191 {
24192 v8::ScriptCompiler::Source source_with_cached_data(
24193 source_str, origin,
24194 new v8::ScriptCompiler::CachedData(original_cached_data->data,
24195 original_cached_data->length));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024196 v8::Local<v8::Script> script =
24197 v8::ScriptCompiler::Compile(context.local(), &source_with_cached_data,
24198 v8::ScriptCompiler::kConsumeParserCache)
24199 .ToLocalChecked();
24200 USE(script);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024201 const v8::ScriptCompiler::CachedData* new_cached_data =
24202 source_with_cached_data.GetCachedData();
24203 CHECK(new_cached_data != NULL);
24204 CHECK(!new_cached_data->rejected);
24205 }
24206 // Compile an incompatible script with the cached data. The new script doesn't
24207 // have the same starting position for the function as the old one, so the old
24208 // cached data will be incompatible with it and will be rejected.
24209 {
24210 v8::Local<v8::String> incompatible_source_str =
24211 v8_str(" function foo() {}");
24212 v8::ScriptCompiler::Source source_with_cached_data(
24213 incompatible_source_str, origin,
24214 new v8::ScriptCompiler::CachedData(original_cached_data->data,
24215 original_cached_data->length));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024216 v8::Local<v8::Script> script =
24217 v8::ScriptCompiler::Compile(context.local(), &source_with_cached_data,
24218 v8::ScriptCompiler::kConsumeParserCache)
24219 .ToLocalChecked();
24220 USE(script);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024221 const v8::ScriptCompiler::CachedData* new_cached_data =
24222 source_with_cached_data.GetCachedData();
24223 CHECK(new_cached_data != NULL);
24224 CHECK(new_cached_data->rejected);
24225 }
24226}
24227
24228
24229TEST(StringConcatOverflow) {
24230 v8::V8::Initialize();
24231 v8::HandleScope scope(CcTest::isolate());
24232 RandomLengthOneByteResource* r =
24233 new RandomLengthOneByteResource(i::String::kMaxLength);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024234 v8::Local<v8::String> str =
24235 v8::String::NewExternalOneByte(CcTest::isolate(), r).ToLocalChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024236 CHECK(!str.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024237 v8::TryCatch try_catch(CcTest::isolate());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024238 v8::Local<v8::String> result = v8::String::Concat(str, str);
24239 CHECK(result.IsEmpty());
24240 CHECK(!try_catch.HasCaught());
24241}
24242
24243
24244TEST(TurboAsmDisablesNeuter) {
Ben Murdochc5610432016-08-08 18:44:38 +010024245 i::FLAG_allow_natives_syntax = true;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024246 v8::V8::Initialize();
24247 v8::HandleScope scope(CcTest::isolate());
24248 LocalContext context;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024249 bool should_be_neuterable = !i::FLAG_turbo_asm;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024250 const char* load =
24251 "function Module(stdlib, foreign, heap) {"
24252 " 'use asm';"
24253 " var MEM32 = new stdlib.Int32Array(heap);"
24254 " function load() { return MEM32[0]; }"
24255 " return { load: load };"
24256 "}"
24257 "var buffer = new ArrayBuffer(4);"
Ben Murdochc5610432016-08-08 18:44:38 +010024258 "var module = Module(this, {}, buffer);"
24259 "%OptimizeFunctionOnNextCall(module.load);"
24260 "module.load();"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024261 "buffer";
24262
24263 v8::Local<v8::ArrayBuffer> result = CompileRun(load).As<v8::ArrayBuffer>();
24264 CHECK_EQ(should_be_neuterable, result->IsNeuterable());
24265
24266 const char* store =
24267 "function Module(stdlib, foreign, heap) {"
24268 " 'use asm';"
24269 " var MEM32 = new stdlib.Int32Array(heap);"
24270 " function store() { MEM32[0] = 0; }"
24271 " return { store: store };"
24272 "}"
24273 "var buffer = new ArrayBuffer(4);"
Ben Murdochc5610432016-08-08 18:44:38 +010024274 "var module = Module(this, {}, buffer);"
24275 "%OptimizeFunctionOnNextCall(module.store);"
24276 "module.store();"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024277 "buffer";
24278
24279 result = CompileRun(store).As<v8::ArrayBuffer>();
24280 CHECK_EQ(should_be_neuterable, result->IsNeuterable());
24281}
24282
24283
24284TEST(GetPrototypeAccessControl) {
24285 i::FLAG_allow_natives_syntax = true;
24286 v8::Isolate* isolate = CcTest::isolate();
24287 v8::HandleScope handle_scope(isolate);
24288 LocalContext env;
24289
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024290 v8::Local<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New(isolate);
24291 obj_template->SetAccessCheckCallback(AccessAlwaysBlocked);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024292
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024293 CHECK(env->Global()
24294 ->Set(env.local(), v8_str("prohibited"),
24295 obj_template->NewInstance(env.local()).ToLocalChecked())
24296 .FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024297
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024298 CHECK(CompileRun(
24299 "function f() { return %_GetPrototype(prohibited); }"
24300 "%OptimizeFunctionOnNextCall(f);"
24301 "f();")->IsNull());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024302}
24303
24304
24305TEST(GetPrototypeHidden) {
24306 i::FLAG_allow_natives_syntax = true;
24307 v8::Isolate* isolate = CcTest::isolate();
24308 v8::HandleScope handle_scope(isolate);
24309 LocalContext env;
24310
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024311 Local<FunctionTemplate> t = FunctionTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024312 t->SetHiddenPrototype(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024313 Local<Object> proto = t->GetFunction(env.local())
24314 .ToLocalChecked()
24315 ->NewInstance(env.local())
24316 .ToLocalChecked();
24317 Local<Object> object = Object::New(isolate);
24318 Local<Object> proto2 = Object::New(isolate);
24319 object->SetPrototype(env.local(), proto).FromJust();
24320 proto->SetPrototype(env.local(), proto2).FromJust();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024321
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024322 CHECK(env->Global()->Set(env.local(), v8_str("object"), object).FromJust());
24323 CHECK(env->Global()->Set(env.local(), v8_str("proto"), proto).FromJust());
24324 CHECK(env->Global()->Set(env.local(), v8_str("proto2"), proto2).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024325
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024326 v8::Local<v8::Value> result = CompileRun("%_GetPrototype(object)");
24327 CHECK(result->Equals(env.local(), proto2).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024328
24329 result = CompileRun(
24330 "function f() { return %_GetPrototype(object); }"
24331 "%OptimizeFunctionOnNextCall(f);"
24332 "f()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024333 CHECK(result->Equals(env.local(), proto2).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024334}
24335
24336
24337TEST(ClassPrototypeCreationContext) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024338 v8::Isolate* isolate = CcTest::isolate();
24339 v8::HandleScope handle_scope(isolate);
24340 LocalContext env;
24341
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024342 Local<Object> result = Local<Object>::Cast(
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024343 CompileRun("'use strict'; class Example { }; Example.prototype"));
24344 CHECK(env.local() == result->CreationContext());
24345}
24346
24347
24348TEST(SimpleStreamingScriptWithSourceURL) {
24349 const char* chunks[] = {"function foo() { ret", "urn 13; } f", "oo();\n",
24350 "//# sourceURL=bar2.js\n", NULL};
24351 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, true,
24352 "bar2.js");
24353}
24354
24355
24356TEST(StreamingScriptWithSplitSourceURL) {
24357 const char* chunks[] = {"function foo() { ret", "urn 13; } f",
24358 "oo();\n//# sourceURL=b", "ar2.js\n", NULL};
24359 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, true,
24360 "bar2.js");
24361}
24362
24363
24364TEST(StreamingScriptWithSourceMappingURLInTheMiddle) {
24365 const char* chunks[] = {"function foo() { ret", "urn 13; }\n//#",
24366 " sourceMappingURL=bar2.js\n", "foo();", NULL};
24367 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, true, NULL,
24368 "bar2.js");
24369}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024370
24371
24372TEST(NewStringRangeError) {
24373 v8::Isolate* isolate = CcTest::isolate();
24374 v8::HandleScope handle_scope(isolate);
24375 const int length = i::String::kMaxLength + 1;
24376 const int buffer_size = length * sizeof(uint16_t);
24377 void* buffer = malloc(buffer_size);
24378 if (buffer == NULL) return;
24379 memset(buffer, 'A', buffer_size);
24380 {
24381 v8::TryCatch try_catch(isolate);
24382 char* data = reinterpret_cast<char*>(buffer);
24383 CHECK(v8::String::NewFromUtf8(isolate, data, v8::NewStringType::kNormal,
24384 length)
24385 .IsEmpty());
24386 CHECK(!try_catch.HasCaught());
24387 }
24388 {
24389 v8::TryCatch try_catch(isolate);
24390 uint8_t* data = reinterpret_cast<uint8_t*>(buffer);
24391 CHECK(v8::String::NewFromOneByte(isolate, data, v8::NewStringType::kNormal,
24392 length)
24393 .IsEmpty());
24394 CHECK(!try_catch.HasCaught());
24395 }
24396 {
24397 v8::TryCatch try_catch(isolate);
24398 uint16_t* data = reinterpret_cast<uint16_t*>(buffer);
24399 CHECK(v8::String::NewFromTwoByte(isolate, data, v8::NewStringType::kNormal,
24400 length)
24401 .IsEmpty());
24402 CHECK(!try_catch.HasCaught());
24403 }
24404 free(buffer);
24405}
24406
24407
24408TEST(SealHandleScope) {
24409 v8::Isolate* isolate = CcTest::isolate();
24410 v8::HandleScope handle_scope(isolate);
24411 LocalContext env;
24412
24413 v8::SealHandleScope seal(isolate);
24414
24415 // Should fail
24416 v8::Local<v8::Object> obj = v8::Object::New(isolate);
24417
24418 USE(obj);
24419}
24420
24421
24422TEST(SealHandleScopeNested) {
24423 v8::Isolate* isolate = CcTest::isolate();
24424 v8::HandleScope handle_scope(isolate);
24425 LocalContext env;
24426
24427 v8::SealHandleScope seal(isolate);
24428
24429 {
24430 v8::HandleScope handle_scope(isolate);
24431
24432 // Should work
24433 v8::Local<v8::Object> obj = v8::Object::New(isolate);
24434
24435 USE(obj);
24436 }
24437}
24438
24439
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024440static void ExtrasBindingTestRuntimeFunction(
24441 const v8::FunctionCallbackInfo<v8::Value>& args) {
24442 CHECK_EQ(
24443 3,
24444 args[0]->Int32Value(args.GetIsolate()->GetCurrentContext()).FromJust());
24445 args.GetReturnValue().Set(v8_num(7));
24446}
24447
Ben Murdoch097c5b22016-05-18 11:27:45 +010024448TEST(ExtrasFunctionSource) {
24449 v8::Isolate* isolate = CcTest::isolate();
24450 v8::HandleScope handle_scope(isolate);
24451 LocalContext env;
24452
24453 v8::Local<v8::Object> binding = env->GetExtrasBindingObject();
24454
24455 // Functions defined in extras do not expose source code.
24456 auto func = binding->Get(env.local(), v8_str("testFunctionToString"))
24457 .ToLocalChecked()
24458 .As<v8::Function>();
24459 auto undefined = v8::Undefined(isolate);
24460 auto result = func->Call(env.local(), undefined, 0, {})
24461 .ToLocalChecked()
24462 .As<v8::String>();
24463 CHECK(result->StrictEquals(v8_str("function foo() { [native code] }")));
24464
24465 // Functions defined in extras do not show up in the stack trace.
24466 auto wrapper = binding->Get(env.local(), v8_str("testStackTrace"))
24467 .ToLocalChecked()
24468 .As<v8::Function>();
24469 CHECK(env->Global()->Set(env.local(), v8_str("wrapper"), wrapper).FromJust());
24470 ExpectString(
24471 "function f(x) { return wrapper(x) }"
24472 "function g() { return new Error().stack; }"
24473 "f(g)",
24474 "Error\n"
24475 " at g (<anonymous>:1:58)\n"
24476 " at f (<anonymous>:1:24)\n"
24477 " at <anonymous>:1:78");
24478}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024479
24480TEST(ExtrasBindingObject) {
24481 v8::Isolate* isolate = CcTest::isolate();
24482 v8::HandleScope handle_scope(isolate);
24483 LocalContext env;
24484
24485 // standalone.gypi ensures we include the test-extra.js file, which should
24486 // export the tested functions.
24487 v8::Local<v8::Object> binding = env->GetExtrasBindingObject();
24488
24489 auto func = binding->Get(env.local(), v8_str("testExtraShouldReturnFive"))
24490 .ToLocalChecked()
24491 .As<v8::Function>();
24492 auto undefined = v8::Undefined(isolate);
24493 auto result = func->Call(env.local(), undefined, 0, {})
24494 .ToLocalChecked()
24495 .As<v8::Number>();
24496 CHECK_EQ(5, result->Int32Value(env.local()).FromJust());
24497
24498 v8::Local<v8::FunctionTemplate> runtimeFunction =
24499 v8::FunctionTemplate::New(isolate, ExtrasBindingTestRuntimeFunction);
24500 binding->Set(env.local(), v8_str("runtime"),
24501 runtimeFunction->GetFunction(env.local()).ToLocalChecked())
24502 .FromJust();
24503 func = binding->Get(env.local(), v8_str("testExtraShouldCallToRuntime"))
24504 .ToLocalChecked()
24505 .As<v8::Function>();
24506 result = func->Call(env.local(), undefined, 0, {})
24507 .ToLocalChecked()
24508 .As<v8::Number>();
24509 CHECK_EQ(7, result->Int32Value(env.local()).FromJust());
24510}
24511
24512
24513TEST(ExperimentalExtras) {
24514 i::FLAG_experimental_extras = true;
24515
24516 v8::Isolate* isolate = CcTest::isolate();
24517 v8::HandleScope handle_scope(isolate);
24518 LocalContext env;
24519
24520 // standalone.gypi ensures we include the test-experimental-extra.js file,
24521 // which should export the tested functions.
24522 v8::Local<v8::Object> binding = env->GetExtrasBindingObject();
24523
24524 auto func =
24525 binding->Get(env.local(), v8_str("testExperimentalExtraShouldReturnTen"))
24526 .ToLocalChecked()
24527 .As<v8::Function>();
24528 auto undefined = v8::Undefined(isolate);
24529 auto result = func->Call(env.local(), undefined, 0, {})
24530 .ToLocalChecked()
24531 .As<v8::Number>();
24532 CHECK_EQ(10, result->Int32Value(env.local()).FromJust());
24533
24534 v8::Local<v8::FunctionTemplate> runtimeFunction =
24535 v8::FunctionTemplate::New(isolate, ExtrasBindingTestRuntimeFunction);
24536 binding->Set(env.local(), v8_str("runtime"),
24537 runtimeFunction->GetFunction(env.local()).ToLocalChecked())
24538 .FromJust();
24539 func = binding->Get(env.local(),
24540 v8_str("testExperimentalExtraShouldCallToRuntime"))
24541 .ToLocalChecked()
24542 .As<v8::Function>();
24543 result = func->Call(env.local(), undefined, 0, {})
24544 .ToLocalChecked()
24545 .As<v8::Number>();
24546 CHECK_EQ(7, result->Int32Value(env.local()).FromJust());
24547}
24548
24549
24550TEST(ExtrasUtilsObject) {
24551 LocalContext context;
24552 v8::Isolate* isolate = context->GetIsolate();
24553 v8::HandleScope handle_scope(isolate);
24554
24555 LocalContext env;
24556 v8::Local<v8::Object> binding = env->GetExtrasBindingObject();
24557
24558 auto func = binding->Get(env.local(), v8_str("testExtraCanUseUtils"))
24559 .ToLocalChecked()
24560 .As<v8::Function>();
24561 auto undefined = v8::Undefined(isolate);
24562 auto result = func->Call(env.local(), undefined, 0, {})
24563 .ToLocalChecked()
24564 .As<v8::Object>();
24565
24566 auto private_symbol = result->Get(env.local(), v8_str("privateSymbol"))
24567 .ToLocalChecked()
24568 .As<v8::Symbol>();
24569 i::Handle<i::Symbol> ips = v8::Utils::OpenHandle(*private_symbol);
24570 CHECK_EQ(true, ips->IsPrivate());
24571
24572 CompileRun("var result = 0; function store(x) { result = x; }");
24573 auto store = CompileRun("store").As<v8::Function>();
24574
24575 auto fulfilled_promise = result->Get(env.local(), v8_str("fulfilledPromise"))
24576 .ToLocalChecked()
24577 .As<v8::Promise>();
24578 fulfilled_promise->Then(env.local(), store).ToLocalChecked();
24579 isolate->RunMicrotasks();
24580 CHECK_EQ(1, CompileRun("result")->Int32Value(env.local()).FromJust());
24581
24582 auto fulfilled_promise_2 =
24583 result->Get(env.local(), v8_str("fulfilledPromise2"))
24584 .ToLocalChecked()
24585 .As<v8::Promise>();
24586 fulfilled_promise_2->Then(env.local(), store).ToLocalChecked();
24587 isolate->RunMicrotasks();
24588 CHECK_EQ(2, CompileRun("result")->Int32Value(env.local()).FromJust());
24589
24590 auto rejected_promise = result->Get(env.local(), v8_str("rejectedPromise"))
24591 .ToLocalChecked()
24592 .As<v8::Promise>();
24593 rejected_promise->Catch(env.local(), store).ToLocalChecked();
24594 isolate->RunMicrotasks();
24595 CHECK_EQ(3, CompileRun("result")->Int32Value(env.local()).FromJust());
24596}
24597
24598
24599TEST(Map) {
24600 v8::Isolate* isolate = CcTest::isolate();
24601 v8::HandleScope handle_scope(isolate);
24602 LocalContext env;
24603
24604 v8::Local<v8::Map> map = v8::Map::New(isolate);
24605 CHECK(map->IsObject());
24606 CHECK(map->IsMap());
24607 CHECK(map->GetPrototype()->StrictEquals(CompileRun("Map.prototype")));
24608 CHECK_EQ(0U, map->Size());
24609
24610 v8::Local<v8::Value> val = CompileRun("new Map([[1, 2], [3, 4]])");
24611 CHECK(val->IsMap());
24612 map = v8::Local<v8::Map>::Cast(val);
24613 CHECK_EQ(2U, map->Size());
24614
24615 v8::Local<v8::Array> contents = map->AsArray();
24616 CHECK_EQ(4U, contents->Length());
24617 CHECK_EQ(
24618 1,
24619 contents->Get(env.local(), 0).ToLocalChecked().As<v8::Int32>()->Value());
24620 CHECK_EQ(
24621 2,
24622 contents->Get(env.local(), 1).ToLocalChecked().As<v8::Int32>()->Value());
24623 CHECK_EQ(
24624 3,
24625 contents->Get(env.local(), 2).ToLocalChecked().As<v8::Int32>()->Value());
24626 CHECK_EQ(
24627 4,
24628 contents->Get(env.local(), 3).ToLocalChecked().As<v8::Int32>()->Value());
24629
24630 CHECK_EQ(2U, map->Size());
24631
24632 CHECK(map->Has(env.local(), v8::Integer::New(isolate, 1)).FromJust());
24633 CHECK(map->Has(env.local(), v8::Integer::New(isolate, 3)).FromJust());
24634
24635 CHECK(!map->Has(env.local(), v8::Integer::New(isolate, 2)).FromJust());
24636 CHECK(!map->Has(env.local(), map).FromJust());
24637
24638 CHECK_EQ(2, map->Get(env.local(), v8::Integer::New(isolate, 1))
24639 .ToLocalChecked()
24640 ->Int32Value(env.local())
24641 .FromJust());
24642 CHECK_EQ(4, map->Get(env.local(), v8::Integer::New(isolate, 3))
24643 .ToLocalChecked()
24644 ->Int32Value(env.local())
24645 .FromJust());
24646
24647 CHECK(map->Get(env.local(), v8::Integer::New(isolate, 42))
24648 .ToLocalChecked()
24649 ->IsUndefined());
24650
24651 CHECK(!map->Set(env.local(), map, map).IsEmpty());
24652 CHECK_EQ(3U, map->Size());
24653 CHECK(map->Has(env.local(), map).FromJust());
24654
24655 CHECK(map->Delete(env.local(), map).FromJust());
24656 CHECK_EQ(2U, map->Size());
24657 CHECK(!map->Has(env.local(), map).FromJust());
24658 CHECK(!map->Delete(env.local(), map).FromJust());
24659
24660 map->Clear();
24661 CHECK_EQ(0U, map->Size());
24662}
24663
24664
24665TEST(Set) {
24666 v8::Isolate* isolate = CcTest::isolate();
24667 v8::HandleScope handle_scope(isolate);
24668 LocalContext env;
24669
24670 v8::Local<v8::Set> set = v8::Set::New(isolate);
24671 CHECK(set->IsObject());
24672 CHECK(set->IsSet());
24673 CHECK(set->GetPrototype()->StrictEquals(CompileRun("Set.prototype")));
24674 CHECK_EQ(0U, set->Size());
24675
24676 v8::Local<v8::Value> val = CompileRun("new Set([1, 2])");
24677 CHECK(val->IsSet());
24678 set = v8::Local<v8::Set>::Cast(val);
24679 CHECK_EQ(2U, set->Size());
24680
24681 v8::Local<v8::Array> keys = set->AsArray();
24682 CHECK_EQ(2U, keys->Length());
24683 CHECK_EQ(1,
24684 keys->Get(env.local(), 0).ToLocalChecked().As<v8::Int32>()->Value());
24685 CHECK_EQ(2,
24686 keys->Get(env.local(), 1).ToLocalChecked().As<v8::Int32>()->Value());
24687
24688 CHECK_EQ(2U, set->Size());
24689
24690 CHECK(set->Has(env.local(), v8::Integer::New(isolate, 1)).FromJust());
24691 CHECK(set->Has(env.local(), v8::Integer::New(isolate, 2)).FromJust());
24692
24693 CHECK(!set->Has(env.local(), v8::Integer::New(isolate, 3)).FromJust());
24694 CHECK(!set->Has(env.local(), set).FromJust());
24695
24696 CHECK(!set->Add(env.local(), set).IsEmpty());
24697 CHECK_EQ(3U, set->Size());
24698 CHECK(set->Has(env.local(), set).FromJust());
24699
24700 CHECK(set->Delete(env.local(), set).FromJust());
24701 CHECK_EQ(2U, set->Size());
24702 CHECK(!set->Has(env.local(), set).FromJust());
24703 CHECK(!set->Delete(env.local(), set).FromJust());
24704
24705 set->Clear();
24706 CHECK_EQ(0U, set->Size());
24707}
24708
Ben Murdochc5610432016-08-08 18:44:38 +010024709TEST(SetDeleteThenAsArray) {
24710 // https://bugs.chromium.org/p/v8/issues/detail?id=4946
24711 v8::Isolate* isolate = CcTest::isolate();
24712 v8::HandleScope handle_scope(isolate);
24713 LocalContext env;
24714
24715 // make a Set
24716 v8::Local<v8::Value> val = CompileRun("new Set([1, 2, 3])");
24717 v8::Local<v8::Set> set = v8::Local<v8::Set>::Cast(val);
24718 CHECK_EQ(3U, set->Size());
24719
24720 // delete the "middle" element (using AsArray to
24721 // determine which element is the "middle" element)
24722 v8::Local<v8::Array> array1 = set->AsArray();
24723 CHECK_EQ(3U, array1->Length());
24724 CHECK(set->Delete(env.local(), array1->Get(env.local(), 1).ToLocalChecked())
24725 .FromJust());
24726
24727 // make sure there are no undefined values when we convert to an array again.
24728 v8::Local<v8::Array> array2 = set->AsArray();
24729 uint32_t length = array2->Length();
24730 CHECK_EQ(2U, length);
24731 for (uint32_t i = 0; i < length; i++) {
24732 CHECK(!array2->Get(env.local(), i).ToLocalChecked()->IsUndefined());
24733 }
24734}
24735
24736TEST(MapDeleteThenAsArray) {
24737 // https://bugs.chromium.org/p/v8/issues/detail?id=4946
24738 v8::Isolate* isolate = CcTest::isolate();
24739 v8::HandleScope handle_scope(isolate);
24740 LocalContext env;
24741
24742 // make a Map
24743 v8::Local<v8::Value> val = CompileRun("new Map([[1, 2], [3, 4], [5, 6]])");
24744 v8::Local<v8::Map> map = v8::Local<v8::Map>::Cast(val);
24745 CHECK_EQ(3U, map->Size());
24746
24747 // delete the "middle" element (using AsArray to
24748 // determine which element is the "middle" element)
24749 v8::Local<v8::Array> array1 = map->AsArray();
24750 CHECK_EQ(6U, array1->Length());
24751 // Map::AsArray returns a flat array, so the second key is at index 2.
24752 v8::Local<v8::Value> key = array1->Get(env.local(), 2).ToLocalChecked();
24753 CHECK(map->Delete(env.local(), key).FromJust());
24754
24755 // make sure there are no undefined values when we convert to an array again.
24756 v8::Local<v8::Array> array2 = map->AsArray();
24757 uint32_t length = array2->Length();
24758 CHECK_EQ(4U, length);
24759 for (uint32_t i = 0; i < length; i++) {
24760 CHECK(!array2->Get(env.local(), i).ToLocalChecked()->IsUndefined());
24761 }
24762}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024763
24764TEST(CompatibleReceiverCheckOnCachedICHandler) {
24765 v8::Isolate* isolate = CcTest::isolate();
24766 v8::HandleScope scope(isolate);
24767 v8::Local<v8::FunctionTemplate> parent = FunctionTemplate::New(isolate);
24768 v8::Local<v8::Signature> signature = v8::Signature::New(isolate, parent);
24769 auto returns_42 =
24770 v8::FunctionTemplate::New(isolate, Returns42, Local<Value>(), signature);
24771 parent->PrototypeTemplate()->SetAccessorProperty(v8_str("age"), returns_42);
24772 v8::Local<v8::FunctionTemplate> child = v8::FunctionTemplate::New(isolate);
24773 child->Inherit(parent);
24774 LocalContext env;
24775 CHECK(env->Global()
24776 ->Set(env.local(), v8_str("Child"),
24777 child->GetFunction(env.local()).ToLocalChecked())
24778 .FromJust());
24779
24780 // Make sure there's a compiled stub for "Child.prototype.age" in the cache.
24781 CompileRun(
24782 "var real = new Child();\n"
24783 "for (var i = 0; i < 3; ++i) {\n"
24784 " real.age;\n"
24785 "}\n");
24786
24787 // Check that the cached stub is never used.
24788 ExpectInt32(
24789 "var fake = Object.create(Child.prototype);\n"
24790 "var result = 0;\n"
24791 "function test(d) {\n"
24792 " if (d == 3) return;\n"
24793 " try {\n"
24794 " fake.age;\n"
24795 " result = 1;\n"
24796 " } catch (e) {\n"
24797 " }\n"
24798 " test(d+1);\n"
24799 "}\n"
24800 "test(0);\n"
24801 "result;\n",
24802 0);
24803}
24804
Ben Murdochda12d292016-06-02 14:46:10 +010024805THREADED_TEST(ReceiverConversionForAccessors) {
24806 LocalContext env;
24807 v8::Isolate* isolate = CcTest::isolate();
24808 v8::HandleScope scope(isolate);
24809 Local<v8::FunctionTemplate> acc =
24810 v8::FunctionTemplate::New(isolate, Returns42);
24811 CHECK(env->Global()
24812 ->Set(env.local(), v8_str("acc"),
24813 acc->GetFunction(env.local()).ToLocalChecked())
24814 .FromJust());
24815
24816 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
24817 templ->SetAccessorProperty(v8_str("acc"), acc, acc);
24818 Local<v8::Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
24819
24820 CHECK(env->Global()->Set(env.local(), v8_str("p"), instance).FromJust());
24821 CHECK(CompileRun("(p.acc == 42)")->BooleanValue(env.local()).FromJust());
24822 CHECK(CompileRun("(p.acc = 7) == 7")->BooleanValue(env.local()).FromJust());
24823
24824 CHECK(!CompileRun("Number.prototype.__proto__ = p;"
24825 "var a = 1;")
24826 .IsEmpty());
24827 CHECK(CompileRun("(a.acc == 42)")->BooleanValue(env.local()).FromJust());
24828 CHECK(CompileRun("(a.acc = 7) == 7")->BooleanValue(env.local()).FromJust());
24829
24830 CHECK(!CompileRun("Boolean.prototype.__proto__ = p;"
24831 "var a = true;")
24832 .IsEmpty());
24833 CHECK(CompileRun("(a.acc == 42)")->BooleanValue(env.local()).FromJust());
24834 CHECK(CompileRun("(a.acc = 7) == 7")->BooleanValue(env.local()).FromJust());
24835
24836 CHECK(!CompileRun("String.prototype.__proto__ = p;"
24837 "var a = 'foo';")
24838 .IsEmpty());
24839 CHECK(CompileRun("(a.acc == 42)")->BooleanValue(env.local()).FromJust());
24840 CHECK(CompileRun("(a.acc = 7) == 7")->BooleanValue(env.local()).FromJust());
24841
24842 CHECK(CompileRun("acc.call(1) == 42")->BooleanValue(env.local()).FromJust());
24843 CHECK(CompileRun("acc.call(true)==42")->BooleanValue(env.local()).FromJust());
24844 CHECK(CompileRun("acc.call('aa')==42")->BooleanValue(env.local()).FromJust());
24845 CHECK(
24846 CompileRun("acc.call(null) == 42")->BooleanValue(env.local()).FromJust());
24847 CHECK(CompileRun("acc.call(undefined) == 42")
24848 ->BooleanValue(env.local())
24849 .FromJust());
24850}
24851
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024852class FutexInterruptionThread : public v8::base::Thread {
24853 public:
24854 explicit FutexInterruptionThread(v8::Isolate* isolate)
24855 : Thread(Options("FutexInterruptionThread")), isolate_(isolate) {}
24856
24857 virtual void Run() {
24858 // Wait a bit before terminating.
24859 v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(100));
24860 isolate_->TerminateExecution();
24861 }
24862
24863 private:
24864 v8::Isolate* isolate_;
24865};
24866
24867
24868TEST(FutexInterruption) {
24869 i::FLAG_harmony_sharedarraybuffer = true;
24870 v8::Isolate* isolate = CcTest::isolate();
24871 v8::HandleScope scope(isolate);
24872 LocalContext env;
24873
24874 FutexInterruptionThread timeout_thread(isolate);
24875
24876 v8::TryCatch try_catch(CcTest::isolate());
24877 timeout_thread.Start();
24878
24879 CompileRun(
24880 "var ab = new SharedArrayBuffer(4);"
24881 "var i32a = new Int32Array(ab);"
24882 "Atomics.futexWait(i32a, 0, 0);");
24883 CHECK(try_catch.HasTerminated());
24884 timeout_thread.Join();
24885}
24886
24887
24888TEST(EstimatedContextSize) {
24889 v8::Isolate* isolate = CcTest::isolate();
24890 v8::HandleScope scope(isolate);
24891 LocalContext env;
24892 CHECK(50000 < env->EstimatedSize());
24893}
24894
24895
24896static int nb_uncaught_exception_callback_calls = 0;
24897
24898
24899bool NoAbortOnUncaughtException(v8::Isolate* isolate) {
24900 ++nb_uncaught_exception_callback_calls;
24901 return false;
24902}
24903
24904
24905TEST(AbortOnUncaughtExceptionNoAbort) {
24906 v8::Isolate* isolate = CcTest::isolate();
24907 v8::HandleScope handle_scope(isolate);
24908 v8::Local<v8::ObjectTemplate> global_template =
24909 v8::ObjectTemplate::New(isolate);
24910 LocalContext env(NULL, global_template);
24911
24912 i::FLAG_abort_on_uncaught_exception = true;
24913 isolate->SetAbortOnUncaughtExceptionCallback(NoAbortOnUncaughtException);
24914
24915 CompileRun("function boom() { throw new Error(\"boom\") }");
24916
24917 v8::Local<v8::Object> global_object = env->Global();
24918 v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
24919 global_object->Get(env.local(), v8_str("boom")).ToLocalChecked());
24920
24921 CHECK(foo->Call(env.local(), global_object, 0, NULL).IsEmpty());
24922
24923 CHECK_EQ(1, nb_uncaught_exception_callback_calls);
24924}
24925
24926
24927TEST(AccessCheckedIsConcatSpreadable) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024928 v8::Isolate* isolate = CcTest::isolate();
24929 HandleScope scope(isolate);
24930 LocalContext env;
24931
24932 // Object with access check
24933 Local<ObjectTemplate> spreadable_template = v8::ObjectTemplate::New(isolate);
24934 spreadable_template->SetAccessCheckCallback(AccessBlocker);
24935 spreadable_template->Set(v8::Symbol::GetIsConcatSpreadable(isolate),
24936 v8::Boolean::New(isolate, true));
24937 Local<Object> object =
24938 spreadable_template->NewInstance(env.local()).ToLocalChecked();
24939
24940 allowed_access = true;
24941 CHECK(env->Global()->Set(env.local(), v8_str("object"), object).FromJust());
24942 object->Set(env.local(), v8_str("length"), v8_num(2)).FromJust();
24943 object->Set(env.local(), 0U, v8_str("a")).FromJust();
24944 object->Set(env.local(), 1U, v8_str("b")).FromJust();
24945
24946 // Access check is allowed, and the object is spread
24947 CompileRun("var result = [].concat(object)");
24948 ExpectTrue("Array.isArray(result)");
24949 ExpectString("result[0]", "a");
24950 ExpectString("result[1]", "b");
24951 ExpectTrue("result.length === 2");
24952 ExpectTrue("object[Symbol.isConcatSpreadable]");
24953
24954 // If access check fails, the value of @@isConcatSpreadable is ignored
24955 allowed_access = false;
24956 CompileRun("var result = [].concat(object)");
24957 ExpectTrue("Array.isArray(result)");
24958 ExpectTrue("result[0] === object");
24959 ExpectTrue("result.length === 1");
24960 ExpectTrue("object[Symbol.isConcatSpreadable] === undefined");
24961}
24962
24963
24964TEST(AccessCheckedToStringTag) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024965 v8::Isolate* isolate = CcTest::isolate();
24966 HandleScope scope(isolate);
24967 LocalContext env;
24968
24969 // Object with access check
24970 Local<ObjectTemplate> object_template = v8::ObjectTemplate::New(isolate);
24971 object_template->SetAccessCheckCallback(AccessBlocker);
24972 Local<Object> object =
24973 object_template->NewInstance(env.local()).ToLocalChecked();
24974
24975 allowed_access = true;
24976 env->Global()->Set(env.local(), v8_str("object"), object).FromJust();
24977 object->Set(env.local(), v8::Symbol::GetToStringTag(isolate), v8_str("hello"))
24978 .FromJust();
24979
24980 // Access check is allowed, and the toStringTag is read
24981 CompileRun("var result = Object.prototype.toString.call(object)");
24982 ExpectString("result", "[object hello]");
24983 ExpectString("object[Symbol.toStringTag]", "hello");
24984
24985 // ToString through the API should succeed too.
24986 String::Utf8Value result_allowed(
24987 object->ObjectProtoToString(env.local()).ToLocalChecked());
24988 CHECK_EQ(0, strcmp(*result_allowed, "[object hello]"));
24989
24990 // If access check fails, the value of @@toStringTag is ignored
24991 allowed_access = false;
24992 CompileRun("var result = Object.prototype.toString.call(object)");
24993 ExpectString("result", "[object Object]");
24994 ExpectTrue("object[Symbol.toStringTag] === undefined");
24995
24996 // ToString through the API should also fail.
24997 String::Utf8Value result_denied(
24998 object->ObjectProtoToString(env.local()).ToLocalChecked());
24999 CHECK_EQ(0, strcmp(*result_denied, "[object Object]"));
25000}
25001
25002
25003TEST(ObjectTemplateIntrinsics) {
25004 v8::Isolate* isolate = CcTest::isolate();
25005 v8::HandleScope scope(isolate);
25006 LocalContext env;
25007
25008 Local<ObjectTemplate> object_template = v8::ObjectTemplate::New(isolate);
25009 object_template->SetIntrinsicDataProperty(v8_str("values"),
25010 v8::kArrayProto_values);
25011 Local<Object> object =
25012 object_template->NewInstance(env.local()).ToLocalChecked();
25013
25014 CHECK(env->Global()->Set(env.local(), v8_str("obj1"), object).FromJust());
25015 ExpectString("typeof obj1.values", "function");
25016
25017 auto values = Local<Function>::Cast(
25018 object->Get(env.local(), v8_str("values")).ToLocalChecked());
25019 auto fn = i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(*values));
25020 auto ctx = v8::Utils::OpenHandle(*env.local());
25021 CHECK_EQ(fn->GetCreationContext(), *ctx);
25022
25023 {
25024 LocalContext env2;
25025 Local<Object> object2 =
25026 object_template->NewInstance(env2.local()).ToLocalChecked();
25027 CHECK(
25028 env2->Global()->Set(env2.local(), v8_str("obj2"), object2).FromJust());
25029 ExpectString("typeof obj2.values", "function");
25030 CHECK_NE(*object->Get(env2.local(), v8_str("values")).ToLocalChecked(),
25031 *object2->Get(env2.local(), v8_str("values")).ToLocalChecked());
25032
25033 auto values2 = Local<Function>::Cast(
25034 object2->Get(env2.local(), v8_str("values")).ToLocalChecked());
25035 auto fn2 = i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(*values2));
25036 auto ctx2 = v8::Utils::OpenHandle(*env2.local());
25037 CHECK_EQ(fn2->GetCreationContext(), *ctx2);
25038 }
25039}
25040
25041
25042TEST(Proxy) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000025043 LocalContext context;
25044 v8::Isolate* isolate = CcTest::isolate();
25045 v8::HandleScope scope(isolate);
25046 v8::Local<v8::Object> target = CompileRun("({})").As<v8::Object>();
25047 v8::Local<v8::Object> handler = CompileRun("({})").As<v8::Object>();
25048
25049 v8::Local<v8::Proxy> proxy =
25050 v8::Proxy::New(context.local(), target, handler).ToLocalChecked();
25051 CHECK(proxy->IsProxy());
25052 CHECK(!target->IsProxy());
25053 CHECK(!proxy->IsRevoked());
25054 CHECK(proxy->GetTarget()->SameValue(target));
25055 CHECK(proxy->GetHandler()->SameValue(handler));
25056
25057 proxy->Revoke();
25058 CHECK(proxy->IsProxy());
25059 CHECK(!target->IsProxy());
25060 CHECK(proxy->IsRevoked());
25061 CHECK(proxy->GetTarget()->SameValue(target));
25062 CHECK(proxy->GetHandler()->IsNull());
25063}
Ben Murdochda12d292016-06-02 14:46:10 +010025064
25065WeakCallCounterAndPersistent<Value>* CreateGarbageWithWeakCallCounter(
25066 v8::Isolate* isolate, WeakCallCounter* counter) {
25067 v8::Locker locker(isolate);
25068 LocalContext env;
25069 HandleScope scope(isolate);
25070 WeakCallCounterAndPersistent<Value>* val =
25071 new WeakCallCounterAndPersistent<Value>(counter);
25072 val->handle.Reset(isolate, Object::New(isolate));
25073 val->handle.SetWeak(val, &WeakPointerCallback,
25074 v8::WeakCallbackType::kParameter);
25075 return val;
25076}
25077
25078class MemoryPressureThread : public v8::base::Thread {
25079 public:
25080 explicit MemoryPressureThread(v8::Isolate* isolate,
25081 v8::MemoryPressureLevel level)
25082 : Thread(Options("MemoryPressureThread")),
25083 isolate_(isolate),
25084 level_(level) {}
25085
25086 virtual void Run() { isolate_->MemoryPressureNotification(level_); }
25087
25088 private:
25089 v8::Isolate* isolate_;
25090 v8::MemoryPressureLevel level_;
25091};
25092
25093TEST(MemoryPressure) {
25094 v8::Isolate* isolate = CcTest::isolate();
25095 WeakCallCounter counter(1234);
25096
25097 // Check that critical memory pressure notification sets GC interrupt.
25098 auto garbage = CreateGarbageWithWeakCallCounter(isolate, &counter);
25099 CHECK(!v8::Locker::IsLocked(isolate));
25100 {
25101 v8::Locker locker(isolate);
25102 v8::HandleScope scope(isolate);
25103 LocalContext env;
25104 MemoryPressureThread memory_pressure_thread(
25105 isolate, v8::MemoryPressureLevel::kCritical);
25106 memory_pressure_thread.Start();
25107 memory_pressure_thread.Join();
25108 // This should trigger GC.
25109 CHECK_EQ(0, counter.NumberOfWeakCalls());
25110 CompileRun("(function noop() { return 0; })()");
25111 CHECK_EQ(1, counter.NumberOfWeakCalls());
25112 }
25113 delete garbage;
25114 // Check that critical memory pressure notification triggers GC.
25115 garbage = CreateGarbageWithWeakCallCounter(isolate, &counter);
25116 {
25117 v8::Locker locker(isolate);
25118 // If isolate is locked, memory pressure notification should trigger GC.
25119 CHECK_EQ(1, counter.NumberOfWeakCalls());
25120 isolate->MemoryPressureNotification(v8::MemoryPressureLevel::kCritical);
25121 CHECK_EQ(2, counter.NumberOfWeakCalls());
25122 }
25123 delete garbage;
25124 // Check that moderate memory pressure notification sets GC into memory
25125 // optimizing mode.
25126 isolate->MemoryPressureNotification(v8::MemoryPressureLevel::kModerate);
25127 CHECK(CcTest::i_isolate()->heap()->ShouldOptimizeForMemoryUsage());
25128 // Check that disabling memory pressure returns GC into normal mode.
25129 isolate->MemoryPressureNotification(v8::MemoryPressureLevel::kNone);
25130 CHECK(!CcTest::i_isolate()->heap()->ShouldOptimizeForMemoryUsage());
25131}
25132
25133TEST(SetIntegrityLevel) {
25134 LocalContext context;
25135 v8::Isolate* isolate = CcTest::isolate();
25136 v8::HandleScope scope(isolate);
25137
25138 v8::Local<v8::Object> obj = v8::Object::New(isolate);
25139 CHECK(context->Global()->Set(context.local(), v8_str("o"), obj).FromJust());
25140
25141 v8::Local<v8::Value> is_frozen = CompileRun("Object.isFrozen(o)");
25142 CHECK(!is_frozen->BooleanValue(context.local()).FromJust());
25143
25144 CHECK(obj->SetIntegrityLevel(context.local(), v8::IntegrityLevel::kFrozen)
25145 .FromJust());
25146
25147 is_frozen = CompileRun("Object.isFrozen(o)");
25148 CHECK(is_frozen->BooleanValue(context.local()).FromJust());
25149}
25150
25151TEST(PrivateForApiIsNumber) {
25152 LocalContext context;
25153 v8::Isolate* isolate = CcTest::isolate();
25154 v8::HandleScope scope(isolate);
25155
25156 // Shouldn't crash.
25157 v8::Private::ForApi(isolate, v8_str("42"));
25158}