blob: 5624e3fbca635c9b42e6079db6bd25441a3ba3af [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 Murdoch61f157c2016-09-16 13:49:30 +010050#include "src/profiler/cpu-profiler.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000051#include "src/unicode-inl.h"
52#include "src/utils.h"
53#include "src/vm-state.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000054#include "test/cctest/heap/heap-tester.h"
Ben Murdoch61f157c2016-09-16 13:49:30 +010055#include "test/cctest/heap/heap-utils.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000056
Ben Murdoch257744e2011-11-30 15:57:28 +000057static const bool kLogThreading = false;
Steve Blockd0582a62009-12-15 09:54:21 +000058
Ben Murdochb8a8cc12014-11-26 15:28:44 +000059using ::v8::Boolean;
60using ::v8::BooleanObject;
Steve Block44f0eee2011-05-26 01:26:41 +010061using ::v8::Context;
Steve Blocka7e24c12009-10-30 11:49:00 +000062using ::v8::Extension;
Steve Block44f0eee2011-05-26 01:26:41 +010063using ::v8::Function;
Ben Murdoch8b112d22011-06-08 16:22:53 +010064using ::v8::FunctionTemplate;
Steve Block44f0eee2011-05-26 01:26:41 +010065using ::v8::HandleScope;
66using ::v8::Local;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000067using ::v8::Maybe;
Ben Murdoch8b112d22011-06-08 16:22:53 +010068using ::v8::Message;
69using ::v8::MessageCallback;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000070using ::v8::Name;
71using ::v8::None;
Steve Block44f0eee2011-05-26 01:26:41 +010072using ::v8::Object;
73using ::v8::ObjectTemplate;
74using ::v8::Persistent;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000075using ::v8::PropertyAttribute;
Steve Block44f0eee2011-05-26 01:26:41 +010076using ::v8::Script;
Ben Murdoch8b112d22011-06-08 16:22:53 +010077using ::v8::StackTrace;
Steve Block44f0eee2011-05-26 01:26:41 +010078using ::v8::String;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000079using ::v8::Symbol;
Ben Murdoch8b112d22011-06-08 16:22:53 +010080using ::v8::TryCatch;
81using ::v8::Undefined;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000082using ::v8::UniqueId;
Steve Block44f0eee2011-05-26 01:26:41 +010083using ::v8::V8;
Ben Murdoch8b112d22011-06-08 16:22:53 +010084using ::v8::Value;
Steve Blocka7e24c12009-10-30 11:49:00 +000085
Steve Blocka7e24c12009-10-30 11:49:00 +000086
Ben Murdochb8a8cc12014-11-26 15:28:44 +000087#define THREADED_PROFILED_TEST(Name) \
88 static void Test##Name(); \
89 TEST(Name##WithProfiler) { \
90 RunWithProfiler(&Test##Name); \
91 } \
92 THREADED_TEST(Name)
Leon Clarked91b9f72010-01-27 17:25:45 +000093
94
Ben Murdochb8a8cc12014-11-26 15:28:44 +000095void RunWithProfiler(void (*test)()) {
96 LocalContext env;
97 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000098 v8::Local<v8::String> profile_name = v8_str("my_profile1");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000099 v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler();
Leon Clarkef7060e22010-06-03 12:02:55 +0100100
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000101 cpu_profiler->StartProfiling(profile_name);
102 (*test)();
103 reinterpret_cast<i::CpuProfiler*>(cpu_profiler)->DeleteAllProfiles();
Iain Merrick75681382010-08-19 15:07:18 +0100104}
105
106
Steve Blocka7e24c12009-10-30 11:49:00 +0000107static int signature_callback_count;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000108static Local<Value> signature_expected_receiver;
109static void IncrementingSignatureCallback(
110 const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000111 ApiTestFuzzer::Fuzz();
112 signature_callback_count++;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000113 CHECK(signature_expected_receiver->Equals(
114 args.GetIsolate()->GetCurrentContext(),
115 args.Holder())
116 .FromJust());
117 CHECK(signature_expected_receiver->Equals(
118 args.GetIsolate()->GetCurrentContext(),
119 args.This())
120 .FromJust());
121 v8::Local<v8::Array> result =
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000122 v8::Array::New(args.GetIsolate(), args.Length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000123 for (int i = 0; i < args.Length(); i++) {
124 CHECK(result->Set(args.GetIsolate()->GetCurrentContext(),
125 v8::Integer::New(args.GetIsolate(), i), args[i])
126 .FromJust());
127 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000128 args.GetReturnValue().Set(result);
Steve Blocka7e24c12009-10-30 11:49:00 +0000129}
130
131
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000132static void Returns42(const v8::FunctionCallbackInfo<v8::Value>& info) {
133 info.GetReturnValue().Set(42);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000134}
135
136
137// Tests that call v8::V8::Dispose() cannot be threaded.
138UNINITIALIZED_TEST(InitializeAndDisposeOnce) {
139 CHECK(v8::V8::Initialize());
140 CHECK(v8::V8::Dispose());
141}
142
143
144// Tests that call v8::V8::Dispose() cannot be threaded.
145UNINITIALIZED_TEST(InitializeAndDisposeMultiple) {
146 for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
147 for (int i = 0; i < 3; ++i) CHECK(v8::V8::Initialize());
148 for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
149 for (int i = 0; i < 3; ++i) CHECK(v8::V8::Initialize());
150 for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
Steve Blocka7e24c12009-10-30 11:49:00 +0000151}
152
153
154THREADED_TEST(Handles) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000155 v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +0000156 Local<Context> local_env;
157 {
158 LocalContext env;
159 local_env = env.local();
160 }
161
162 // Local context should still be live.
163 CHECK(!local_env.IsEmpty());
164 local_env->Enter();
165
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000166 v8::Local<v8::Primitive> undef = v8::Undefined(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +0000167 CHECK(!undef.IsEmpty());
168 CHECK(undef->IsUndefined());
169
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000170 const char* source = "1 + 2 + 3";
171 Local<Script> script = v8_compile(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000172 CHECK_EQ(6, v8_run_int32value(script));
Steve Blocka7e24c12009-10-30 11:49:00 +0000173
174 local_env->Exit();
175}
176
177
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000178THREADED_TEST(IsolateOfContext) {
179 v8::HandleScope scope(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000180 v8::Local<Context> env = Context::New(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +0000181
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000182 CHECK(!env->GetIsolate()->InContext());
183 CHECK(env->GetIsolate() == CcTest::isolate());
184 env->Enter();
185 CHECK(env->GetIsolate()->InContext());
186 CHECK(env->GetIsolate() == CcTest::isolate());
187 env->Exit();
188 CHECK(!env->GetIsolate()->InContext());
189 CHECK(env->GetIsolate() == CcTest::isolate());
190}
191
192
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400193static void TestSignature(const char* loop_js, Local<Value> receiver,
194 v8::Isolate* isolate) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000195 i::ScopedVector<char> source(200);
196 i::SNPrintF(source,
197 "for (var i = 0; i < 10; i++) {"
198 " %s"
199 "}",
200 loop_js);
201 signature_callback_count = 0;
202 signature_expected_receiver = receiver;
203 bool expected_to_throw = receiver.IsEmpty();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000204 v8::TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000205 CompileRun(source.start());
206 CHECK_EQ(expected_to_throw, try_catch.HasCaught());
207 if (!expected_to_throw) {
208 CHECK_EQ(10, signature_callback_count);
209 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000210 CHECK(v8_str("TypeError: Illegal invocation")
211 ->Equals(isolate->GetCurrentContext(),
212 try_catch.Exception()
213 ->ToString(isolate->GetCurrentContext())
214 .ToLocalChecked())
215 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000216 }
217}
218
219
220THREADED_TEST(ReceiverSignature) {
221 LocalContext env;
222 v8::Isolate* isolate = env->GetIsolate();
223 v8::HandleScope scope(isolate);
224 // Setup templates.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000225 v8::Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(isolate);
226 v8::Local<v8::Signature> sig = v8::Signature::New(isolate, fun);
227 v8::Local<v8::FunctionTemplate> callback_sig = v8::FunctionTemplate::New(
228 isolate, IncrementingSignatureCallback, Local<Value>(), sig);
229 v8::Local<v8::FunctionTemplate> callback =
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000230 v8::FunctionTemplate::New(isolate, IncrementingSignatureCallback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000231 v8::Local<v8::FunctionTemplate> sub_fun = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000232 sub_fun->Inherit(fun);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000233 v8::Local<v8::FunctionTemplate> unrel_fun =
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000234 v8::FunctionTemplate::New(isolate);
235 // Install properties.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000236 v8::Local<v8::ObjectTemplate> fun_proto = fun->PrototypeTemplate();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000237 fun_proto->Set(v8_str("prop_sig"), callback_sig);
238 fun_proto->Set(v8_str("prop"), callback);
239 fun_proto->SetAccessorProperty(
240 v8_str("accessor_sig"), callback_sig, callback_sig);
241 fun_proto->SetAccessorProperty(v8_str("accessor"), callback, callback);
242 // Instantiate templates.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000243 Local<Value> fun_instance =
244 fun->InstanceTemplate()->NewInstance(env.local()).ToLocalChecked();
245 Local<Value> sub_fun_instance =
246 sub_fun->InstanceTemplate()->NewInstance(env.local()).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000247 // Setup global variables.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000248 CHECK(env->Global()
249 ->Set(env.local(), v8_str("Fun"),
250 fun->GetFunction(env.local()).ToLocalChecked())
251 .FromJust());
252 CHECK(env->Global()
253 ->Set(env.local(), v8_str("UnrelFun"),
254 unrel_fun->GetFunction(env.local()).ToLocalChecked())
255 .FromJust());
256 CHECK(env->Global()
257 ->Set(env.local(), v8_str("fun_instance"), fun_instance)
258 .FromJust());
259 CHECK(env->Global()
260 ->Set(env.local(), v8_str("sub_fun_instance"), sub_fun_instance)
261 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +0000262 CompileRun(
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000263 "var accessor_sig_key = 'accessor_sig';"
264 "var accessor_key = 'accessor';"
265 "var prop_sig_key = 'prop_sig';"
266 "var prop_key = 'prop';"
267 ""
268 "function copy_props(obj) {"
269 " var keys = [accessor_sig_key, accessor_key, prop_sig_key, prop_key];"
270 " var source = Fun.prototype;"
271 " for (var i in keys) {"
272 " var key = keys[i];"
273 " var desc = Object.getOwnPropertyDescriptor(source, key);"
274 " Object.defineProperty(obj, key, desc);"
275 " }"
276 "}"
277 ""
278 "var obj = {};"
279 "copy_props(obj);"
280 "var unrel = new UnrelFun();"
281 "copy_props(unrel);");
282 // Test with and without ICs
283 const char* test_objects[] = {
284 "fun_instance", "sub_fun_instance", "obj", "unrel" };
285 unsigned bad_signature_start_offset = 2;
286 for (unsigned i = 0; i < arraysize(test_objects); i++) {
287 i::ScopedVector<char> source(200);
288 i::SNPrintF(
289 source, "var test_object = %s; test_object", test_objects[i]);
290 Local<Value> test_object = CompileRun(source.start());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400291 TestSignature("test_object.prop();", test_object, isolate);
292 TestSignature("test_object.accessor;", test_object, isolate);
293 TestSignature("test_object[accessor_key];", test_object, isolate);
294 TestSignature("test_object.accessor = 1;", test_object, isolate);
295 TestSignature("test_object[accessor_key] = 1;", test_object, isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000296 if (i >= bad_signature_start_offset) test_object = Local<Value>();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400297 TestSignature("test_object.prop_sig();", test_object, isolate);
298 TestSignature("test_object.accessor_sig;", test_object, isolate);
299 TestSignature("test_object[accessor_sig_key];", test_object, isolate);
300 TestSignature("test_object.accessor_sig = 1;", test_object, isolate);
301 TestSignature("test_object[accessor_sig_key] = 1;", test_object, isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000302 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000303}
304
305
Steve Blocka7e24c12009-10-30 11:49:00 +0000306THREADED_TEST(HulIgennem) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000307 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000308 v8::Isolate* isolate = env->GetIsolate();
309 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000310 v8::Local<v8::Primitive> undef = v8::Undefined(isolate);
311 Local<String> undef_str = undef->ToString(env.local()).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000312 char* value = i::NewArray<char>(undef_str->Utf8Length() + 1);
313 undef_str->WriteUtf8(value);
Steve Blocka7e24c12009-10-30 11:49:00 +0000314 CHECK_EQ(0, strcmp(value, "undefined"));
315 i::DeleteArray(value);
316}
317
318
319THREADED_TEST(Access) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000320 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000321 v8::Isolate* isolate = env->GetIsolate();
322 v8::HandleScope scope(isolate);
323 Local<v8::Object> obj = v8::Object::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000324 Local<Value> foo_before =
325 obj->Get(env.local(), v8_str("foo")).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +0000326 CHECK(foo_before->IsUndefined());
327 Local<String> bar_str = v8_str("bar");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000328 CHECK(obj->Set(env.local(), v8_str("foo"), bar_str).FromJust());
329 Local<Value> foo_after =
330 obj->Get(env.local(), v8_str("foo")).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +0000331 CHECK(!foo_after->IsUndefined());
332 CHECK(foo_after->IsString());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000333 CHECK(bar_str->Equals(env.local(), foo_after).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +0000334}
335
336
Steve Block6ded16b2010-05-10 14:33:55 +0100337THREADED_TEST(AccessElement) {
Steve Block6ded16b2010-05-10 14:33:55 +0100338 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000339 v8::HandleScope scope(env->GetIsolate());
340 Local<v8::Object> obj = v8::Object::New(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000341 Local<Value> before = obj->Get(env.local(), 1).ToLocalChecked();
Steve Block6ded16b2010-05-10 14:33:55 +0100342 CHECK(before->IsUndefined());
343 Local<String> bar_str = v8_str("bar");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000344 CHECK(obj->Set(env.local(), 1, bar_str).FromJust());
345 Local<Value> after = obj->Get(env.local(), 1).ToLocalChecked();
Steve Block6ded16b2010-05-10 14:33:55 +0100346 CHECK(!after->IsUndefined());
347 CHECK(after->IsString());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000348 CHECK(bar_str->Equals(env.local(), after).FromJust());
Steve Block6ded16b2010-05-10 14:33:55 +0100349
350 Local<v8::Array> value = CompileRun("[\"a\", \"b\"]").As<v8::Array>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000351 CHECK(v8_str("a")
352 ->Equals(env.local(), value->Get(env.local(), 0).ToLocalChecked())
353 .FromJust());
354 CHECK(v8_str("b")
355 ->Equals(env.local(), value->Get(env.local(), 1).ToLocalChecked())
356 .FromJust());
Steve Block6ded16b2010-05-10 14:33:55 +0100357}
358
359
Steve Blocka7e24c12009-10-30 11:49:00 +0000360THREADED_TEST(Script) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000361 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000362 v8::HandleScope scope(env->GetIsolate());
363 const char* source = "1 + 2 + 3";
364 Local<Script> script = v8_compile(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000365 CHECK_EQ(6, v8_run_int32value(script));
Steve Blocka7e24c12009-10-30 11:49:00 +0000366}
367
368
Steve Blocka7e24c12009-10-30 11:49:00 +0000369class TestResource: public String::ExternalStringResource {
370 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000371 explicit TestResource(uint16_t* data, int* counter = NULL,
372 bool owning_data = true)
373 : data_(data), length_(0), counter_(counter), owning_data_(owning_data) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000374 while (data[length_]) ++length_;
375 }
376
377 ~TestResource() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000378 if (owning_data_) i::DeleteArray(data_);
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000379 if (counter_ != NULL) ++*counter_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000380 }
381
382 const uint16_t* data() const {
383 return data_;
384 }
385
386 size_t length() const {
387 return length_;
388 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000389
Steve Blocka7e24c12009-10-30 11:49:00 +0000390 private:
391 uint16_t* data_;
392 size_t length_;
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000393 int* counter_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000394 bool owning_data_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000395};
396
397
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000398class TestOneByteResource : public String::ExternalOneByteStringResource {
Steve Blocka7e24c12009-10-30 11:49:00 +0000399 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000400 explicit TestOneByteResource(const char* data, int* counter = NULL,
401 size_t offset = 0)
402 : orig_data_(data),
403 data_(data + offset),
404 length_(strlen(data) - offset),
405 counter_(counter) {}
Steve Blocka7e24c12009-10-30 11:49:00 +0000406
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000407 ~TestOneByteResource() {
408 i::DeleteArray(orig_data_);
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000409 if (counter_ != NULL) ++*counter_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000410 }
411
412 const char* data() const {
413 return data_;
414 }
415
416 size_t length() const {
417 return length_;
418 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000419
Steve Blocka7e24c12009-10-30 11:49:00 +0000420 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000421 const char* orig_data_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000422 const char* data_;
423 size_t length_;
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000424 int* counter_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000425};
426
427
Steve Blocka7e24c12009-10-30 11:49:00 +0000428THREADED_TEST(ScriptUsingStringResource) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000429 int dispose_count = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +0000430 const char* c_source = "1 + 2 * 3";
431 uint16_t* two_byte_source = AsciiToTwoByteString(c_source);
432 {
Steve Blocka7e24c12009-10-30 11:49:00 +0000433 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000434 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000435 TestResource* resource = new TestResource(two_byte_source, &dispose_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000436 Local<String> source =
437 String::NewExternalTwoByte(env->GetIsolate(), resource)
438 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000439 Local<Script> script = v8_compile(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000440 Local<Value> value = script->Run(env.local()).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +0000441 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000442 CHECK_EQ(7, value->Int32Value(env.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +0000443 CHECK(source->IsExternal());
444 CHECK_EQ(resource,
445 static_cast<TestResource*>(source->GetExternalStringResource()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000446 String::Encoding encoding = String::UNKNOWN_ENCODING;
447 CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
448 source->GetExternalStringResourceBase(&encoding));
449 CHECK_EQ(String::TWO_BYTE_ENCODING, encoding);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000450 CcTest::heap()->CollectAllGarbage();
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000451 CHECK_EQ(0, dispose_count);
Steve Blocka7e24c12009-10-30 11:49:00 +0000452 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000453 CcTest::i_isolate()->compilation_cache()->Clear();
454 CcTest::heap()->CollectAllAvailableGarbage();
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000455 CHECK_EQ(1, dispose_count);
Steve Blocka7e24c12009-10-30 11:49:00 +0000456}
457
458
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000459THREADED_TEST(ScriptUsingOneByteStringResource) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000460 int dispose_count = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +0000461 const char* c_source = "1 + 2 * 3";
462 {
Steve Blocka7e24c12009-10-30 11:49:00 +0000463 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000464 v8::HandleScope scope(env->GetIsolate());
465 TestOneByteResource* resource =
466 new TestOneByteResource(i::StrDup(c_source), &dispose_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000467 Local<String> source =
468 String::NewExternalOneByte(env->GetIsolate(), resource)
469 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000470 CHECK(source->IsExternalOneByte());
471 CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
472 source->GetExternalOneByteStringResource());
473 String::Encoding encoding = String::UNKNOWN_ENCODING;
474 CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
475 source->GetExternalStringResourceBase(&encoding));
476 CHECK_EQ(String::ONE_BYTE_ENCODING, encoding);
477 Local<Script> script = v8_compile(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000478 Local<Value> value = script->Run(env.local()).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +0000479 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000480 CHECK_EQ(7, value->Int32Value(env.local()).FromJust());
481 CcTest::heap()->CollectAllGarbage();
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000482 CHECK_EQ(0, dispose_count);
Steve Blocka7e24c12009-10-30 11:49:00 +0000483 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000484 CcTest::i_isolate()->compilation_cache()->Clear();
485 CcTest::heap()->CollectAllAvailableGarbage();
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000486 CHECK_EQ(1, dispose_count);
Steve Blocka7e24c12009-10-30 11:49:00 +0000487}
488
489
490THREADED_TEST(ScriptMakingExternalString) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000491 int dispose_count = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +0000492 uint16_t* two_byte_source = AsciiToTwoByteString("1 + 2 * 3");
493 {
Steve Blocka7e24c12009-10-30 11:49:00 +0000494 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000495 v8::HandleScope scope(env->GetIsolate());
496 Local<String> source =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000497 String::NewFromTwoByte(env->GetIsolate(), two_byte_source,
498 v8::NewStringType::kNormal)
499 .ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +0000500 // Trigger GCs so that the newly allocated string moves to old gen.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000501 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
502 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
503 CHECK_EQ(source->IsExternal(), false);
504 CHECK_EQ(source->IsExternalOneByte(), false);
505 String::Encoding encoding = String::UNKNOWN_ENCODING;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000506 CHECK(!source->GetExternalStringResourceBase(&encoding));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000507 CHECK_EQ(String::ONE_BYTE_ENCODING, encoding);
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000508 bool success = source->MakeExternal(new TestResource(two_byte_source,
509 &dispose_count));
Steve Blocka7e24c12009-10-30 11:49:00 +0000510 CHECK(success);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000511 Local<Script> script = v8_compile(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000512 Local<Value> value = script->Run(env.local()).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +0000513 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000514 CHECK_EQ(7, value->Int32Value(env.local()).FromJust());
515 CcTest::heap()->CollectAllGarbage();
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000516 CHECK_EQ(0, dispose_count);
Steve Blocka7e24c12009-10-30 11:49:00 +0000517 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000518 CcTest::i_isolate()->compilation_cache()->Clear();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000519 CcTest::heap()->CollectAllGarbage();
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000520 CHECK_EQ(1, dispose_count);
Steve Blocka7e24c12009-10-30 11:49:00 +0000521}
522
523
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000524THREADED_TEST(ScriptMakingExternalOneByteString) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000525 int dispose_count = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +0000526 const char* c_source = "1 + 2 * 3";
527 {
Steve Blocka7e24c12009-10-30 11:49:00 +0000528 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000529 v8::HandleScope scope(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +0000530 Local<String> source = v8_str(c_source);
Andrei Popescu402d9372010-02-26 13:31:12 +0000531 // Trigger GCs so that the newly allocated string moves to old gen.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000532 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
533 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
Steve Blocka7e24c12009-10-30 11:49:00 +0000534 bool success = source->MakeExternal(
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000535 new TestOneByteResource(i::StrDup(c_source), &dispose_count));
Steve Blocka7e24c12009-10-30 11:49:00 +0000536 CHECK(success);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000537 Local<Script> script = v8_compile(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000538 Local<Value> value = script->Run(env.local()).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +0000539 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000540 CHECK_EQ(7, value->Int32Value(env.local()).FromJust());
541 CcTest::heap()->CollectAllGarbage();
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000542 CHECK_EQ(0, dispose_count);
Steve Blocka7e24c12009-10-30 11:49:00 +0000543 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000544 CcTest::i_isolate()->compilation_cache()->Clear();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000545 CcTest::heap()->CollectAllGarbage();
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000546 CHECK_EQ(1, dispose_count);
Steve Blocka7e24c12009-10-30 11:49:00 +0000547}
548
549
Andrei Popescu402d9372010-02-26 13:31:12 +0000550TEST(MakingExternalStringConditions) {
Andrei Popescu402d9372010-02-26 13:31:12 +0000551 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000552 v8::HandleScope scope(env->GetIsolate());
Andrei Popescu402d9372010-02-26 13:31:12 +0000553
554 // Free some space in the new space so that we can check freshness.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000555 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
556 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
Andrei Popescu402d9372010-02-26 13:31:12 +0000557
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100558 uint16_t* two_byte_string = AsciiToTwoByteString("s1");
Ben Murdoch61f157c2016-09-16 13:49:30 +0100559 Local<String> local_string =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000560 String::NewFromTwoByte(env->GetIsolate(), two_byte_string,
561 v8::NewStringType::kNormal)
562 .ToLocalChecked();
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100563 i::DeleteArray(two_byte_string);
564
Ben Murdoch61f157c2016-09-16 13:49:30 +0100565 // We should refuse to externalize new space strings.
566 CHECK(!local_string->CanMakeExternal());
Andrei Popescu402d9372010-02-26 13:31:12 +0000567 // Trigger GCs so that the newly allocated string moves to old gen.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000568 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
569 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
Andrei Popescu402d9372010-02-26 13:31:12 +0000570 // Old space strings should be accepted.
Ben Murdoch61f157c2016-09-16 13:49:30 +0100571 CHECK(local_string->CanMakeExternal());
Andrei Popescu402d9372010-02-26 13:31:12 +0000572}
573
574
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000575TEST(MakingExternalOneByteStringConditions) {
Andrei Popescu402d9372010-02-26 13:31:12 +0000576 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000577 v8::HandleScope scope(env->GetIsolate());
Andrei Popescu402d9372010-02-26 13:31:12 +0000578
579 // Free some space in the new space so that we can check freshness.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000580 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
581 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
Andrei Popescu402d9372010-02-26 13:31:12 +0000582
Ben Murdoch61f157c2016-09-16 13:49:30 +0100583 Local<String> local_string = v8_str("s1");
584 // We should refuse to externalize new space strings.
585 CHECK(!local_string->CanMakeExternal());
Andrei Popescu402d9372010-02-26 13:31:12 +0000586 // Trigger GCs so that the newly allocated string moves to old gen.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000587 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
588 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
Andrei Popescu402d9372010-02-26 13:31:12 +0000589 // Old space strings should be accepted.
Ben Murdoch61f157c2016-09-16 13:49:30 +0100590 CHECK(local_string->CanMakeExternal());
Andrei Popescu402d9372010-02-26 13:31:12 +0000591}
592
593
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000594TEST(MakingExternalUnalignedOneByteString) {
595 LocalContext env;
596 v8::HandleScope scope(env->GetIsolate());
597
598 CompileRun("function cons(a, b) { return a + b; }"
599 "function slice(a) { return a.substring(1); }");
600 // Create a cons string that will land in old pointer space.
601 Local<String> cons = Local<String>::Cast(CompileRun(
602 "cons('abcdefghijklm', 'nopqrstuvwxyz');"));
603 // Create a sliced string that will land in old pointer space.
604 Local<String> slice = Local<String>::Cast(CompileRun(
605 "slice('abcdefghijklmnopqrstuvwxyz');"));
606
607 // Trigger GCs so that the newly allocated string moves to old gen.
Ben Murdoch61f157c2016-09-16 13:49:30 +0100608 i::heap::SimulateFullSpace(CcTest::heap()->old_space());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000609 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
610 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
611
612 // Turn into external string with unaligned resource data.
613 const char* c_cons = "_abcdefghijklmnopqrstuvwxyz";
614 bool success =
615 cons->MakeExternal(new TestOneByteResource(i::StrDup(c_cons), NULL, 1));
616 CHECK(success);
617 const char* c_slice = "_bcdefghijklmnopqrstuvwxyz";
618 success =
619 slice->MakeExternal(new TestOneByteResource(i::StrDup(c_slice), NULL, 1));
620 CHECK(success);
621
622 // Trigger GCs and force evacuation.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000623 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000624 CcTest::heap()->CollectAllGarbage(i::Heap::kReduceMemoryFootprintMask);
Steve Blocka7e24c12009-10-30 11:49:00 +0000625}
626
627
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000628THREADED_TEST(UsingExternalString) {
629 i::Factory* factory = CcTest::i_isolate()->factory();
Steve Blocka7e24c12009-10-30 11:49:00 +0000630 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000631 v8::HandleScope scope(CcTest::isolate());
632 uint16_t* two_byte_string = AsciiToTwoByteString("test string");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000633 Local<String> string =
634 String::NewExternalTwoByte(CcTest::isolate(),
635 new TestResource(two_byte_string))
636 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +0000637 i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
638 // Trigger GCs so that the newly allocated string moves to old gen.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000639 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
640 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
641 i::Handle<i::String> isymbol =
642 factory->InternalizeString(istring);
643 CHECK(isymbol->IsInternalizedString());
Steve Blocka7e24c12009-10-30 11:49:00 +0000644 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000645 CcTest::heap()->CollectAllGarbage();
646 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000647}
648
649
650THREADED_TEST(UsingExternalOneByteString) {
651 i::Factory* factory = CcTest::i_isolate()->factory();
652 {
653 v8::HandleScope scope(CcTest::isolate());
654 const char* one_byte_string = "test string";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000655 Local<String> string =
656 String::NewExternalOneByte(
657 CcTest::isolate(),
658 new TestOneByteResource(i::StrDup(one_byte_string)))
659 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000660 i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
661 // Trigger GCs so that the newly allocated string moves to old gen.
662 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
663 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
664 i::Handle<i::String> isymbol =
665 factory->InternalizeString(istring);
666 CHECK(isymbol->IsInternalizedString());
667 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000668 CcTest::heap()->CollectAllGarbage();
669 CcTest::heap()->CollectAllGarbage();
Steve Blocka7e24c12009-10-30 11:49:00 +0000670}
671
672
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400673class RandomLengthResource : public v8::String::ExternalStringResource {
674 public:
675 explicit RandomLengthResource(int length) : length_(length) {}
676 virtual const uint16_t* data() const { return string_; }
677 virtual size_t length() const { return length_; }
678
679 private:
680 uint16_t string_[10];
681 int length_;
682};
683
684
685class RandomLengthOneByteResource
686 : public v8::String::ExternalOneByteStringResource {
687 public:
688 explicit RandomLengthOneByteResource(int length) : length_(length) {}
689 virtual const char* data() const { return string_; }
690 virtual size_t length() const { return length_; }
691
692 private:
693 char string_[10];
694 int length_;
695};
696
697
698THREADED_TEST(NewExternalForVeryLongString) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000699 auto isolate = CcTest::isolate();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400700 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000701 v8::HandleScope scope(isolate);
702 v8::TryCatch try_catch(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400703 RandomLengthOneByteResource r(1 << 30);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000704 v8::MaybeLocal<v8::String> maybe_str =
705 v8::String::NewExternalOneByte(isolate, &r);
706 CHECK(maybe_str.IsEmpty());
707 CHECK(!try_catch.HasCaught());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400708 }
709
710 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000711 v8::HandleScope scope(isolate);
712 v8::TryCatch try_catch(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400713 RandomLengthResource r(1 << 30);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000714 v8::MaybeLocal<v8::String> maybe_str =
715 v8::String::NewExternalTwoByte(isolate, &r);
716 CHECK(maybe_str.IsEmpty());
717 CHECK(!try_catch.HasCaught());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400718 }
719}
720
721
Leon Clarkee46be812010-01-19 14:06:41 +0000722THREADED_TEST(ScavengeExternalString) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000723 i::FLAG_stress_compaction = false;
724 i::FLAG_gc_global = false;
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000725 int dispose_count = 0;
Steve Block6ded16b2010-05-10 14:33:55 +0100726 bool in_new_space = false;
Leon Clarkee46be812010-01-19 14:06:41 +0000727 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000728 v8::HandleScope scope(CcTest::isolate());
Leon Clarkee46be812010-01-19 14:06:41 +0000729 uint16_t* two_byte_string = AsciiToTwoByteString("test string");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000730 Local<String> string =
731 String::NewExternalTwoByte(
732 CcTest::isolate(),
733 new TestResource(two_byte_string, &dispose_count))
734 .ToLocalChecked();
Leon Clarkee46be812010-01-19 14:06:41 +0000735 i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000736 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
737 in_new_space = CcTest::heap()->InNewSpace(*istring);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000738 CHECK(in_new_space || CcTest::heap()->old_space()->Contains(*istring));
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000739 CHECK_EQ(0, dispose_count);
Leon Clarkee46be812010-01-19 14:06:41 +0000740 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000741 CcTest::heap()->CollectGarbage(in_new_space ? i::NEW_SPACE : i::OLD_SPACE);
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000742 CHECK_EQ(1, dispose_count);
Leon Clarkee46be812010-01-19 14:06:41 +0000743}
744
745
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000746THREADED_TEST(ScavengeExternalOneByteString) {
747 i::FLAG_stress_compaction = false;
748 i::FLAG_gc_global = false;
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000749 int dispose_count = 0;
Steve Block6ded16b2010-05-10 14:33:55 +0100750 bool in_new_space = false;
Leon Clarkee46be812010-01-19 14:06:41 +0000751 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000752 v8::HandleScope scope(CcTest::isolate());
Leon Clarkee46be812010-01-19 14:06:41 +0000753 const char* one_byte_string = "test string";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000754 Local<String> string =
755 String::NewExternalOneByte(
756 CcTest::isolate(),
757 new TestOneByteResource(i::StrDup(one_byte_string), &dispose_count))
758 .ToLocalChecked();
Leon Clarkee46be812010-01-19 14:06:41 +0000759 i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000760 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
761 in_new_space = CcTest::heap()->InNewSpace(*istring);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000762 CHECK(in_new_space || CcTest::heap()->old_space()->Contains(*istring));
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000763 CHECK_EQ(0, dispose_count);
Leon Clarkee46be812010-01-19 14:06:41 +0000764 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000765 CcTest::heap()->CollectGarbage(in_new_space ? i::NEW_SPACE : i::OLD_SPACE);
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000766 CHECK_EQ(1, dispose_count);
Leon Clarkee46be812010-01-19 14:06:41 +0000767}
768
769
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000770class TestOneByteResourceWithDisposeControl : public TestOneByteResource {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100771 public:
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000772 // Only used by non-threaded tests, so it can use static fields.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100773 static int dispose_calls;
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000774 static int dispose_count;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100775
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000776 TestOneByteResourceWithDisposeControl(const char* data, bool dispose)
777 : TestOneByteResource(data, &dispose_count), dispose_(dispose) {}
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100778
779 void Dispose() {
780 ++dispose_calls;
781 if (dispose_) delete this;
782 }
783 private:
784 bool dispose_;
785};
786
787
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000788int TestOneByteResourceWithDisposeControl::dispose_count = 0;
789int TestOneByteResourceWithDisposeControl::dispose_calls = 0;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100790
791
792TEST(ExternalStringWithDisposeHandling) {
793 const char* c_source = "1 + 2 * 3";
794
795 // Use a stack allocated external string resource allocated object.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000796 TestOneByteResourceWithDisposeControl::dispose_count = 0;
797 TestOneByteResourceWithDisposeControl::dispose_calls = 0;
798 TestOneByteResourceWithDisposeControl res_stack(i::StrDup(c_source), false);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100799 {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100800 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000801 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000802 Local<String> source =
803 String::NewExternalOneByte(env->GetIsolate(), &res_stack)
804 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000805 Local<Script> script = v8_compile(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000806 Local<Value> value = script->Run(env.local()).ToLocalChecked();
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100807 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000808 CHECK_EQ(7, value->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000809 CcTest::heap()->CollectAllAvailableGarbage();
810 CHECK_EQ(0, TestOneByteResourceWithDisposeControl::dispose_count);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100811 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000812 CcTest::i_isolate()->compilation_cache()->Clear();
813 CcTest::heap()->CollectAllAvailableGarbage();
814 CHECK_EQ(1, TestOneByteResourceWithDisposeControl::dispose_calls);
815 CHECK_EQ(0, TestOneByteResourceWithDisposeControl::dispose_count);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100816
817 // Use a heap allocated external string resource allocated object.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000818 TestOneByteResourceWithDisposeControl::dispose_count = 0;
819 TestOneByteResourceWithDisposeControl::dispose_calls = 0;
820 TestOneByteResource* res_heap =
821 new TestOneByteResourceWithDisposeControl(i::StrDup(c_source), true);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100822 {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100823 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000824 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000825 Local<String> source =
826 String::NewExternalOneByte(env->GetIsolate(), res_heap)
827 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000828 Local<Script> script = v8_compile(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000829 Local<Value> value = script->Run(env.local()).ToLocalChecked();
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100830 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000831 CHECK_EQ(7, value->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000832 CcTest::heap()->CollectAllAvailableGarbage();
833 CHECK_EQ(0, TestOneByteResourceWithDisposeControl::dispose_count);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100834 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000835 CcTest::i_isolate()->compilation_cache()->Clear();
836 CcTest::heap()->CollectAllAvailableGarbage();
837 CHECK_EQ(1, TestOneByteResourceWithDisposeControl::dispose_calls);
838 CHECK_EQ(1, TestOneByteResourceWithDisposeControl::dispose_count);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100839}
840
841
Steve Block3ce2e202009-11-05 08:53:23 +0000842THREADED_TEST(StringConcat) {
843 {
Steve Block3ce2e202009-11-05 08:53:23 +0000844 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000845 v8::HandleScope scope(env->GetIsolate());
Steve Block3ce2e202009-11-05 08:53:23 +0000846 const char* one_byte_string_1 = "function a_times_t";
847 const char* two_byte_string_1 = "wo_plus_b(a, b) {return ";
848 const char* one_byte_extern_1 = "a * 2 + b;} a_times_two_plus_b(4, 8) + ";
849 const char* two_byte_extern_1 = "a_times_two_plus_b(4, 8) + ";
850 const char* one_byte_string_2 = "a_times_two_plus_b(4, 8) + ";
851 const char* two_byte_string_2 = "a_times_two_plus_b(4, 8) + ";
852 const char* two_byte_extern_2 = "a_times_two_plus_b(1, 2);";
853 Local<String> left = v8_str(one_byte_string_1);
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100854
855 uint16_t* two_byte_source = AsciiToTwoByteString(two_byte_string_1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000856 Local<String> right =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000857 String::NewFromTwoByte(env->GetIsolate(), two_byte_source,
858 v8::NewStringType::kNormal)
859 .ToLocalChecked();
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100860 i::DeleteArray(two_byte_source);
861
Steve Block3ce2e202009-11-05 08:53:23 +0000862 Local<String> source = String::Concat(left, right);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000863 right = String::NewExternalOneByte(
864 env->GetIsolate(),
865 new TestOneByteResource(i::StrDup(one_byte_extern_1)))
866 .ToLocalChecked();
Steve Block3ce2e202009-11-05 08:53:23 +0000867 source = String::Concat(source, right);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000868 right = String::NewExternalTwoByte(
869 env->GetIsolate(),
870 new TestResource(AsciiToTwoByteString(two_byte_extern_1)))
871 .ToLocalChecked();
Steve Block3ce2e202009-11-05 08:53:23 +0000872 source = String::Concat(source, right);
873 right = v8_str(one_byte_string_2);
874 source = String::Concat(source, right);
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100875
876 two_byte_source = AsciiToTwoByteString(two_byte_string_2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000877 right = String::NewFromTwoByte(env->GetIsolate(), two_byte_source,
878 v8::NewStringType::kNormal)
879 .ToLocalChecked();
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100880 i::DeleteArray(two_byte_source);
881
Steve Block3ce2e202009-11-05 08:53:23 +0000882 source = String::Concat(source, right);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000883 right = String::NewExternalTwoByte(
884 env->GetIsolate(),
885 new TestResource(AsciiToTwoByteString(two_byte_extern_2)))
886 .ToLocalChecked();
Steve Block3ce2e202009-11-05 08:53:23 +0000887 source = String::Concat(source, right);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000888 Local<Script> script = v8_compile(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000889 Local<Value> value = script->Run(env.local()).ToLocalChecked();
Steve Block3ce2e202009-11-05 08:53:23 +0000890 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000891 CHECK_EQ(68, value->Int32Value(env.local()).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +0000892 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000893 CcTest::i_isolate()->compilation_cache()->Clear();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000894 CcTest::heap()->CollectAllGarbage();
895 CcTest::heap()->CollectAllGarbage();
Steve Block3ce2e202009-11-05 08:53:23 +0000896}
897
898
Steve Blocka7e24c12009-10-30 11:49:00 +0000899THREADED_TEST(GlobalProperties) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000900 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000901 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000902 v8::Local<v8::Object> global = env->Global();
903 CHECK(global->Set(env.local(), v8_str("pi"), v8_num(3.1415926)).FromJust());
904 Local<Value> pi = global->Get(env.local(), v8_str("pi")).ToLocalChecked();
905 CHECK_EQ(3.1415926, pi->NumberValue(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000906}
907
908
909static void handle_callback_impl(const v8::FunctionCallbackInfo<Value>& info,
910 i::Address callback) {
911 ApiTestFuzzer::Fuzz();
912 CheckReturnValue(info, callback);
913 info.GetReturnValue().Set(v8_str("bad value"));
914 info.GetReturnValue().Set(v8_num(102));
915}
916
917
918static void handle_callback(const v8::FunctionCallbackInfo<Value>& info) {
919 return handle_callback_impl(info, FUNCTION_ADDR(handle_callback));
920}
921
922
923static void handle_callback_2(const v8::FunctionCallbackInfo<Value>& info) {
924 return handle_callback_impl(info, FUNCTION_ADDR(handle_callback_2));
925}
926
927static void construct_callback(
928 const v8::FunctionCallbackInfo<Value>& info) {
929 ApiTestFuzzer::Fuzz();
930 CheckReturnValue(info, FUNCTION_ADDR(construct_callback));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000931 CHECK(
932 info.This()
933 ->Set(info.GetIsolate()->GetCurrentContext(), v8_str("x"), v8_num(1))
934 .FromJust());
935 CHECK(
936 info.This()
937 ->Set(info.GetIsolate()->GetCurrentContext(), v8_str("y"), v8_num(2))
938 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000939 info.GetReturnValue().Set(v8_str("bad value"));
940 info.GetReturnValue().Set(info.This());
941}
942
943
944static void Return239Callback(
945 Local<String> name, const v8::PropertyCallbackInfo<Value>& info) {
946 ApiTestFuzzer::Fuzz();
947 CheckReturnValue(info, FUNCTION_ADDR(Return239Callback));
948 info.GetReturnValue().Set(v8_str("bad value"));
949 info.GetReturnValue().Set(v8_num(239));
950}
951
952
953template<typename Handler>
954static void TestFunctionTemplateInitializer(Handler handler,
955 Handler handler_2) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000956 // Test constructor calls.
957 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000958 LocalContext env;
959 v8::Isolate* isolate = env->GetIsolate();
960 v8::HandleScope scope(isolate);
961
Steve Blocka7e24c12009-10-30 11:49:00 +0000962 Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000963 v8::FunctionTemplate::New(isolate, handler);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000964 Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
965 CHECK(env->Global()->Set(env.local(), v8_str("obj"), fun).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000966 Local<Script> script = v8_compile("obj()");
967 for (int i = 0; i < 30; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000968 CHECK_EQ(102, v8_run_int32value(script));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000969 }
970 }
971 // Use SetCallHandler to initialize a function template, should work like
972 // the previous one.
973 {
974 LocalContext env;
975 v8::Isolate* isolate = env->GetIsolate();
976 v8::HandleScope scope(isolate);
977
978 Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(isolate);
979 fun_templ->SetCallHandler(handler_2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000980 Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
981 CHECK(env->Global()->Set(env.local(), v8_str("obj"), fun).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000982 Local<Script> script = v8_compile("obj()");
983 for (int i = 0; i < 30; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000984 CHECK_EQ(102, v8_run_int32value(script));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000985 }
986 }
987}
988
989
990template<typename Constructor, typename Accessor>
991static void TestFunctionTemplateAccessor(Constructor constructor,
992 Accessor accessor) {
993 LocalContext env;
994 v8::HandleScope scope(env->GetIsolate());
995
996 Local<v8::FunctionTemplate> fun_templ =
997 v8::FunctionTemplate::New(env->GetIsolate(), constructor);
998 fun_templ->SetClassName(v8_str("funky"));
999 fun_templ->InstanceTemplate()->SetAccessor(v8_str("m"), accessor);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001000 Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
1001 CHECK(env->Global()->Set(env.local(), v8_str("obj"), fun).FromJust());
1002 Local<Value> result =
1003 v8_compile("(new obj()).toString()")->Run(env.local()).ToLocalChecked();
1004 CHECK(v8_str("[object funky]")->Equals(env.local(), result).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001005 CompileRun("var obj_instance = new obj();");
1006 Local<Script> script;
1007 script = v8_compile("obj_instance.x");
1008 for (int i = 0; i < 30; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001009 CHECK_EQ(1, v8_run_int32value(script));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001010 }
1011 script = v8_compile("obj_instance.m");
1012 for (int i = 0; i < 30; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001013 CHECK_EQ(239, v8_run_int32value(script));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001014 }
1015}
Steve Blocka7e24c12009-10-30 11:49:00 +00001016
Ben Murdochf87a2032010-10-22 12:50:53 +01001017
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001018THREADED_PROFILED_TEST(FunctionTemplate) {
1019 TestFunctionTemplateInitializer(handle_callback, handle_callback_2);
1020 TestFunctionTemplateAccessor(construct_callback, Return239Callback);
1021}
1022
1023
1024static void SimpleCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
1025 ApiTestFuzzer::Fuzz();
1026 CheckReturnValue(info, FUNCTION_ADDR(SimpleCallback));
1027 info.GetReturnValue().Set(v8_num(51423 + info.Length()));
1028}
1029
1030
1031template<typename Callback>
1032static void TestSimpleCallback(Callback callback) {
1033 LocalContext env;
1034 v8::Isolate* isolate = env->GetIsolate();
1035 v8::HandleScope scope(isolate);
1036
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001037 v8::Local<v8::ObjectTemplate> object_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001038 v8::ObjectTemplate::New(isolate);
1039 object_template->Set(isolate, "callback",
1040 v8::FunctionTemplate::New(isolate, callback));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001041 v8::Local<v8::Object> object =
1042 object_template->NewInstance(env.local()).ToLocalChecked();
1043 CHECK((*env)
1044 ->Global()
1045 ->Set(env.local(), v8_str("callback_object"), object)
1046 .FromJust());
1047 v8::Local<v8::Script> script;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001048 script = v8_compile("callback_object.callback(17)");
1049 for (int i = 0; i < 30; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001050 CHECK_EQ(51424, v8_run_int32value(script));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001051 }
1052 script = v8_compile("callback_object.callback(17, 24)");
1053 for (int i = 0; i < 30; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001054 CHECK_EQ(51425, v8_run_int32value(script));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001055 }
1056}
1057
1058
1059THREADED_PROFILED_TEST(SimpleCallback) {
1060 TestSimpleCallback(SimpleCallback);
1061}
1062
1063
1064template<typename T>
1065void FastReturnValueCallback(const v8::FunctionCallbackInfo<v8::Value>& info);
1066
1067// constant return values
1068static int32_t fast_return_value_int32 = 471;
1069static uint32_t fast_return_value_uint32 = 571;
1070static const double kFastReturnValueDouble = 2.7;
1071// variable return values
1072static bool fast_return_value_bool = false;
1073enum ReturnValueOddball {
1074 kNullReturnValue,
1075 kUndefinedReturnValue,
1076 kEmptyStringReturnValue
1077};
1078static ReturnValueOddball fast_return_value_void;
1079static bool fast_return_value_object_is_empty = false;
1080
1081// Helper function to avoid compiler error: insufficient contextual information
1082// to determine type when applying FUNCTION_ADDR to a template function.
1083static i::Address address_of(v8::FunctionCallback callback) {
1084 return FUNCTION_ADDR(callback);
1085}
1086
1087template<>
1088void FastReturnValueCallback<int32_t>(
1089 const v8::FunctionCallbackInfo<v8::Value>& info) {
1090 CheckReturnValue(info, address_of(FastReturnValueCallback<int32_t>));
1091 info.GetReturnValue().Set(fast_return_value_int32);
1092}
1093
1094template<>
1095void FastReturnValueCallback<uint32_t>(
1096 const v8::FunctionCallbackInfo<v8::Value>& info) {
1097 CheckReturnValue(info, address_of(FastReturnValueCallback<uint32_t>));
1098 info.GetReturnValue().Set(fast_return_value_uint32);
1099}
1100
1101template<>
1102void FastReturnValueCallback<double>(
1103 const v8::FunctionCallbackInfo<v8::Value>& info) {
1104 CheckReturnValue(info, address_of(FastReturnValueCallback<double>));
1105 info.GetReturnValue().Set(kFastReturnValueDouble);
1106}
1107
1108template<>
1109void FastReturnValueCallback<bool>(
1110 const v8::FunctionCallbackInfo<v8::Value>& info) {
1111 CheckReturnValue(info, address_of(FastReturnValueCallback<bool>));
1112 info.GetReturnValue().Set(fast_return_value_bool);
1113}
1114
1115template<>
1116void FastReturnValueCallback<void>(
1117 const v8::FunctionCallbackInfo<v8::Value>& info) {
1118 CheckReturnValue(info, address_of(FastReturnValueCallback<void>));
1119 switch (fast_return_value_void) {
1120 case kNullReturnValue:
1121 info.GetReturnValue().SetNull();
1122 break;
1123 case kUndefinedReturnValue:
1124 info.GetReturnValue().SetUndefined();
1125 break;
1126 case kEmptyStringReturnValue:
1127 info.GetReturnValue().SetEmptyString();
1128 break;
1129 }
1130}
1131
1132template<>
1133void FastReturnValueCallback<Object>(
1134 const v8::FunctionCallbackInfo<v8::Value>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001135 v8::Local<v8::Object> object;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001136 if (!fast_return_value_object_is_empty) {
1137 object = Object::New(info.GetIsolate());
1138 }
1139 info.GetReturnValue().Set(object);
1140}
1141
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001142template <typename T>
1143Local<Value> TestFastReturnValues() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001144 LocalContext env;
1145 v8::Isolate* isolate = env->GetIsolate();
1146 v8::EscapableHandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001147 v8::Local<v8::ObjectTemplate> object_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001148 v8::ObjectTemplate::New(isolate);
1149 v8::FunctionCallback callback = &FastReturnValueCallback<T>;
1150 object_template->Set(isolate, "callback",
1151 v8::FunctionTemplate::New(isolate, callback));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001152 v8::Local<v8::Object> object =
1153 object_template->NewInstance(env.local()).ToLocalChecked();
1154 CHECK((*env)
1155 ->Global()
1156 ->Set(env.local(), v8_str("callback_object"), object)
1157 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001158 return scope.Escape(CompileRun("callback_object.callback()"));
1159}
1160
1161
1162THREADED_PROFILED_TEST(FastReturnValues) {
1163 LocalContext env;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001164 v8::Isolate* isolate = env->GetIsolate();
1165 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001166 v8::Local<v8::Value> value;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001167 // check int32_t and uint32_t
1168 int32_t int_values[] = {
1169 0, 234, -723,
1170 i::Smi::kMinValue, i::Smi::kMaxValue
1171 };
1172 for (size_t i = 0; i < arraysize(int_values); i++) {
1173 for (int modifier = -1; modifier <= 1; modifier++) {
1174 int int_value = int_values[i] + modifier;
1175 // check int32_t
1176 fast_return_value_int32 = int_value;
1177 value = TestFastReturnValues<int32_t>();
1178 CHECK(value->IsInt32());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001179 CHECK_EQ(fast_return_value_int32,
1180 value->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001181 // check uint32_t
1182 fast_return_value_uint32 = static_cast<uint32_t>(int_value);
1183 value = TestFastReturnValues<uint32_t>();
1184 CHECK(value->IsUint32());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001185 CHECK_EQ(fast_return_value_uint32,
1186 value->Uint32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001187 }
1188 }
1189 // check double
1190 value = TestFastReturnValues<double>();
1191 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001192 CHECK_EQ(kFastReturnValueDouble,
1193 value->ToNumber(env.local()).ToLocalChecked()->Value());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001194 // check bool values
1195 for (int i = 0; i < 2; i++) {
1196 fast_return_value_bool = i == 0;
1197 value = TestFastReturnValues<bool>();
1198 CHECK(value->IsBoolean());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001199 CHECK_EQ(fast_return_value_bool,
1200 value->ToBoolean(env.local()).ToLocalChecked()->Value());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001201 }
1202 // check oddballs
1203 ReturnValueOddball oddballs[] = {
1204 kNullReturnValue,
1205 kUndefinedReturnValue,
1206 kEmptyStringReturnValue
1207 };
1208 for (size_t i = 0; i < arraysize(oddballs); i++) {
1209 fast_return_value_void = oddballs[i];
1210 value = TestFastReturnValues<void>();
1211 switch (fast_return_value_void) {
1212 case kNullReturnValue:
1213 CHECK(value->IsNull());
1214 break;
1215 case kUndefinedReturnValue:
1216 CHECK(value->IsUndefined());
1217 break;
1218 case kEmptyStringReturnValue:
1219 CHECK(value->IsString());
1220 CHECK_EQ(0, v8::String::Cast(*value)->Length());
1221 break;
1222 }
1223 }
1224 // check handles
1225 fast_return_value_object_is_empty = false;
1226 value = TestFastReturnValues<Object>();
1227 CHECK(value->IsObject());
1228 fast_return_value_object_is_empty = true;
1229 value = TestFastReturnValues<Object>();
1230 CHECK(value->IsUndefined());
1231}
1232
1233
1234THREADED_TEST(FunctionTemplateSetLength) {
1235 LocalContext env;
1236 v8::Isolate* isolate = env->GetIsolate();
1237 v8::HandleScope scope(isolate);
1238 {
1239 Local<v8::FunctionTemplate> fun_templ =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001240 v8::FunctionTemplate::New(isolate, handle_callback, Local<v8::Value>(),
1241 Local<v8::Signature>(), 23);
1242 Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
1243 CHECK(env->Global()->Set(env.local(), v8_str("obj"), fun).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001244 Local<Script> script = v8_compile("obj.length");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001245 CHECK_EQ(23, v8_run_int32value(script));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001246 }
1247 {
1248 Local<v8::FunctionTemplate> fun_templ =
1249 v8::FunctionTemplate::New(isolate, handle_callback);
1250 fun_templ->SetLength(22);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001251 Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
1252 CHECK(env->Global()->Set(env.local(), v8_str("obj"), fun).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001253 Local<Script> script = v8_compile("obj.length");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001254 CHECK_EQ(22, v8_run_int32value(script));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001255 }
1256 {
1257 // Without setting length it defaults to 0.
1258 Local<v8::FunctionTemplate> fun_templ =
1259 v8::FunctionTemplate::New(isolate, handle_callback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001260 Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
1261 CHECK(env->Global()->Set(env.local(), v8_str("obj"), fun).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001262 Local<Script> script = v8_compile("obj.length");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001263 CHECK_EQ(0, v8_run_int32value(script));
Steve Blocka7e24c12009-10-30 11:49:00 +00001264 }
1265}
1266
1267
Ben Murdochb8e0da22011-05-16 14:20:40 +01001268static void* expected_ptr;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001269static void callback(const v8::FunctionCallbackInfo<v8::Value>& args) {
1270 void* ptr = v8::External::Cast(*args.Data())->Value();
Ben Murdochb8e0da22011-05-16 14:20:40 +01001271 CHECK_EQ(expected_ptr, ptr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001272 args.GetReturnValue().Set(true);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001273}
1274
1275
1276static void TestExternalPointerWrapping() {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001277 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001278 v8::Isolate* isolate = env->GetIsolate();
1279 v8::HandleScope scope(isolate);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001280
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001281 v8::Local<v8::Value> data = v8::External::New(isolate, expected_ptr);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001282
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001283 v8::Local<v8::Object> obj = v8::Object::New(isolate);
1284 CHECK(obj->Set(env.local(), v8_str("func"),
1285 v8::FunctionTemplate::New(isolate, callback, data)
1286 ->GetFunction(env.local())
1287 .ToLocalChecked())
1288 .FromJust());
1289 CHECK(env->Global()->Set(env.local(), v8_str("obj"), obj).FromJust());
Ben Murdochb8e0da22011-05-16 14:20:40 +01001290
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001291 CHECK(CompileRun("function foo() {\n"
1292 " for (var i = 0; i < 13; i++) obj.func();\n"
1293 "}\n"
1294 "foo(), true")
1295 ->BooleanValue(env.local())
1296 .FromJust());
Ben Murdochb8e0da22011-05-16 14:20:40 +01001297}
1298
1299
1300THREADED_TEST(ExternalWrap) {
1301 // Check heap allocated object.
1302 int* ptr = new int;
1303 expected_ptr = ptr;
1304 TestExternalPointerWrapping();
1305 delete ptr;
1306
1307 // Check stack allocated object.
1308 int foo;
1309 expected_ptr = &foo;
1310 TestExternalPointerWrapping();
1311
1312 // Check not aligned addresses.
1313 const int n = 100;
1314 char* s = new char[n];
1315 for (int i = 0; i < n; i++) {
1316 expected_ptr = s + i;
1317 TestExternalPointerWrapping();
1318 }
1319
1320 delete[] s;
1321
1322 // Check several invalid addresses.
1323 expected_ptr = reinterpret_cast<void*>(1);
1324 TestExternalPointerWrapping();
1325
1326 expected_ptr = reinterpret_cast<void*>(0xdeadbeef);
1327 TestExternalPointerWrapping();
1328
1329 expected_ptr = reinterpret_cast<void*>(0xdeadbeef + 1);
1330 TestExternalPointerWrapping();
1331
1332#if defined(V8_HOST_ARCH_X64)
Steve Block1e0659c2011-05-24 12:43:12 +01001333 // Check a value with a leading 1 bit in x64 Smi encoding.
1334 expected_ptr = reinterpret_cast<void*>(0x400000000);
1335 TestExternalPointerWrapping();
1336
Ben Murdochb8e0da22011-05-16 14:20:40 +01001337 expected_ptr = reinterpret_cast<void*>(0xdeadbeefdeadbeef);
1338 TestExternalPointerWrapping();
1339
1340 expected_ptr = reinterpret_cast<void*>(0xdeadbeefdeadbeef + 1);
1341 TestExternalPointerWrapping();
1342#endif
1343}
1344
1345
Steve Blocka7e24c12009-10-30 11:49:00 +00001346THREADED_TEST(FindInstanceInPrototypeChain) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001347 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001348 v8::Isolate* isolate = env->GetIsolate();
1349 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001350
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001351 Local<v8::FunctionTemplate> base = v8::FunctionTemplate::New(isolate);
1352 Local<v8::FunctionTemplate> derived = v8::FunctionTemplate::New(isolate);
1353 Local<v8::FunctionTemplate> other = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001354 derived->Inherit(base);
1355
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001356 Local<v8::Function> base_function =
1357 base->GetFunction(env.local()).ToLocalChecked();
1358 Local<v8::Function> derived_function =
1359 derived->GetFunction(env.local()).ToLocalChecked();
1360 Local<v8::Function> other_function =
1361 other->GetFunction(env.local()).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00001362
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001363 Local<v8::Object> base_instance =
1364 base_function->NewInstance(env.local()).ToLocalChecked();
1365 Local<v8::Object> derived_instance =
1366 derived_function->NewInstance(env.local()).ToLocalChecked();
1367 Local<v8::Object> derived_instance2 =
1368 derived_function->NewInstance(env.local()).ToLocalChecked();
1369 Local<v8::Object> other_instance =
1370 other_function->NewInstance(env.local()).ToLocalChecked();
1371 CHECK(
1372 derived_instance2->Set(env.local(), v8_str("__proto__"), derived_instance)
1373 .FromJust());
1374 CHECK(other_instance->Set(env.local(), v8_str("__proto__"), derived_instance2)
1375 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00001376
1377 // base_instance is only an instance of base.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001378 CHECK(base_instance->Equals(env.local(),
1379 base_instance->FindInstanceInPrototypeChain(base))
1380 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00001381 CHECK(base_instance->FindInstanceInPrototypeChain(derived).IsEmpty());
1382 CHECK(base_instance->FindInstanceInPrototypeChain(other).IsEmpty());
1383
1384 // derived_instance is an instance of base and derived.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001385 CHECK(derived_instance->Equals(env.local(),
1386 derived_instance->FindInstanceInPrototypeChain(
1387 base))
1388 .FromJust());
1389 CHECK(derived_instance->Equals(env.local(),
1390 derived_instance->FindInstanceInPrototypeChain(
1391 derived))
1392 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00001393 CHECK(derived_instance->FindInstanceInPrototypeChain(other).IsEmpty());
1394
1395 // other_instance is an instance of other and its immediate
1396 // prototype derived_instance2 is an instance of base and derived.
1397 // Note, derived_instance is an instance of base and derived too,
1398 // but it comes after derived_instance2 in the prototype chain of
1399 // other_instance.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001400 CHECK(derived_instance2->Equals(
1401 env.local(),
1402 other_instance->FindInstanceInPrototypeChain(base))
1403 .FromJust());
1404 CHECK(derived_instance2->Equals(env.local(),
1405 other_instance->FindInstanceInPrototypeChain(
1406 derived))
1407 .FromJust());
1408 CHECK(other_instance->Equals(
1409 env.local(),
1410 other_instance->FindInstanceInPrototypeChain(other))
1411 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00001412}
1413
1414
Steve Block3ce2e202009-11-05 08:53:23 +00001415THREADED_TEST(TinyInteger) {
Steve Block3ce2e202009-11-05 08:53:23 +00001416 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001417 v8::Isolate* isolate = env->GetIsolate();
1418 v8::HandleScope scope(isolate);
1419
Steve Block3ce2e202009-11-05 08:53:23 +00001420 int32_t value = 239;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001421 Local<v8::Integer> value_obj = v8::Integer::New(isolate, value);
1422 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1423
1424 value_obj = v8::Integer::New(isolate, value);
Steve Block3ce2e202009-11-05 08:53:23 +00001425 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1426}
1427
1428
1429THREADED_TEST(BigSmiInteger) {
Steve Block3ce2e202009-11-05 08:53:23 +00001430 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001431 v8::HandleScope scope(env->GetIsolate());
1432 v8::Isolate* isolate = CcTest::isolate();
1433
Steve Block3ce2e202009-11-05 08:53:23 +00001434 int32_t value = i::Smi::kMaxValue;
1435 // We cannot add one to a Smi::kMaxValue without wrapping.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001436 if (i::SmiValuesAre31Bits()) {
Steve Block3ce2e202009-11-05 08:53:23 +00001437 CHECK(i::Smi::IsValid(value));
1438 CHECK(!i::Smi::IsValid(value + 1));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001439
1440 Local<v8::Integer> value_obj = v8::Integer::New(isolate, value);
1441 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1442
1443 value_obj = v8::Integer::New(isolate, value);
Steve Block3ce2e202009-11-05 08:53:23 +00001444 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1445 }
1446}
1447
1448
1449THREADED_TEST(BigInteger) {
Steve Block3ce2e202009-11-05 08:53:23 +00001450 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001451 v8::HandleScope scope(env->GetIsolate());
1452 v8::Isolate* isolate = CcTest::isolate();
1453
Steve Block3ce2e202009-11-05 08:53:23 +00001454 // We cannot add one to a Smi::kMaxValue without wrapping.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001455 if (i::SmiValuesAre31Bits()) {
Steve Block3ce2e202009-11-05 08:53:23 +00001456 // The casts allow this to compile, even if Smi::kMaxValue is 2^31-1.
1457 // The code will not be run in that case, due to the "if" guard.
1458 int32_t value =
1459 static_cast<int32_t>(static_cast<uint32_t>(i::Smi::kMaxValue) + 1);
1460 CHECK(value > i::Smi::kMaxValue);
1461 CHECK(!i::Smi::IsValid(value));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001462
1463 Local<v8::Integer> value_obj = v8::Integer::New(isolate, value);
1464 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1465
1466 value_obj = v8::Integer::New(isolate, value);
Steve Block3ce2e202009-11-05 08:53:23 +00001467 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1468 }
1469}
1470
1471
1472THREADED_TEST(TinyUnsignedInteger) {
Steve Block3ce2e202009-11-05 08:53:23 +00001473 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001474 v8::HandleScope scope(env->GetIsolate());
1475 v8::Isolate* isolate = CcTest::isolate();
1476
Steve Block3ce2e202009-11-05 08:53:23 +00001477 uint32_t value = 239;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001478
1479 Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
1480 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1481
1482 value_obj = v8::Integer::NewFromUnsigned(isolate, value);
Steve Block3ce2e202009-11-05 08:53:23 +00001483 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1484}
1485
1486
1487THREADED_TEST(BigUnsignedSmiInteger) {
Steve Block3ce2e202009-11-05 08:53:23 +00001488 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001489 v8::HandleScope scope(env->GetIsolate());
1490 v8::Isolate* isolate = CcTest::isolate();
1491
Steve Block3ce2e202009-11-05 08:53:23 +00001492 uint32_t value = static_cast<uint32_t>(i::Smi::kMaxValue);
1493 CHECK(i::Smi::IsValid(value));
1494 CHECK(!i::Smi::IsValid(value + 1));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001495
1496 Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
1497 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1498
1499 value_obj = v8::Integer::NewFromUnsigned(isolate, value);
Steve Block3ce2e202009-11-05 08:53:23 +00001500 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1501}
1502
1503
1504THREADED_TEST(BigUnsignedInteger) {
Steve Block3ce2e202009-11-05 08:53:23 +00001505 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001506 v8::HandleScope scope(env->GetIsolate());
1507 v8::Isolate* isolate = CcTest::isolate();
1508
Steve Block3ce2e202009-11-05 08:53:23 +00001509 uint32_t value = static_cast<uint32_t>(i::Smi::kMaxValue) + 1;
1510 CHECK(value > static_cast<uint32_t>(i::Smi::kMaxValue));
1511 CHECK(!i::Smi::IsValid(value));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001512
1513 Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
1514 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1515
1516 value_obj = v8::Integer::NewFromUnsigned(isolate, value);
Steve Block3ce2e202009-11-05 08:53:23 +00001517 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1518}
1519
1520
1521THREADED_TEST(OutOfSignedRangeUnsignedInteger) {
Steve Block3ce2e202009-11-05 08:53:23 +00001522 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001523 v8::HandleScope scope(env->GetIsolate());
1524 v8::Isolate* isolate = CcTest::isolate();
1525
Steve Block3ce2e202009-11-05 08:53:23 +00001526 uint32_t INT32_MAX_AS_UINT = (1U << 31) - 1;
1527 uint32_t value = INT32_MAX_AS_UINT + 1;
1528 CHECK(value > INT32_MAX_AS_UINT); // No overflow.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001529
1530 Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
1531 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1532
1533 value_obj = v8::Integer::NewFromUnsigned(isolate, value);
Steve Block3ce2e202009-11-05 08:53:23 +00001534 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1535}
1536
1537
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001538THREADED_TEST(IsNativeError) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001539 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001540 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001541 v8::Local<Value> syntax_error = CompileRun(
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001542 "var out = 0; try { eval(\"#\"); } catch(x) { out = x; } out; ");
1543 CHECK(syntax_error->IsNativeError());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001544 v8::Local<Value> not_error = CompileRun("{a:42}");
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001545 CHECK(!not_error->IsNativeError());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001546 v8::Local<Value> not_object = CompileRun("42");
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001547 CHECK(!not_object->IsNativeError());
1548}
1549
1550
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001551THREADED_TEST(IsGeneratorFunctionOrObject) {
1552 LocalContext env;
1553 v8::HandleScope scope(env->GetIsolate());
1554
1555 CompileRun("function *gen() { yield 1; }\nfunction func() {}");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001556 v8::Local<Value> gen = CompileRun("gen");
1557 v8::Local<Value> genObj = CompileRun("gen()");
1558 v8::Local<Value> object = CompileRun("{a:42}");
1559 v8::Local<Value> func = CompileRun("func");
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001560
1561 CHECK(gen->IsGeneratorFunction());
1562 CHECK(gen->IsFunction());
1563 CHECK(!gen->IsGeneratorObject());
1564
1565 CHECK(!genObj->IsGeneratorFunction());
1566 CHECK(!genObj->IsFunction());
1567 CHECK(genObj->IsGeneratorObject());
1568
1569 CHECK(!object->IsGeneratorFunction());
1570 CHECK(!object->IsFunction());
1571 CHECK(!object->IsGeneratorObject());
1572
1573 CHECK(!func->IsGeneratorFunction());
1574 CHECK(func->IsFunction());
1575 CHECK(!func->IsGeneratorObject());
1576}
1577
1578
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001579THREADED_TEST(ArgumentsObject) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001580 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001581 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001582 v8::Local<Value> arguments_object =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001583 CompileRun("var out = 0; (function(){ out = arguments; })(1,2,3); out;");
1584 CHECK(arguments_object->IsArgumentsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001585 v8::Local<Value> array = CompileRun("[1,2,3]");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001586 CHECK(!array->IsArgumentsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001587 v8::Local<Value> object = CompileRun("{a:42}");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001588 CHECK(!object->IsArgumentsObject());
1589}
1590
1591
1592THREADED_TEST(IsMapOrSet) {
1593 LocalContext env;
1594 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001595 v8::Local<Value> map = CompileRun("new Map()");
1596 v8::Local<Value> set = CompileRun("new Set()");
1597 v8::Local<Value> weak_map = CompileRun("new WeakMap()");
1598 v8::Local<Value> weak_set = CompileRun("new WeakSet()");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001599 CHECK(map->IsMap());
1600 CHECK(set->IsSet());
1601 CHECK(weak_map->IsWeakMap());
1602 CHECK(weak_set->IsWeakSet());
1603
1604 CHECK(!map->IsSet());
1605 CHECK(!map->IsWeakMap());
1606 CHECK(!map->IsWeakSet());
1607
1608 CHECK(!set->IsMap());
1609 CHECK(!set->IsWeakMap());
1610 CHECK(!set->IsWeakSet());
1611
1612 CHECK(!weak_map->IsMap());
1613 CHECK(!weak_map->IsSet());
1614 CHECK(!weak_map->IsWeakSet());
1615
1616 CHECK(!weak_set->IsMap());
1617 CHECK(!weak_set->IsSet());
1618 CHECK(!weak_set->IsWeakMap());
1619
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001620 v8::Local<Value> object = CompileRun("{a:42}");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001621 CHECK(!object->IsMap());
1622 CHECK(!object->IsSet());
1623 CHECK(!object->IsWeakMap());
1624 CHECK(!object->IsWeakSet());
1625}
1626
1627
1628THREADED_TEST(StringObject) {
1629 LocalContext env;
1630 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001631 v8::Local<Value> boxed_string = CompileRun("new String(\"test\")");
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001632 CHECK(boxed_string->IsStringObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001633 v8::Local<Value> unboxed_string = CompileRun("\"test\"");
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001634 CHECK(!unboxed_string->IsStringObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001635 v8::Local<Value> boxed_not_string = CompileRun("new Number(42)");
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001636 CHECK(!boxed_not_string->IsStringObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001637 v8::Local<Value> not_object = CompileRun("0");
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001638 CHECK(!not_object->IsStringObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001639 v8::Local<v8::StringObject> as_boxed = boxed_string.As<v8::StringObject>();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001640 CHECK(!as_boxed.IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001641 Local<v8::String> the_string = as_boxed->ValueOf();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001642 CHECK(!the_string.IsEmpty());
1643 ExpectObject("\"test\"", the_string);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001644 v8::Local<v8::Value> new_boxed_string = v8::StringObject::New(the_string);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001645 CHECK(new_boxed_string->IsStringObject());
1646 as_boxed = new_boxed_string.As<v8::StringObject>();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001647 the_string = as_boxed->ValueOf();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001648 CHECK(!the_string.IsEmpty());
1649 ExpectObject("\"test\"", the_string);
1650}
1651
1652
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001653TEST(StringObjectDelete) {
1654 LocalContext context;
1655 v8::HandleScope scope(context->GetIsolate());
1656 v8::Local<Value> boxed_string = CompileRun("new String(\"test\")");
1657 CHECK(boxed_string->IsStringObject());
1658 v8::Local<v8::Object> str_obj = boxed_string.As<v8::Object>();
1659 CHECK(!str_obj->Delete(context.local(), 2).FromJust());
1660 CHECK(!str_obj->Delete(context.local(), v8_num(2)).FromJust());
1661}
1662
1663
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001664THREADED_TEST(NumberObject) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001665 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001666 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001667 v8::Local<Value> boxed_number = CompileRun("new Number(42)");
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001668 CHECK(boxed_number->IsNumberObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001669 v8::Local<Value> unboxed_number = CompileRun("42");
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001670 CHECK(!unboxed_number->IsNumberObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001671 v8::Local<Value> boxed_not_number = CompileRun("new Boolean(false)");
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001672 CHECK(!boxed_not_number->IsNumberObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001673 v8::Local<v8::NumberObject> as_boxed = boxed_number.As<v8::NumberObject>();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001674 CHECK(!as_boxed.IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001675 double the_number = as_boxed->ValueOf();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001676 CHECK_EQ(42.0, the_number);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001677 v8::Local<v8::Value> new_boxed_number =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001678 v8::NumberObject::New(env->GetIsolate(), 43);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001679 CHECK(new_boxed_number->IsNumberObject());
1680 as_boxed = new_boxed_number.As<v8::NumberObject>();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001681 the_number = as_boxed->ValueOf();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001682 CHECK_EQ(43.0, the_number);
1683}
1684
1685
1686THREADED_TEST(BooleanObject) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001687 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001688 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001689 v8::Local<Value> boxed_boolean = CompileRun("new Boolean(true)");
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001690 CHECK(boxed_boolean->IsBooleanObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001691 v8::Local<Value> unboxed_boolean = CompileRun("true");
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001692 CHECK(!unboxed_boolean->IsBooleanObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001693 v8::Local<Value> boxed_not_boolean = CompileRun("new Number(42)");
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001694 CHECK(!boxed_not_boolean->IsBooleanObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001695 v8::Local<v8::BooleanObject> as_boxed = boxed_boolean.As<v8::BooleanObject>();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001696 CHECK(!as_boxed.IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001697 bool the_boolean = as_boxed->ValueOf();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001698 CHECK_EQ(true, the_boolean);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001699 v8::Local<v8::Value> boxed_true =
1700 v8::BooleanObject::New(env->GetIsolate(), true);
1701 v8::Local<v8::Value> boxed_false =
1702 v8::BooleanObject::New(env->GetIsolate(), false);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001703 CHECK(boxed_true->IsBooleanObject());
1704 CHECK(boxed_false->IsBooleanObject());
1705 as_boxed = boxed_true.As<v8::BooleanObject>();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001706 CHECK_EQ(true, as_boxed->ValueOf());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001707 as_boxed = boxed_false.As<v8::BooleanObject>();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001708 CHECK_EQ(false, as_boxed->ValueOf());
1709}
1710
1711
1712THREADED_TEST(PrimitiveAndWrappedBooleans) {
1713 LocalContext env;
1714 v8::HandleScope scope(env->GetIsolate());
1715
1716 Local<Value> primitive_false = Boolean::New(env->GetIsolate(), false);
1717 CHECK(primitive_false->IsBoolean());
1718 CHECK(!primitive_false->IsBooleanObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001719 CHECK(!primitive_false->BooleanValue(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001720 CHECK(!primitive_false->IsTrue());
1721 CHECK(primitive_false->IsFalse());
1722
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001723 Local<Value> false_value = BooleanObject::New(env->GetIsolate(), false);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001724 CHECK(!false_value->IsBoolean());
1725 CHECK(false_value->IsBooleanObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001726 CHECK(false_value->BooleanValue(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001727 CHECK(!false_value->IsTrue());
1728 CHECK(!false_value->IsFalse());
1729
1730 Local<BooleanObject> false_boolean_object = false_value.As<BooleanObject>();
1731 CHECK(!false_boolean_object->IsBoolean());
1732 CHECK(false_boolean_object->IsBooleanObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001733 CHECK(false_boolean_object->BooleanValue(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001734 CHECK(!false_boolean_object->ValueOf());
1735 CHECK(!false_boolean_object->IsTrue());
1736 CHECK(!false_boolean_object->IsFalse());
1737
1738 Local<Value> primitive_true = Boolean::New(env->GetIsolate(), true);
1739 CHECK(primitive_true->IsBoolean());
1740 CHECK(!primitive_true->IsBooleanObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001741 CHECK(primitive_true->BooleanValue(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001742 CHECK(primitive_true->IsTrue());
1743 CHECK(!primitive_true->IsFalse());
1744
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001745 Local<Value> true_value = BooleanObject::New(env->GetIsolate(), true);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001746 CHECK(!true_value->IsBoolean());
1747 CHECK(true_value->IsBooleanObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001748 CHECK(true_value->BooleanValue(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001749 CHECK(!true_value->IsTrue());
1750 CHECK(!true_value->IsFalse());
1751
1752 Local<BooleanObject> true_boolean_object = true_value.As<BooleanObject>();
1753 CHECK(!true_boolean_object->IsBoolean());
1754 CHECK(true_boolean_object->IsBooleanObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001755 CHECK(true_boolean_object->BooleanValue(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001756 CHECK(true_boolean_object->ValueOf());
1757 CHECK(!true_boolean_object->IsTrue());
1758 CHECK(!true_boolean_object->IsFalse());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001759}
1760
1761
Steve Blocka7e24c12009-10-30 11:49:00 +00001762THREADED_TEST(Number) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001763 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001764 v8::HandleScope scope(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00001765 double PI = 3.1415926;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001766 Local<v8::Number> pi_obj = v8::Number::New(env->GetIsolate(), PI);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001767 CHECK_EQ(PI, pi_obj->NumberValue(env.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00001768}
1769
1770
1771THREADED_TEST(ToNumber) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001772 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001773 v8::Isolate* isolate = CcTest::isolate();
1774 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001775 Local<String> str = v8_str("3.1415926");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001776 CHECK_EQ(3.1415926, str->NumberValue(env.local()).FromJust());
1777 v8::Local<v8::Boolean> t = v8::True(isolate);
1778 CHECK_EQ(1.0, t->NumberValue(env.local()).FromJust());
1779 v8::Local<v8::Boolean> f = v8::False(isolate);
1780 CHECK_EQ(0.0, f->NumberValue(env.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00001781}
1782
1783
1784THREADED_TEST(Date) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001785 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001786 v8::HandleScope scope(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00001787 double PI = 3.1415926;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001788 Local<Value> date = v8::Date::New(env.local(), PI).ToLocalChecked();
1789 CHECK_EQ(3.0, date->NumberValue(env.local()).FromJust());
1790 CHECK(date.As<v8::Date>()
1791 ->Set(env.local(), v8_str("property"),
1792 v8::Integer::New(env->GetIsolate(), 42))
1793 .FromJust());
1794 CHECK_EQ(42, date.As<v8::Date>()
1795 ->Get(env.local(), v8_str("property"))
1796 .ToLocalChecked()
1797 ->Int32Value(env.local())
1798 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00001799}
1800
1801
1802THREADED_TEST(Boolean) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001803 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001804 v8::Isolate* isolate = env->GetIsolate();
1805 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001806 v8::Local<v8::Boolean> t = v8::True(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001807 CHECK(t->Value());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001808 v8::Local<v8::Boolean> f = v8::False(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001809 CHECK(!f->Value());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001810 v8::Local<v8::Primitive> u = v8::Undefined(isolate);
1811 CHECK(!u->BooleanValue(env.local()).FromJust());
1812 v8::Local<v8::Primitive> n = v8::Null(isolate);
1813 CHECK(!n->BooleanValue(env.local()).FromJust());
1814 v8::Local<String> str1 = v8_str("");
1815 CHECK(!str1->BooleanValue(env.local()).FromJust());
1816 v8::Local<String> str2 = v8_str("x");
1817 CHECK(str2->BooleanValue(env.local()).FromJust());
1818 CHECK(!v8::Number::New(isolate, 0)->BooleanValue(env.local()).FromJust());
1819 CHECK(v8::Number::New(isolate, -1)->BooleanValue(env.local()).FromJust());
1820 CHECK(v8::Number::New(isolate, 1)->BooleanValue(env.local()).FromJust());
1821 CHECK(v8::Number::New(isolate, 42)->BooleanValue(env.local()).FromJust());
1822 CHECK(!v8_compile("NaN")
1823 ->Run(env.local())
1824 .ToLocalChecked()
1825 ->BooleanValue(env.local())
1826 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00001827}
1828
1829
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001830static void DummyCallHandler(const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001831 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001832 args.GetReturnValue().Set(v8_num(13.4));
Steve Blocka7e24c12009-10-30 11:49:00 +00001833}
1834
1835
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001836static void GetM(Local<String> name,
1837 const v8::PropertyCallbackInfo<v8::Value>& info) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001838 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001839 info.GetReturnValue().Set(v8_num(876));
Steve Blocka7e24c12009-10-30 11:49:00 +00001840}
1841
1842
1843THREADED_TEST(GlobalPrototype) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001844 v8::Isolate* isolate = CcTest::isolate();
1845 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001846 v8::Local<v8::FunctionTemplate> func_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001847 v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001848 func_templ->PrototypeTemplate()->Set(
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001849 isolate, "dummy", v8::FunctionTemplate::New(isolate, DummyCallHandler));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001850 v8::Local<ObjectTemplate> templ = func_templ->InstanceTemplate();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001851 templ->Set(isolate, "x", v8_num(200));
Steve Blocka7e24c12009-10-30 11:49:00 +00001852 templ->SetAccessor(v8_str("m"), GetM);
1853 LocalContext env(0, templ);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001854 v8::Local<Script> script(v8_compile("dummy()"));
1855 v8::Local<Value> result(script->Run(env.local()).ToLocalChecked());
1856 CHECK_EQ(13.4, result->NumberValue(env.local()).FromJust());
1857 CHECK_EQ(200, v8_run_int32value(v8_compile("x")));
1858 CHECK_EQ(876, v8_run_int32value(v8_compile("m")));
Steve Blocka7e24c12009-10-30 11:49:00 +00001859}
1860
1861
Steve Blocka7e24c12009-10-30 11:49:00 +00001862THREADED_TEST(ObjectTemplate) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001863 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001864 v8::Isolate* isolate = CcTest::isolate();
1865 v8::HandleScope scope(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001866 Local<v8::FunctionTemplate> acc =
1867 v8::FunctionTemplate::New(isolate, Returns42);
1868 CHECK(env->Global()
1869 ->Set(env.local(), v8_str("acc"),
1870 acc->GetFunction(env.local()).ToLocalChecked())
1871 .FromJust());
1872
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001873 Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(isolate);
1874 v8::Local<v8::String> class_name = v8_str("the_class_name");
1875 fun->SetClassName(class_name);
1876 Local<ObjectTemplate> templ1 = ObjectTemplate::New(isolate, fun);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001877 templ1->Set(isolate, "x", v8_num(10));
1878 templ1->Set(isolate, "y", v8_num(13));
Ben Murdoch097c5b22016-05-18 11:27:45 +01001879 templ1->Set(v8_str("foo"), acc);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001880 Local<v8::Object> instance1 =
1881 templ1->NewInstance(env.local()).ToLocalChecked();
1882 CHECK(class_name->StrictEquals(instance1->GetConstructorName()));
1883 CHECK(env->Global()->Set(env.local(), v8_str("p"), instance1).FromJust());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001884 CHECK(CompileRun("(p.x == 10)")->BooleanValue(env.local()).FromJust());
1885 CHECK(CompileRun("(p.y == 13)")->BooleanValue(env.local()).FromJust());
1886 CHECK(CompileRun("(p.foo() == 42)")->BooleanValue(env.local()).FromJust());
1887 CHECK(CompileRun("(p.foo == acc)")->BooleanValue(env.local()).FromJust());
1888 // Ensure that foo become a data field.
1889 CompileRun("p.foo = function() {}");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001890 Local<v8::FunctionTemplate> fun2 = v8::FunctionTemplate::New(isolate);
1891 fun2->PrototypeTemplate()->Set(isolate, "nirk", v8_num(123));
1892 Local<ObjectTemplate> templ2 = fun2->InstanceTemplate();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001893 templ2->Set(isolate, "a", v8_num(12));
1894 templ2->Set(isolate, "b", templ1);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001895 templ2->Set(v8_str("bar"), acc);
1896 templ2->SetAccessorProperty(v8_str("acc"), acc);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001897 Local<v8::Object> instance2 =
1898 templ2->NewInstance(env.local()).ToLocalChecked();
1899 CHECK(env->Global()->Set(env.local(), v8_str("q"), instance2).FromJust());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001900 CHECK(CompileRun("(q.nirk == 123)")->BooleanValue(env.local()).FromJust());
1901 CHECK(CompileRun("(q.a == 12)")->BooleanValue(env.local()).FromJust());
1902 CHECK(CompileRun("(q.b.x == 10)")->BooleanValue(env.local()).FromJust());
1903 CHECK(CompileRun("(q.b.y == 13)")->BooleanValue(env.local()).FromJust());
1904 CHECK(CompileRun("(q.b.foo() == 42)")->BooleanValue(env.local()).FromJust());
1905 CHECK(CompileRun("(q.b.foo === acc)")->BooleanValue(env.local()).FromJust());
1906 CHECK(CompileRun("(q.b !== p)")->BooleanValue(env.local()).FromJust());
1907 CHECK(CompileRun("(q.acc == 42)")->BooleanValue(env.local()).FromJust());
1908 CHECK(CompileRun("(q.bar() == 42)")->BooleanValue(env.local()).FromJust());
1909 CHECK(CompileRun("(q.bar == acc)")->BooleanValue(env.local()).FromJust());
1910
1911 instance2 = templ2->NewInstance(env.local()).ToLocalChecked();
1912 CHECK(env->Global()->Set(env.local(), v8_str("q2"), instance2).FromJust());
1913 CHECK(CompileRun("(q2.nirk == 123)")->BooleanValue(env.local()).FromJust());
1914 CHECK(CompileRun("(q2.a == 12)")->BooleanValue(env.local()).FromJust());
1915 CHECK(CompileRun("(q2.b.x == 10)")->BooleanValue(env.local()).FromJust());
1916 CHECK(CompileRun("(q2.b.y == 13)")->BooleanValue(env.local()).FromJust());
1917 CHECK(CompileRun("(q2.b.foo() == 42)")->BooleanValue(env.local()).FromJust());
1918 CHECK(CompileRun("(q2.b.foo === acc)")->BooleanValue(env.local()).FromJust());
1919 CHECK(CompileRun("(q2.acc == 42)")->BooleanValue(env.local()).FromJust());
1920 CHECK(CompileRun("(q2.bar() == 42)")->BooleanValue(env.local()).FromJust());
1921 CHECK(CompileRun("(q2.bar === acc)")->BooleanValue(env.local()).FromJust());
1922
1923 CHECK(CompileRun("(q.b !== q2.b)")->BooleanValue(env.local()).FromJust());
1924 CHECK(CompileRun("q.b.x = 17; (q2.b.x == 10)")
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001925 ->BooleanValue(env.local())
1926 .FromJust());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001927 CHECK(CompileRun("desc1 = Object.getOwnPropertyDescriptor(q, 'acc');"
1928 "(desc1.get === acc)")
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001929 ->BooleanValue(env.local())
1930 .FromJust());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001931 CHECK(CompileRun("desc2 = Object.getOwnPropertyDescriptor(q2, 'acc');"
1932 "(desc2.get === acc)")
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001933 ->BooleanValue(env.local())
1934 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00001935}
1936
Ben Murdoch097c5b22016-05-18 11:27:45 +01001937THREADED_TEST(IntegerValue) {
1938 LocalContext env;
1939 v8::Isolate* isolate = CcTest::isolate();
1940 v8::HandleScope scope(isolate);
1941
1942 CHECK_EQ(0, CompileRun("undefined")->IntegerValue(env.local()).FromJust());
1943}
1944
1945static void GetNirk(Local<String> name,
1946 const v8::PropertyCallbackInfo<v8::Value>& info) {
1947 ApiTestFuzzer::Fuzz();
1948 info.GetReturnValue().Set(v8_num(900));
1949}
1950
1951static void GetRino(Local<String> name,
1952 const v8::PropertyCallbackInfo<v8::Value>& info) {
1953 ApiTestFuzzer::Fuzz();
1954 info.GetReturnValue().Set(v8_num(560));
1955}
1956
1957enum ObjectInstantiationMode {
1958 // Create object using ObjectTemplate::NewInstance.
1959 ObjectTemplate_NewInstance,
1960 // Create object using FunctionTemplate::NewInstance on constructor.
1961 Constructor_GetFunction_NewInstance,
1962 // Create object using new operator on constructor.
1963 Constructor_GetFunction_New
1964};
1965
1966// Test object instance creation using a function template with an instance
1967// template inherited from another function template with accessors and data
1968// properties in prototype template.
1969static void TestObjectTemplateInheritedWithPrototype(
1970 ObjectInstantiationMode mode) {
1971 LocalContext env;
1972 v8::Isolate* isolate = CcTest::isolate();
1973 v8::HandleScope scope(isolate);
1974
1975 Local<v8::FunctionTemplate> fun_A = v8::FunctionTemplate::New(isolate);
1976 fun_A->SetClassName(v8_str("A"));
1977 v8::Local<v8::ObjectTemplate> prototype_templ = fun_A->PrototypeTemplate();
1978 prototype_templ->Set(isolate, "a", v8_num(113));
1979 prototype_templ->SetNativeDataProperty(v8_str("nirk"), GetNirk);
1980 prototype_templ->Set(isolate, "b", v8_num(153));
1981
1982 Local<v8::FunctionTemplate> fun_B = v8::FunctionTemplate::New(isolate);
1983 v8::Local<v8::String> class_name = v8_str("B");
1984 fun_B->SetClassName(class_name);
1985 fun_B->Inherit(fun_A);
1986 prototype_templ = fun_B->PrototypeTemplate();
1987 prototype_templ->Set(isolate, "c", v8_num(713));
1988 prototype_templ->SetNativeDataProperty(v8_str("rino"), GetRino);
1989 prototype_templ->Set(isolate, "d", v8_num(753));
1990
1991 Local<ObjectTemplate> templ = fun_B->InstanceTemplate();
1992 templ->Set(isolate, "x", v8_num(10));
1993 templ->Set(isolate, "y", v8_num(13));
1994
1995 // Perform several iterations to trigger creation from cached boilerplate.
1996 for (int i = 0; i < 3; i++) {
1997 Local<v8::Object> instance;
1998 switch (mode) {
1999 case ObjectTemplate_NewInstance:
2000 instance = templ->NewInstance(env.local()).ToLocalChecked();
2001 break;
2002
2003 case Constructor_GetFunction_NewInstance: {
2004 Local<v8::Function> function_B =
2005 fun_B->GetFunction(env.local()).ToLocalChecked();
2006 instance = function_B->NewInstance(env.local()).ToLocalChecked();
2007 break;
2008 }
2009 case Constructor_GetFunction_New: {
2010 Local<v8::Function> function_B =
2011 fun_B->GetFunction(env.local()).ToLocalChecked();
2012 if (i == 0) {
2013 CHECK(env->Global()
2014 ->Set(env.local(), class_name, function_B)
2015 .FromJust());
2016 }
2017 instance =
2018 CompileRun("new B()")->ToObject(env.local()).ToLocalChecked();
2019 break;
2020 }
2021 default:
2022 UNREACHABLE();
2023 }
2024
2025 CHECK(class_name->StrictEquals(instance->GetConstructorName()));
2026 CHECK(env->Global()->Set(env.local(), v8_str("o"), instance).FromJust());
2027
2028 CHECK_EQ(10, CompileRun("o.x")->IntegerValue(env.local()).FromJust());
2029 CHECK_EQ(13, CompileRun("o.y")->IntegerValue(env.local()).FromJust());
2030
2031 CHECK_EQ(113, CompileRun("o.a")->IntegerValue(env.local()).FromJust());
2032 CHECK_EQ(900, CompileRun("o.nirk")->IntegerValue(env.local()).FromJust());
2033 CHECK_EQ(153, CompileRun("o.b")->IntegerValue(env.local()).FromJust());
2034 CHECK_EQ(713, CompileRun("o.c")->IntegerValue(env.local()).FromJust());
2035 CHECK_EQ(560, CompileRun("o.rino")->IntegerValue(env.local()).FromJust());
2036 CHECK_EQ(753, CompileRun("o.d")->IntegerValue(env.local()).FromJust());
2037 }
2038}
2039
2040THREADED_TEST(TestObjectTemplateInheritedWithAccessorsInPrototype1) {
2041 TestObjectTemplateInheritedWithPrototype(ObjectTemplate_NewInstance);
2042}
2043
2044THREADED_TEST(TestObjectTemplateInheritedWithAccessorsInPrototype2) {
2045 TestObjectTemplateInheritedWithPrototype(Constructor_GetFunction_NewInstance);
2046}
2047
2048THREADED_TEST(TestObjectTemplateInheritedWithAccessorsInPrototype3) {
2049 TestObjectTemplateInheritedWithPrototype(Constructor_GetFunction_New);
2050}
2051
2052// Test object instance creation using a function template without an instance
2053// template inherited from another function template.
2054static void TestObjectTemplateInheritedWithoutInstanceTemplate(
2055 ObjectInstantiationMode mode) {
2056 LocalContext env;
2057 v8::Isolate* isolate = CcTest::isolate();
2058 v8::HandleScope scope(isolate);
2059
2060 Local<v8::FunctionTemplate> fun_A = v8::FunctionTemplate::New(isolate);
2061 fun_A->SetClassName(v8_str("A"));
2062
2063 Local<ObjectTemplate> templ_A = fun_A->InstanceTemplate();
2064 templ_A->SetNativeDataProperty(v8_str("nirk"), GetNirk);
2065 templ_A->SetNativeDataProperty(v8_str("rino"), GetRino);
2066
2067 Local<v8::FunctionTemplate> fun_B = v8::FunctionTemplate::New(isolate);
2068 v8::Local<v8::String> class_name = v8_str("B");
2069 fun_B->SetClassName(class_name);
2070 fun_B->Inherit(fun_A);
2071
2072 // Perform several iterations to trigger creation from cached boilerplate.
2073 for (int i = 0; i < 3; i++) {
2074 Local<v8::Object> instance;
2075 switch (mode) {
2076 case Constructor_GetFunction_NewInstance: {
2077 Local<v8::Function> function_B =
2078 fun_B->GetFunction(env.local()).ToLocalChecked();
2079 instance = function_B->NewInstance(env.local()).ToLocalChecked();
2080 break;
2081 }
2082 case Constructor_GetFunction_New: {
2083 Local<v8::Function> function_B =
2084 fun_B->GetFunction(env.local()).ToLocalChecked();
2085 if (i == 0) {
2086 CHECK(env->Global()
2087 ->Set(env.local(), class_name, function_B)
2088 .FromJust());
2089 }
2090 instance =
2091 CompileRun("new B()")->ToObject(env.local()).ToLocalChecked();
2092 break;
2093 }
2094 default:
2095 UNREACHABLE();
2096 }
2097
2098 CHECK(class_name->StrictEquals(instance->GetConstructorName()));
2099 CHECK(env->Global()->Set(env.local(), v8_str("o"), instance).FromJust());
2100
2101 CHECK_EQ(900, CompileRun("o.nirk")->IntegerValue(env.local()).FromJust());
2102 CHECK_EQ(560, CompileRun("o.rino")->IntegerValue(env.local()).FromJust());
2103 }
2104}
2105
2106THREADED_TEST(TestObjectTemplateInheritedWithPrototype1) {
2107 TestObjectTemplateInheritedWithoutInstanceTemplate(
2108 Constructor_GetFunction_NewInstance);
2109}
2110
2111THREADED_TEST(TestObjectTemplateInheritedWithPrototype2) {
2112 TestObjectTemplateInheritedWithoutInstanceTemplate(
2113 Constructor_GetFunction_New);
2114}
Steve Blocka7e24c12009-10-30 11:49:00 +00002115
Ben Murdochc5610432016-08-08 18:44:38 +01002116THREADED_TEST(TestObjectTemplateClassInheritance) {
2117 LocalContext env;
2118 v8::Isolate* isolate = CcTest::isolate();
2119 v8::HandleScope scope(isolate);
2120
2121 Local<v8::FunctionTemplate> fun_A = v8::FunctionTemplate::New(isolate);
2122 fun_A->SetClassName(v8_str("A"));
2123
2124 Local<ObjectTemplate> templ_A = fun_A->InstanceTemplate();
2125 templ_A->SetNativeDataProperty(v8_str("nirk"), GetNirk);
2126 templ_A->SetNativeDataProperty(v8_str("rino"), GetRino);
2127
2128 Local<v8::FunctionTemplate> fun_B = v8::FunctionTemplate::New(isolate);
2129 v8::Local<v8::String> class_name = v8_str("B");
2130 fun_B->SetClassName(class_name);
2131 fun_B->Inherit(fun_A);
2132
2133 v8::Local<v8::String> subclass_name = v8_str("C");
2134 v8::Local<v8::Object> b_proto;
2135 v8::Local<v8::Object> c_proto;
2136 // Perform several iterations to make sure the cache doesn't break
2137 // subclassing.
2138 for (int i = 0; i < 3; i++) {
2139 Local<v8::Function> function_B =
2140 fun_B->GetFunction(env.local()).ToLocalChecked();
2141 if (i == 0) {
2142 CHECK(env->Global()->Set(env.local(), class_name, function_B).FromJust());
2143 CompileRun("class C extends B {}");
2144 b_proto =
2145 CompileRun("B.prototype")->ToObject(env.local()).ToLocalChecked();
2146 c_proto =
2147 CompileRun("C.prototype")->ToObject(env.local()).ToLocalChecked();
2148 CHECK(b_proto->Equals(env.local(), c_proto->GetPrototype()).FromJust());
2149 }
2150 Local<v8::Object> instance =
2151 CompileRun("new C()")->ToObject(env.local()).ToLocalChecked();
2152 CHECK(c_proto->Equals(env.local(), instance->GetPrototype()).FromJust());
2153
2154 CHECK(subclass_name->StrictEquals(instance->GetConstructorName()));
2155 CHECK(env->Global()->Set(env.local(), v8_str("o"), instance).FromJust());
2156
2157 CHECK_EQ(900, CompileRun("o.nirk")->IntegerValue(env.local()).FromJust());
2158 CHECK_EQ(560, CompileRun("o.rino")->IntegerValue(env.local()).FromJust());
2159 }
2160}
2161
2162static void NamedPropertyGetterWhichReturns42(
2163 Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
2164 info.GetReturnValue().Set(v8_num(42));
2165}
2166
2167THREADED_TEST(TestObjectTemplateReflectConstruct) {
2168 LocalContext env;
2169 v8::Isolate* isolate = CcTest::isolate();
2170 v8::HandleScope scope(isolate);
2171
2172 Local<v8::FunctionTemplate> fun_B = v8::FunctionTemplate::New(isolate);
2173 fun_B->InstanceTemplate()->SetHandler(
2174 v8::NamedPropertyHandlerConfiguration(NamedPropertyGetterWhichReturns42));
2175 v8::Local<v8::String> class_name = v8_str("B");
2176 fun_B->SetClassName(class_name);
2177
2178 v8::Local<v8::String> subclass_name = v8_str("C");
2179 v8::Local<v8::Object> b_proto;
2180 v8::Local<v8::Object> c_proto;
2181 // Perform several iterations to make sure the cache doesn't break
2182 // subclassing.
2183 for (int i = 0; i < 3; i++) {
2184 Local<v8::Function> function_B =
2185 fun_B->GetFunction(env.local()).ToLocalChecked();
2186 if (i == 0) {
2187 CHECK(env->Global()->Set(env.local(), class_name, function_B).FromJust());
2188 CompileRun("function C() {}");
2189 c_proto =
2190 CompileRun("C.prototype")->ToObject(env.local()).ToLocalChecked();
2191 }
2192 Local<v8::Object> instance = CompileRun("Reflect.construct(B, [], C)")
2193 ->ToObject(env.local())
2194 .ToLocalChecked();
2195 CHECK(c_proto->Equals(env.local(), instance->GetPrototype()).FromJust());
2196
2197 CHECK(subclass_name->StrictEquals(instance->GetConstructorName()));
2198 CHECK(env->Global()->Set(env.local(), v8_str("o"), instance).FromJust());
2199
2200 CHECK_EQ(42, CompileRun("o.nirk")->IntegerValue(env.local()).FromJust());
2201 CHECK_EQ(42, CompileRun("o.rino")->IntegerValue(env.local()).FromJust());
2202 }
2203}
2204
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002205static void GetFlabby(const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002206 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002207 args.GetReturnValue().Set(v8_num(17.2));
Steve Blocka7e24c12009-10-30 11:49:00 +00002208}
2209
2210
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002211static void GetKnurd(Local<String> property,
2212 const v8::PropertyCallbackInfo<v8::Value>& info) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002213 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002214 info.GetReturnValue().Set(v8_num(15.2));
Steve Blocka7e24c12009-10-30 11:49:00 +00002215}
2216
2217
2218THREADED_TEST(DescriptorInheritance) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002219 v8::Isolate* isolate = CcTest::isolate();
2220 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002221 v8::Local<v8::FunctionTemplate> super = v8::FunctionTemplate::New(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002222 super->PrototypeTemplate()->Set(isolate, "flabby",
2223 v8::FunctionTemplate::New(isolate,
2224 GetFlabby));
2225 super->PrototypeTemplate()->Set(isolate, "PI", v8_num(3.14));
Steve Blocka7e24c12009-10-30 11:49:00 +00002226
2227 super->InstanceTemplate()->SetAccessor(v8_str("knurd"), GetKnurd);
2228
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002229 v8::Local<v8::FunctionTemplate> base1 = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00002230 base1->Inherit(super);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002231 base1->PrototypeTemplate()->Set(isolate, "v1", v8_num(20.1));
Steve Blocka7e24c12009-10-30 11:49:00 +00002232
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002233 v8::Local<v8::FunctionTemplate> base2 = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00002234 base2->Inherit(super);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002235 base2->PrototypeTemplate()->Set(isolate, "v2", v8_num(10.1));
Steve Blocka7e24c12009-10-30 11:49:00 +00002236
2237 LocalContext env;
2238
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002239 CHECK(env->Global()
2240 ->Set(env.local(), v8_str("s"),
2241 super->GetFunction(env.local()).ToLocalChecked())
2242 .FromJust());
2243 CHECK(env->Global()
2244 ->Set(env.local(), v8_str("base1"),
2245 base1->GetFunction(env.local()).ToLocalChecked())
2246 .FromJust());
2247 CHECK(env->Global()
2248 ->Set(env.local(), v8_str("base2"),
2249 base2->GetFunction(env.local()).ToLocalChecked())
2250 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00002251
2252 // Checks right __proto__ chain.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002253 CHECK(CompileRun("base1.prototype.__proto__ == s.prototype")
2254 ->BooleanValue(env.local())
2255 .FromJust());
2256 CHECK(CompileRun("base2.prototype.__proto__ == s.prototype")
2257 ->BooleanValue(env.local())
2258 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00002259
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002260 CHECK(v8_compile("s.prototype.PI == 3.14")
2261 ->Run(env.local())
2262 .ToLocalChecked()
2263 ->BooleanValue(env.local())
2264 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00002265
2266 // Instance accessor should not be visible on function object or its prototype
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002267 CHECK(
2268 CompileRun("s.knurd == undefined")->BooleanValue(env.local()).FromJust());
2269 CHECK(CompileRun("s.prototype.knurd == undefined")
2270 ->BooleanValue(env.local())
2271 .FromJust());
2272 CHECK(CompileRun("base1.prototype.knurd == undefined")
2273 ->BooleanValue(env.local())
2274 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00002275
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002276 CHECK(env->Global()
2277 ->Set(env.local(), v8_str("obj"), base1->GetFunction(env.local())
2278 .ToLocalChecked()
2279 ->NewInstance(env.local())
2280 .ToLocalChecked())
2281 .FromJust());
Ben Murdoch097c5b22016-05-18 11:27:45 +01002282 CHECK_EQ(17.2,
2283 CompileRun("obj.flabby()")->NumberValue(env.local()).FromJust());
2284 CHECK(CompileRun("'flabby' in obj")->BooleanValue(env.local()).FromJust());
2285 CHECK_EQ(15.2, CompileRun("obj.knurd")->NumberValue(env.local()).FromJust());
2286 CHECK(CompileRun("'knurd' in obj")->BooleanValue(env.local()).FromJust());
2287 CHECK_EQ(20.1, CompileRun("obj.v1")->NumberValue(env.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00002288
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002289 CHECK(env->Global()
2290 ->Set(env.local(), v8_str("obj2"), base2->GetFunction(env.local())
2291 .ToLocalChecked()
2292 ->NewInstance(env.local())
2293 .ToLocalChecked())
2294 .FromJust());
Ben Murdoch097c5b22016-05-18 11:27:45 +01002295 CHECK_EQ(17.2,
2296 CompileRun("obj2.flabby()")->NumberValue(env.local()).FromJust());
2297 CHECK(CompileRun("'flabby' in obj2")->BooleanValue(env.local()).FromJust());
2298 CHECK_EQ(15.2, CompileRun("obj2.knurd")->NumberValue(env.local()).FromJust());
2299 CHECK(CompileRun("'knurd' in obj2")->BooleanValue(env.local()).FromJust());
2300 CHECK_EQ(10.1, CompileRun("obj2.v2")->NumberValue(env.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00002301
2302 // base1 and base2 cannot cross reference to each's prototype
Ben Murdoch097c5b22016-05-18 11:27:45 +01002303 CHECK(CompileRun("obj.v2")->IsUndefined());
2304 CHECK(CompileRun("obj2.v1")->IsUndefined());
2305}
2306
2307THREADED_TEST(DescriptorInheritance2) {
2308 LocalContext env;
2309 v8::Isolate* isolate = CcTest::isolate();
2310 v8::HandleScope scope(isolate);
2311 v8::Local<v8::FunctionTemplate> fun_A = v8::FunctionTemplate::New(isolate);
2312 fun_A->SetClassName(v8_str("A"));
2313 fun_A->InstanceTemplate()->SetNativeDataProperty(v8_str("knurd1"), GetKnurd);
2314 fun_A->InstanceTemplate()->SetNativeDataProperty(v8_str("nirk1"), GetNirk);
2315 fun_A->InstanceTemplate()->SetNativeDataProperty(v8_str("rino1"), GetRino);
2316
2317 v8::Local<v8::FunctionTemplate> fun_B = v8::FunctionTemplate::New(isolate);
2318 fun_B->SetClassName(v8_str("B"));
2319 fun_B->Inherit(fun_A);
2320
2321 v8::Local<v8::FunctionTemplate> fun_C = v8::FunctionTemplate::New(isolate);
2322 fun_C->SetClassName(v8_str("C"));
2323 fun_C->Inherit(fun_B);
2324 fun_C->InstanceTemplate()->SetNativeDataProperty(v8_str("knurd2"), GetKnurd);
2325 fun_C->InstanceTemplate()->SetNativeDataProperty(v8_str("nirk2"), GetNirk);
2326 fun_C->InstanceTemplate()->SetNativeDataProperty(v8_str("rino2"), GetRino);
2327
2328 v8::Local<v8::FunctionTemplate> fun_D = v8::FunctionTemplate::New(isolate);
2329 fun_D->SetClassName(v8_str("D"));
2330 fun_D->Inherit(fun_C);
2331
2332 v8::Local<v8::FunctionTemplate> fun_E = v8::FunctionTemplate::New(isolate);
2333 fun_E->SetClassName(v8_str("E"));
2334 fun_E->Inherit(fun_D);
2335 fun_E->InstanceTemplate()->SetNativeDataProperty(v8_str("knurd3"), GetKnurd);
2336 fun_E->InstanceTemplate()->SetNativeDataProperty(v8_str("nirk3"), GetNirk);
2337 fun_E->InstanceTemplate()->SetNativeDataProperty(v8_str("rino3"), GetRino);
2338
2339 v8::Local<v8::FunctionTemplate> fun_F = v8::FunctionTemplate::New(isolate);
2340 fun_F->SetClassName(v8_str("F"));
2341 fun_F->Inherit(fun_E);
2342 v8::Local<v8::ObjectTemplate> templ = fun_F->InstanceTemplate();
2343 const int kDataPropertiesNumber = 100;
2344 for (int i = 0; i < kDataPropertiesNumber; i++) {
2345 v8::Local<v8::Value> val = v8_num(i);
2346 v8::Local<v8::String> val_str = val->ToString(env.local()).ToLocalChecked();
2347 v8::Local<v8::String> name = String::Concat(v8_str("p"), val_str);
2348
2349 templ->Set(name, val);
2350 templ->Set(val_str, val);
2351 }
2352
2353 CHECK(env->Global()
2354 ->Set(env.local(), v8_str("F"),
2355 fun_F->GetFunction(env.local()).ToLocalChecked())
2356 .FromJust());
2357
2358 v8::Local<v8::Script> script = v8_compile("o = new F()");
2359
2360 for (int i = 0; i < 100; i++) {
2361 v8::HandleScope scope(isolate);
2362 script->Run(env.local()).ToLocalChecked();
2363 }
2364 v8::Local<v8::Object> object = script->Run(env.local())
2365 .ToLocalChecked()
2366 ->ToObject(env.local())
2367 .ToLocalChecked();
2368
2369 CHECK_EQ(15.2, CompileRun("o.knurd1")->NumberValue(env.local()).FromJust());
2370 CHECK_EQ(15.2, CompileRun("o.knurd2")->NumberValue(env.local()).FromJust());
2371 CHECK_EQ(15.2, CompileRun("o.knurd3")->NumberValue(env.local()).FromJust());
2372
2373 CHECK_EQ(900, CompileRun("o.nirk1")->IntegerValue(env.local()).FromJust());
2374 CHECK_EQ(900, CompileRun("o.nirk2")->IntegerValue(env.local()).FromJust());
2375 CHECK_EQ(900, CompileRun("o.nirk3")->IntegerValue(env.local()).FromJust());
2376
2377 CHECK_EQ(560, CompileRun("o.rino1")->IntegerValue(env.local()).FromJust());
2378 CHECK_EQ(560, CompileRun("o.rino2")->IntegerValue(env.local()).FromJust());
2379 CHECK_EQ(560, CompileRun("o.rino3")->IntegerValue(env.local()).FromJust());
2380
2381 for (int i = 0; i < kDataPropertiesNumber; i++) {
2382 v8::Local<v8::Value> val = v8_num(i);
2383 v8::Local<v8::String> val_str = val->ToString(env.local()).ToLocalChecked();
2384 v8::Local<v8::String> name = String::Concat(v8_str("p"), val_str);
2385
2386 CHECK_EQ(i, object->Get(env.local(), name)
2387 .ToLocalChecked()
2388 ->IntegerValue(env.local())
2389 .FromJust());
2390 CHECK_EQ(i, object->Get(env.local(), val)
2391 .ToLocalChecked()
2392 ->IntegerValue(env.local())
2393 .FromJust());
2394 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002395}
2396
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002397
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002398// Helper functions for Interceptor/Accessor interaction tests
2399
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002400void SimpleAccessorGetter(Local<String> name,
2401 const v8::PropertyCallbackInfo<v8::Value>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002402 Local<Object> self = Local<Object>::Cast(info.This());
2403 info.GetReturnValue().Set(self->Get(info.GetIsolate()->GetCurrentContext(),
2404 String::Concat(v8_str("accessor_"), name))
2405 .ToLocalChecked());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002406}
2407
2408void SimpleAccessorSetter(Local<String> name, Local<Value> value,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002409 const v8::PropertyCallbackInfo<void>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002410 Local<Object> self = Local<Object>::Cast(info.This());
2411 CHECK(self->Set(info.GetIsolate()->GetCurrentContext(),
2412 String::Concat(v8_str("accessor_"), name), value)
2413 .FromJust());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002414}
2415
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002416void SymbolAccessorGetter(Local<Name> name,
2417 const v8::PropertyCallbackInfo<v8::Value>& info) {
2418 CHECK(name->IsSymbol());
2419 Local<Symbol> sym = Local<Symbol>::Cast(name);
2420 if (sym->Name()->IsUndefined())
2421 return;
2422 SimpleAccessorGetter(Local<String>::Cast(sym->Name()), info);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002423}
2424
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002425void SymbolAccessorSetter(Local<Name> name, Local<Value> value,
2426 const v8::PropertyCallbackInfo<void>& info) {
2427 CHECK(name->IsSymbol());
2428 Local<Symbol> sym = Local<Symbol>::Cast(name);
2429 if (sym->Name()->IsUndefined())
2430 return;
2431 SimpleAccessorSetter(Local<String>::Cast(sym->Name()), value, info);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002432}
2433
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002434void SymbolAccessorGetterReturnsDefault(
2435 Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
2436 CHECK(name->IsSymbol());
2437 Local<Symbol> sym = Local<Symbol>::Cast(name);
2438 if (sym->Name()->IsUndefined()) return;
2439 info.GetReturnValue().Set(info.Data());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002440}
2441
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002442static void ThrowingSymbolAccessorGetter(
2443 Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
2444 info.GetReturnValue().Set(info.GetIsolate()->ThrowException(name));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002445}
2446
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002447
Ben Murdoch097c5b22016-05-18 11:27:45 +01002448THREADED_TEST(AccessorIsPreservedOnAttributeChange) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002449 v8::Isolate* isolate = CcTest::isolate();
2450 v8::HandleScope scope(isolate);
2451 LocalContext env;
2452 v8::Local<v8::Value> res = CompileRun("var a = []; a;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002453 i::Handle<i::JSReceiver> a(v8::Utils::OpenHandle(v8::Object::Cast(*res)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002454 CHECK(a->map()->instance_descriptors()->IsFixedArray());
2455 CHECK_GT(i::FixedArray::cast(a->map()->instance_descriptors())->length(), 0);
2456 CompileRun("Object.defineProperty(a, 'length', { writable: false });");
2457 CHECK_EQ(i::FixedArray::cast(a->map()->instance_descriptors())->length(), 0);
Ben Murdoch097c5b22016-05-18 11:27:45 +01002458 // But we should still have an AccessorInfo.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002459 i::Handle<i::String> name(v8::Utils::OpenHandle(*v8_str("length")));
2460 i::LookupIterator it(a, name, i::LookupIterator::OWN_SKIP_INTERCEPTOR);
2461 CHECK_EQ(i::LookupIterator::ACCESSOR, it.state());
Ben Murdoch097c5b22016-05-18 11:27:45 +01002462 CHECK(it.GetAccessors()->IsAccessorInfo());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002463}
2464
2465
Steve Blocka7e24c12009-10-30 11:49:00 +00002466THREADED_TEST(UndefinedIsNotEnumerable) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002467 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002468 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002469 v8::Local<Value> result = CompileRun("this.propertyIsEnumerable(undefined)");
Steve Blocka7e24c12009-10-30 11:49:00 +00002470 CHECK(result->IsFalse());
2471}
2472
2473
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002474v8::Local<Script> call_recursively_script;
2475static const int kTargetRecursionDepth = 150; // near maximum
Steve Blocka7e24c12009-10-30 11:49:00 +00002476
2477
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002478static void CallScriptRecursivelyCall(
2479 const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002480 ApiTestFuzzer::Fuzz();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002481 v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
2482 int depth = args.This()
2483 ->Get(context, v8_str("depth"))
2484 .ToLocalChecked()
2485 ->Int32Value(context)
2486 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002487 if (depth == kTargetRecursionDepth) return;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002488 CHECK(args.This()
2489 ->Set(context, v8_str("depth"),
2490 v8::Integer::New(args.GetIsolate(), depth + 1))
2491 .FromJust());
2492 args.GetReturnValue().Set(
2493 call_recursively_script->Run(context).ToLocalChecked());
Steve Blocka7e24c12009-10-30 11:49:00 +00002494}
2495
2496
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002497static void CallFunctionRecursivelyCall(
2498 const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002499 ApiTestFuzzer::Fuzz();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002500 v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
2501 int depth = args.This()
2502 ->Get(context, v8_str("depth"))
2503 .ToLocalChecked()
2504 ->Int32Value(context)
2505 .FromJust();
Steve Blocka7e24c12009-10-30 11:49:00 +00002506 if (depth == kTargetRecursionDepth) {
2507 printf("[depth = %d]\n", depth);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002508 return;
Steve Blocka7e24c12009-10-30 11:49:00 +00002509 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002510 CHECK(args.This()
2511 ->Set(context, v8_str("depth"),
2512 v8::Integer::New(args.GetIsolate(), depth + 1))
2513 .FromJust());
2514 v8::Local<Value> function =
2515 args.This()
2516 ->Get(context, v8_str("callFunctionRecursively"))
2517 .ToLocalChecked();
2518 args.GetReturnValue().Set(function.As<Function>()
2519 ->Call(context, args.This(), 0, NULL)
2520 .ToLocalChecked());
Steve Blocka7e24c12009-10-30 11:49:00 +00002521}
2522
2523
2524THREADED_TEST(DeepCrossLanguageRecursion) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002525 v8::Isolate* isolate = CcTest::isolate();
2526 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002527 v8::Local<v8::ObjectTemplate> global = ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00002528 global->Set(v8_str("callScriptRecursively"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002529 v8::FunctionTemplate::New(isolate, CallScriptRecursivelyCall));
Steve Blocka7e24c12009-10-30 11:49:00 +00002530 global->Set(v8_str("callFunctionRecursively"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002531 v8::FunctionTemplate::New(isolate, CallFunctionRecursivelyCall));
Steve Blocka7e24c12009-10-30 11:49:00 +00002532 LocalContext env(NULL, global);
2533
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002534 CHECK(env->Global()
2535 ->Set(env.local(), v8_str("depth"), v8::Integer::New(isolate, 0))
2536 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00002537 call_recursively_script = v8_compile("callScriptRecursively()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002538 call_recursively_script->Run(env.local()).ToLocalChecked();
2539 call_recursively_script = v8::Local<Script>();
Steve Blocka7e24c12009-10-30 11:49:00 +00002540
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002541 CHECK(env->Global()
2542 ->Set(env.local(), v8_str("depth"), v8::Integer::New(isolate, 0))
2543 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002544 CompileRun("callFunctionRecursively()");
Steve Blocka7e24c12009-10-30 11:49:00 +00002545}
2546
2547
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002548static void ThrowingPropertyHandlerGet(
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002549 Local<Name> key, const v8::PropertyCallbackInfo<v8::Value>& info) {
2550 // Since this interceptor is used on "with" objects, the runtime will look up
2551 // @@unscopables. Punt.
2552 if (key->IsSymbol()) return;
Steve Blocka7e24c12009-10-30 11:49:00 +00002553 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002554 info.GetReturnValue().Set(info.GetIsolate()->ThrowException(key));
Steve Blocka7e24c12009-10-30 11:49:00 +00002555}
2556
2557
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002558static void ThrowingPropertyHandlerSet(
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002559 Local<Name> key, Local<Value>,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002560 const v8::PropertyCallbackInfo<v8::Value>& info) {
2561 info.GetIsolate()->ThrowException(key);
2562 info.GetReturnValue().SetUndefined(); // not the same as empty handle
Steve Blocka7e24c12009-10-30 11:49:00 +00002563}
2564
2565
2566THREADED_TEST(CallbackExceptionRegression) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002567 v8::Isolate* isolate = CcTest::isolate();
2568 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002569 v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002570 obj->SetHandler(v8::NamedPropertyHandlerConfiguration(
2571 ThrowingPropertyHandlerGet, ThrowingPropertyHandlerSet));
Steve Blocka7e24c12009-10-30 11:49:00 +00002572 LocalContext env;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002573 CHECK(env->Global()
2574 ->Set(env.local(), v8_str("obj"),
2575 obj->NewInstance(env.local()).ToLocalChecked())
2576 .FromJust());
2577 v8::Local<Value> otto =
2578 CompileRun("try { with (obj) { otto; } } catch (e) { e; }");
2579 CHECK(v8_str("otto")->Equals(env.local(), otto).FromJust());
2580 v8::Local<Value> netto =
2581 CompileRun("try { with (obj) { netto = 4; } } catch (e) { e; }");
2582 CHECK(v8_str("netto")->Equals(env.local(), netto).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00002583}
2584
2585
Steve Blocka7e24c12009-10-30 11:49:00 +00002586THREADED_TEST(FunctionPrototype) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002587 v8::Isolate* isolate = CcTest::isolate();
2588 v8::HandleScope scope(isolate);
2589 Local<v8::FunctionTemplate> Foo = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00002590 Foo->PrototypeTemplate()->Set(v8_str("plak"), v8_num(321));
2591 LocalContext env;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002592 CHECK(env->Global()
2593 ->Set(env.local(), v8_str("Foo"),
2594 Foo->GetFunction(env.local()).ToLocalChecked())
2595 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002596 Local<Script> script = v8_compile("Foo.prototype.plak");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002597 CHECK_EQ(v8_run_int32value(script), 321);
Steve Blocka7e24c12009-10-30 11:49:00 +00002598}
2599
2600
2601THREADED_TEST(InternalFields) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002602 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002603 v8::Isolate* isolate = env->GetIsolate();
2604 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00002605
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002606 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00002607 Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
2608 instance_templ->SetInternalFieldCount(1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002609 Local<v8::Object> obj = templ->GetFunction(env.local())
2610 .ToLocalChecked()
2611 ->NewInstance(env.local())
2612 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00002613 CHECK_EQ(1, obj->InternalFieldCount());
2614 CHECK(obj->GetInternalField(0)->IsUndefined());
2615 obj->SetInternalField(0, v8_num(17));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002616 CHECK_EQ(17, obj->GetInternalField(0)->Int32Value(env.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00002617}
2618
2619
Steve Block6ded16b2010-05-10 14:33:55 +01002620THREADED_TEST(GlobalObjectInternalFields) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002621 v8::Isolate* isolate = CcTest::isolate();
2622 v8::HandleScope scope(isolate);
2623 Local<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New(isolate);
Steve Block6ded16b2010-05-10 14:33:55 +01002624 global_template->SetInternalFieldCount(1);
2625 LocalContext env(NULL, global_template);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002626 v8::Local<v8::Object> global_proxy = env->Global();
2627 v8::Local<v8::Object> global = global_proxy->GetPrototype().As<v8::Object>();
Steve Block6ded16b2010-05-10 14:33:55 +01002628 CHECK_EQ(1, global->InternalFieldCount());
2629 CHECK(global->GetInternalField(0)->IsUndefined());
2630 global->SetInternalField(0, v8_num(17));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002631 CHECK_EQ(17, global->GetInternalField(0)->Int32Value(env.local()).FromJust());
Steve Block6ded16b2010-05-10 14:33:55 +01002632}
2633
2634
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002635THREADED_TEST(GlobalObjectHasRealIndexedProperty) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002636 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002637 v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00002638
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002639 v8::Local<v8::Object> global = env->Global();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002640 CHECK(global->Set(env.local(), 0, v8_str("value")).FromJust());
2641 CHECK(global->HasRealIndexedProperty(env.local(), 0).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00002642}
2643
2644
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002645static void CheckAlignedPointerInInternalField(Local<v8::Object> obj,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002646 void* value) {
2647 CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(value) & 0x1));
2648 obj->SetAlignedPointerInInternalField(0, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002649 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002650 CHECK_EQ(value, obj->GetAlignedPointerFromInternalField(0));
2651}
Steve Block3ce2e202009-11-05 08:53:23 +00002652
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002653
2654THREADED_TEST(InternalFieldsAlignedPointers) {
2655 LocalContext env;
2656 v8::Isolate* isolate = env->GetIsolate();
2657 v8::HandleScope scope(isolate);
2658
2659 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
Steve Block3ce2e202009-11-05 08:53:23 +00002660 Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
2661 instance_templ->SetInternalFieldCount(1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002662 Local<v8::Object> obj = templ->GetFunction(env.local())
2663 .ToLocalChecked()
2664 ->NewInstance(env.local())
2665 .ToLocalChecked();
Steve Block3ce2e202009-11-05 08:53:23 +00002666 CHECK_EQ(1, obj->InternalFieldCount());
Steve Block3ce2e202009-11-05 08:53:23 +00002667
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002668 CheckAlignedPointerInInternalField(obj, NULL);
Steve Block3ce2e202009-11-05 08:53:23 +00002669
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002670 int* heap_allocated = new int[100];
2671 CheckAlignedPointerInInternalField(obj, heap_allocated);
2672 delete[] heap_allocated;
Steve Block3ce2e202009-11-05 08:53:23 +00002673
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002674 int stack_allocated[100];
2675 CheckAlignedPointerInInternalField(obj, stack_allocated);
Steve Block3ce2e202009-11-05 08:53:23 +00002676
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002677 void* huge = reinterpret_cast<void*>(~static_cast<uintptr_t>(1));
2678 CheckAlignedPointerInInternalField(obj, huge);
Steve Block3ce2e202009-11-05 08:53:23 +00002679
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002680 v8::Global<v8::Object> persistent(isolate, obj);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002681 CHECK_EQ(1, Object::InternalFieldCount(persistent));
2682 CHECK_EQ(huge, Object::GetAlignedPointerFromInternalField(persistent, 0));
2683}
Steve Block3ce2e202009-11-05 08:53:23 +00002684
Steve Block3ce2e202009-11-05 08:53:23 +00002685
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002686static void CheckAlignedPointerInEmbedderData(LocalContext* env, int index,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002687 void* value) {
2688 CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(value) & 0x1));
2689 (*env)->SetAlignedPointerInEmbedderData(index, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002690 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002691 CHECK_EQ(value, (*env)->GetAlignedPointerFromEmbedderData(index));
2692}
2693
2694
2695static void* AlignedTestPointer(int i) {
2696 return reinterpret_cast<void*>(i * 1234);
2697}
2698
2699
2700THREADED_TEST(EmbedderDataAlignedPointers) {
2701 LocalContext env;
2702 v8::HandleScope scope(env->GetIsolate());
2703
2704 CheckAlignedPointerInEmbedderData(&env, 0, NULL);
2705
2706 int* heap_allocated = new int[100];
2707 CheckAlignedPointerInEmbedderData(&env, 1, heap_allocated);
2708 delete[] heap_allocated;
2709
2710 int stack_allocated[100];
2711 CheckAlignedPointerInEmbedderData(&env, 2, stack_allocated);
2712
2713 void* huge = reinterpret_cast<void*>(~static_cast<uintptr_t>(1));
2714 CheckAlignedPointerInEmbedderData(&env, 3, huge);
2715
2716 // Test growing of the embedder data's backing store.
2717 for (int i = 0; i < 100; i++) {
2718 env->SetAlignedPointerInEmbedderData(i, AlignedTestPointer(i));
2719 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002720 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002721 for (int i = 0; i < 100; i++) {
2722 CHECK_EQ(AlignedTestPointer(i), env->GetAlignedPointerFromEmbedderData(i));
2723 }
2724}
2725
2726
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002727static void CheckEmbedderData(LocalContext* env, int index,
2728 v8::Local<Value> data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002729 (*env)->SetEmbedderData(index, data);
2730 CHECK((*env)->GetEmbedderData(index)->StrictEquals(data));
2731}
2732
2733
2734THREADED_TEST(EmbedderData) {
2735 LocalContext env;
2736 v8::Isolate* isolate = env->GetIsolate();
2737 v8::HandleScope scope(isolate);
2738
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002739 CheckEmbedderData(&env, 3, v8_str("The quick brown fox jumps"));
2740 CheckEmbedderData(&env, 2, v8_str("over the lazy dog."));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002741 CheckEmbedderData(&env, 1, v8::Number::New(isolate, 1.2345));
2742 CheckEmbedderData(&env, 0, v8::Boolean::New(isolate, true));
Steve Block3ce2e202009-11-05 08:53:23 +00002743}
2744
2745
Steve Blocka7e24c12009-10-30 11:49:00 +00002746THREADED_TEST(IdentityHash) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002747 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002748 v8::Isolate* isolate = env->GetIsolate();
2749 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00002750
2751 // Ensure that the test starts with an fresh heap to test whether the hash
2752 // code is based on the address.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002753 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002754 Local<v8::Object> obj = v8::Object::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00002755 int hash = obj->GetIdentityHash();
2756 int hash1 = obj->GetIdentityHash();
2757 CHECK_EQ(hash, hash1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002758 int hash2 = v8::Object::New(isolate)->GetIdentityHash();
Steve Blocka7e24c12009-10-30 11:49:00 +00002759 // Since the identity hash is essentially a random number two consecutive
2760 // objects should not be assigned the same hash code. If the test below fails
2761 // the random number generator should be evaluated.
2762 CHECK_NE(hash, hash2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002763 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002764 int hash3 = v8::Object::New(isolate)->GetIdentityHash();
Steve Blocka7e24c12009-10-30 11:49:00 +00002765 // Make sure that the identity hash is not based on the initial address of
2766 // the object alone. If the test below fails the random number generator
2767 // should be evaluated.
2768 CHECK_NE(hash, hash3);
2769 int hash4 = obj->GetIdentityHash();
2770 CHECK_EQ(hash, hash4);
Steve Block1e0659c2011-05-24 12:43:12 +01002771
2772 // Check identity hashes behaviour in the presence of JS accessors.
2773 // Put a getter for 'v8::IdentityHash' on the Object's prototype:
2774 {
2775 CompileRun("Object.prototype['v8::IdentityHash'] = 42;\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002776 Local<v8::Object> o1 = v8::Object::New(isolate);
2777 Local<v8::Object> o2 = v8::Object::New(isolate);
Steve Block1e0659c2011-05-24 12:43:12 +01002778 CHECK_NE(o1->GetIdentityHash(), o2->GetIdentityHash());
2779 }
2780 {
2781 CompileRun(
2782 "function cnst() { return 42; };\n"
2783 "Object.prototype.__defineGetter__('v8::IdentityHash', cnst);\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002784 Local<v8::Object> o1 = v8::Object::New(isolate);
2785 Local<v8::Object> o2 = v8::Object::New(isolate);
Steve Block1e0659c2011-05-24 12:43:12 +01002786 CHECK_NE(o1->GetIdentityHash(), o2->GetIdentityHash());
2787 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002788}
2789
2790
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002791void GlobalProxyIdentityHash(bool set_in_js) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002792 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002793 v8::Isolate* isolate = env->GetIsolate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002794 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002795 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002796 Local<Object> global_proxy = env->Global();
2797 i::Handle<i::Object> i_global_proxy = v8::Utils::OpenHandle(*global_proxy);
2798 CHECK(env->Global()
2799 ->Set(env.local(), v8_str("global"), global_proxy)
2800 .FromJust());
Ben Murdoch61f157c2016-09-16 13:49:30 +01002801 int32_t hash1;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002802 if (set_in_js) {
2803 CompileRun("var m = new Set(); m.add(global);");
Ben Murdoch61f157c2016-09-16 13:49:30 +01002804 i::Object* original_hash = i_global_proxy->GetHash();
2805 CHECK(original_hash->IsSmi());
2806 hash1 = i::Smi::cast(original_hash)->value();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002807 } else {
Ben Murdoch61f157c2016-09-16 13:49:30 +01002808 hash1 = i::Object::GetOrCreateHash(i_isolate, i_global_proxy)->value();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002809 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002810 // Hash should be retained after being detached.
2811 env->DetachGlobal();
2812 int hash2 = global_proxy->GetIdentityHash();
2813 CHECK_EQ(hash1, hash2);
2814 {
2815 // Re-attach global proxy to a new context, hash should stay the same.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002816 LocalContext env2(NULL, Local<ObjectTemplate>(), global_proxy);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002817 int hash3 = global_proxy->GetIdentityHash();
2818 CHECK_EQ(hash1, hash3);
2819 }
2820}
Steve Blocka7e24c12009-10-30 11:49:00 +00002821
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002822
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002823THREADED_TEST(GlobalProxyIdentityHash) {
2824 GlobalProxyIdentityHash(true);
2825 GlobalProxyIdentityHash(false);
2826}
2827
2828
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002829TEST(SymbolIdentityHash) {
2830 LocalContext env;
2831 v8::Isolate* isolate = env->GetIsolate();
2832 v8::HandleScope scope(isolate);
2833
2834 {
2835 Local<v8::Symbol> symbol = v8::Symbol::New(isolate);
2836 int hash = symbol->GetIdentityHash();
2837 int hash1 = symbol->GetIdentityHash();
2838 CHECK_EQ(hash, hash1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002839 CcTest::heap()->CollectAllGarbage();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002840 int hash3 = symbol->GetIdentityHash();
2841 CHECK_EQ(hash, hash3);
2842 }
2843
2844 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002845 v8::Local<v8::Symbol> js_symbol =
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002846 CompileRun("Symbol('foo')").As<v8::Symbol>();
2847 int hash = js_symbol->GetIdentityHash();
2848 int hash1 = js_symbol->GetIdentityHash();
2849 CHECK_EQ(hash, hash1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002850 CcTest::heap()->CollectAllGarbage();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002851 int hash3 = js_symbol->GetIdentityHash();
2852 CHECK_EQ(hash, hash3);
2853 }
2854}
2855
2856
2857TEST(StringIdentityHash) {
2858 LocalContext env;
2859 v8::Isolate* isolate = env->GetIsolate();
2860 v8::HandleScope scope(isolate);
2861
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002862 Local<v8::String> str = v8_str("str1");
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002863 int hash = str->GetIdentityHash();
2864 int hash1 = str->GetIdentityHash();
2865 CHECK_EQ(hash, hash1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002866 CcTest::heap()->CollectAllGarbage();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002867 int hash3 = str->GetIdentityHash();
2868 CHECK_EQ(hash, hash3);
2869
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002870 Local<v8::String> str2 = v8_str("str1");
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002871 int hash4 = str2->GetIdentityHash();
2872 CHECK_EQ(hash, hash4);
2873}
2874
2875
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002876THREADED_TEST(SymbolProperties) {
2877 LocalContext env;
2878 v8::Isolate* isolate = env->GetIsolate();
2879 v8::HandleScope scope(isolate);
2880
2881 v8::Local<v8::Object> obj = v8::Object::New(isolate);
2882 v8::Local<v8::Symbol> sym1 = v8::Symbol::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002883 v8::Local<v8::Symbol> sym2 = v8::Symbol::New(isolate, v8_str("my-symbol"));
2884 v8::Local<v8::Symbol> sym3 = v8::Symbol::New(isolate, v8_str("sym3"));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002885
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002886 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002887
2888 // Check basic symbol functionality.
2889 CHECK(sym1->IsSymbol());
2890 CHECK(sym2->IsSymbol());
2891 CHECK(!obj->IsSymbol());
2892
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002893 CHECK(sym1->Equals(env.local(), sym1).FromJust());
2894 CHECK(sym2->Equals(env.local(), sym2).FromJust());
2895 CHECK(!sym1->Equals(env.local(), sym2).FromJust());
2896 CHECK(!sym2->Equals(env.local(), sym1).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002897 CHECK(sym1->StrictEquals(sym1));
2898 CHECK(sym2->StrictEquals(sym2));
2899 CHECK(!sym1->StrictEquals(sym2));
2900 CHECK(!sym2->StrictEquals(sym1));
2901
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002902 CHECK(sym2->Name()->Equals(env.local(), v8_str("my-symbol")).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002903
2904 v8::Local<v8::Value> sym_val = sym2;
2905 CHECK(sym_val->IsSymbol());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002906 CHECK(sym_val->Equals(env.local(), sym2).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002907 CHECK(sym_val->StrictEquals(sym2));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002908 CHECK(v8::Symbol::Cast(*sym_val)->Equals(env.local(), sym2).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002909
2910 v8::Local<v8::Value> sym_obj = v8::SymbolObject::New(isolate, sym2);
2911 CHECK(sym_obj->IsSymbolObject());
2912 CHECK(!sym2->IsSymbolObject());
2913 CHECK(!obj->IsSymbolObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002914 CHECK(sym_obj->Equals(env.local(), sym2).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002915 CHECK(!sym_obj->StrictEquals(sym2));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002916 CHECK(v8::SymbolObject::Cast(*sym_obj)
2917 ->Equals(env.local(), sym_obj)
2918 .FromJust());
2919 CHECK(v8::SymbolObject::Cast(*sym_obj)
2920 ->ValueOf()
2921 ->Equals(env.local(), sym2)
2922 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002923
2924 // Make sure delete of a non-existent symbol property works.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002925 CHECK(obj->Delete(env.local(), sym1).FromJust());
2926 CHECK(!obj->Has(env.local(), sym1).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002927
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002928 CHECK(
2929 obj->Set(env.local(), sym1, v8::Integer::New(isolate, 1503)).FromJust());
2930 CHECK(obj->Has(env.local(), sym1).FromJust());
2931 CHECK_EQ(1503, obj->Get(env.local(), sym1)
2932 .ToLocalChecked()
2933 ->Int32Value(env.local())
2934 .FromJust());
2935 CHECK(
2936 obj->Set(env.local(), sym1, v8::Integer::New(isolate, 2002)).FromJust());
2937 CHECK(obj->Has(env.local(), sym1).FromJust());
2938 CHECK_EQ(2002, obj->Get(env.local(), sym1)
2939 .ToLocalChecked()
2940 ->Int32Value(env.local())
2941 .FromJust());
2942 CHECK_EQ(v8::None, obj->GetPropertyAttributes(env.local(), sym1).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002943
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002944 CHECK_EQ(0u,
2945 obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
2946 unsigned num_props =
2947 obj->GetPropertyNames(env.local()).ToLocalChecked()->Length();
2948 CHECK(obj->Set(env.local(), v8_str("bla"), v8::Integer::New(isolate, 20))
2949 .FromJust());
2950 CHECK_EQ(1u,
2951 obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
2952 CHECK_EQ(num_props + 1,
2953 obj->GetPropertyNames(env.local()).ToLocalChecked()->Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002954
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002955 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002956
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002957 CHECK(obj->SetAccessor(env.local(), sym3, SymbolAccessorGetter,
2958 SymbolAccessorSetter)
2959 .FromJust());
2960 CHECK(obj->Get(env.local(), sym3).ToLocalChecked()->IsUndefined());
2961 CHECK(obj->Set(env.local(), sym3, v8::Integer::New(isolate, 42)).FromJust());
2962 CHECK(obj->Get(env.local(), sym3)
2963 .ToLocalChecked()
2964 ->Equals(env.local(), v8::Integer::New(isolate, 42))
2965 .FromJust());
2966 CHECK(obj->Get(env.local(), v8_str("accessor_sym3"))
2967 .ToLocalChecked()
2968 ->Equals(env.local(), v8::Integer::New(isolate, 42))
2969 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002970
2971 // Add another property and delete it afterwards to force the object in
2972 // slow case.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002973 CHECK(
2974 obj->Set(env.local(), sym2, v8::Integer::New(isolate, 2008)).FromJust());
2975 CHECK_EQ(2002, obj->Get(env.local(), sym1)
2976 .ToLocalChecked()
2977 ->Int32Value(env.local())
2978 .FromJust());
2979 CHECK_EQ(2008, obj->Get(env.local(), sym2)
2980 .ToLocalChecked()
2981 ->Int32Value(env.local())
2982 .FromJust());
2983 CHECK_EQ(2002, obj->Get(env.local(), sym1)
2984 .ToLocalChecked()
2985 ->Int32Value(env.local())
2986 .FromJust());
2987 CHECK_EQ(2u,
2988 obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002989
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002990 CHECK(obj->Has(env.local(), sym1).FromJust());
2991 CHECK(obj->Has(env.local(), sym2).FromJust());
2992 CHECK(obj->Has(env.local(), sym3).FromJust());
2993 CHECK(obj->Has(env.local(), v8_str("accessor_sym3")).FromJust());
2994 CHECK(obj->Delete(env.local(), sym2).FromJust());
2995 CHECK(obj->Has(env.local(), sym1).FromJust());
2996 CHECK(!obj->Has(env.local(), sym2).FromJust());
2997 CHECK(obj->Has(env.local(), sym3).FromJust());
2998 CHECK(obj->Has(env.local(), v8_str("accessor_sym3")).FromJust());
2999 CHECK_EQ(2002, obj->Get(env.local(), sym1)
3000 .ToLocalChecked()
3001 ->Int32Value(env.local())
3002 .FromJust());
3003 CHECK(obj->Get(env.local(), sym3)
3004 .ToLocalChecked()
3005 ->Equals(env.local(), v8::Integer::New(isolate, 42))
3006 .FromJust());
3007 CHECK(obj->Get(env.local(), v8_str("accessor_sym3"))
3008 .ToLocalChecked()
3009 ->Equals(env.local(), v8::Integer::New(isolate, 42))
3010 .FromJust());
3011 CHECK_EQ(2u,
3012 obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003013
3014 // Symbol properties are inherited.
3015 v8::Local<v8::Object> child = v8::Object::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003016 CHECK(child->SetPrototype(env.local(), obj).FromJust());
3017 CHECK(child->Has(env.local(), sym1).FromJust());
3018 CHECK_EQ(2002, child->Get(env.local(), sym1)
3019 .ToLocalChecked()
3020 ->Int32Value(env.local())
3021 .FromJust());
3022 CHECK(obj->Get(env.local(), sym3)
3023 .ToLocalChecked()
3024 ->Equals(env.local(), v8::Integer::New(isolate, 42))
3025 .FromJust());
3026 CHECK(obj->Get(env.local(), v8_str("accessor_sym3"))
3027 .ToLocalChecked()
3028 ->Equals(env.local(), v8::Integer::New(isolate, 42))
3029 .FromJust());
3030 CHECK_EQ(0u,
3031 child->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003032}
3033
3034
3035THREADED_TEST(SymbolTemplateProperties) {
3036 LocalContext env;
3037 v8::Isolate* isolate = env->GetIsolate();
3038 v8::HandleScope scope(isolate);
3039 v8::Local<v8::FunctionTemplate> foo = v8::FunctionTemplate::New(isolate);
3040 v8::Local<v8::Name> name = v8::Symbol::New(isolate);
3041 CHECK(!name.IsEmpty());
3042 foo->PrototypeTemplate()->Set(name, v8::FunctionTemplate::New(isolate));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003043 v8::Local<v8::Object> new_instance =
3044 foo->InstanceTemplate()->NewInstance(env.local()).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003045 CHECK(!new_instance.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003046 CHECK(new_instance->Has(env.local(), name).FromJust());
3047}
3048
3049
3050THREADED_TEST(PrivatePropertiesOnProxies) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003051 LocalContext env;
3052 v8::Isolate* isolate = env->GetIsolate();
3053 v8::HandleScope scope(isolate);
3054
3055 v8::Local<v8::Object> target = CompileRun("({})").As<v8::Object>();
3056 v8::Local<v8::Object> handler = CompileRun("({})").As<v8::Object>();
3057
3058 v8::Local<v8::Proxy> proxy =
3059 v8::Proxy::New(env.local(), target, handler).ToLocalChecked();
3060
3061 v8::Local<v8::Private> priv1 = v8::Private::New(isolate);
3062 v8::Local<v8::Private> priv2 =
3063 v8::Private::New(isolate, v8_str("my-private"));
3064
3065 CcTest::heap()->CollectAllGarbage();
3066
3067 CHECK(priv2->Name()
3068 ->Equals(env.local(),
3069 v8::String::NewFromUtf8(isolate, "my-private",
3070 v8::NewStringType::kNormal)
3071 .ToLocalChecked())
3072 .FromJust());
3073
3074 // Make sure delete of a non-existent private symbol property works.
3075 proxy->DeletePrivate(env.local(), priv1).FromJust();
3076 CHECK(!proxy->HasPrivate(env.local(), priv1).FromJust());
3077
3078 CHECK(proxy->SetPrivate(env.local(), priv1, v8::Integer::New(isolate, 1503))
3079 .FromJust());
3080 CHECK(proxy->HasPrivate(env.local(), priv1).FromJust());
3081 CHECK_EQ(1503, proxy->GetPrivate(env.local(), priv1)
3082 .ToLocalChecked()
3083 ->Int32Value(env.local())
3084 .FromJust());
3085 CHECK(proxy->SetPrivate(env.local(), priv1, v8::Integer::New(isolate, 2002))
3086 .FromJust());
3087 CHECK(proxy->HasPrivate(env.local(), priv1).FromJust());
3088 CHECK_EQ(2002, proxy->GetPrivate(env.local(), priv1)
3089 .ToLocalChecked()
3090 ->Int32Value(env.local())
3091 .FromJust());
3092
3093 CHECK_EQ(0u,
3094 proxy->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
3095 unsigned num_props =
3096 proxy->GetPropertyNames(env.local()).ToLocalChecked()->Length();
3097 CHECK(proxy->Set(env.local(), v8::String::NewFromUtf8(
3098 isolate, "bla", v8::NewStringType::kNormal)
3099 .ToLocalChecked(),
3100 v8::Integer::New(isolate, 20))
3101 .FromJust());
3102 CHECK_EQ(1u,
3103 proxy->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
3104 CHECK_EQ(num_props + 1,
3105 proxy->GetPropertyNames(env.local()).ToLocalChecked()->Length());
3106
3107 CcTest::heap()->CollectAllGarbage();
3108
3109 // Add another property and delete it afterwards to force the object in
3110 // slow case.
3111 CHECK(proxy->SetPrivate(env.local(), priv2, v8::Integer::New(isolate, 2008))
3112 .FromJust());
3113 CHECK_EQ(2002, proxy->GetPrivate(env.local(), priv1)
3114 .ToLocalChecked()
3115 ->Int32Value(env.local())
3116 .FromJust());
3117 CHECK_EQ(2008, proxy->GetPrivate(env.local(), priv2)
3118 .ToLocalChecked()
3119 ->Int32Value(env.local())
3120 .FromJust());
3121 CHECK_EQ(2002, proxy->GetPrivate(env.local(), priv1)
3122 .ToLocalChecked()
3123 ->Int32Value(env.local())
3124 .FromJust());
3125 CHECK_EQ(1u,
3126 proxy->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
3127
3128 CHECK(proxy->HasPrivate(env.local(), priv1).FromJust());
3129 CHECK(proxy->HasPrivate(env.local(), priv2).FromJust());
3130 CHECK(proxy->DeletePrivate(env.local(), priv2).FromJust());
3131 CHECK(proxy->HasPrivate(env.local(), priv1).FromJust());
3132 CHECK(!proxy->HasPrivate(env.local(), priv2).FromJust());
3133 CHECK_EQ(2002, proxy->GetPrivate(env.local(), priv1)
3134 .ToLocalChecked()
3135 ->Int32Value(env.local())
3136 .FromJust());
3137 CHECK_EQ(1u,
3138 proxy->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
3139
3140 // Private properties are not inherited (for the time being).
3141 v8::Local<v8::Object> child = v8::Object::New(isolate);
3142 CHECK(child->SetPrototype(env.local(), proxy).FromJust());
3143 CHECK(!child->HasPrivate(env.local(), priv1).FromJust());
3144 CHECK_EQ(0u,
3145 child->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003146}
3147
3148
3149THREADED_TEST(PrivateProperties) {
3150 LocalContext env;
3151 v8::Isolate* isolate = env->GetIsolate();
3152 v8::HandleScope scope(isolate);
3153
3154 v8::Local<v8::Object> obj = v8::Object::New(isolate);
3155 v8::Local<v8::Private> priv1 = v8::Private::New(isolate);
3156 v8::Local<v8::Private> priv2 =
3157 v8::Private::New(isolate, v8_str("my-private"));
3158
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003159 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003160
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003161 CHECK(priv2->Name()
3162 ->Equals(env.local(),
3163 v8::String::NewFromUtf8(isolate, "my-private",
3164 v8::NewStringType::kNormal)
3165 .ToLocalChecked())
3166 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003167
3168 // Make sure delete of a non-existent private symbol property works.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003169 obj->DeletePrivate(env.local(), priv1).FromJust();
3170 CHECK(!obj->HasPrivate(env.local(), priv1).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003171
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003172 CHECK(obj->SetPrivate(env.local(), priv1, v8::Integer::New(isolate, 1503))
3173 .FromJust());
3174 CHECK(obj->HasPrivate(env.local(), priv1).FromJust());
3175 CHECK_EQ(1503, obj->GetPrivate(env.local(), priv1)
3176 .ToLocalChecked()
3177 ->Int32Value(env.local())
3178 .FromJust());
3179 CHECK(obj->SetPrivate(env.local(), priv1, v8::Integer::New(isolate, 2002))
3180 .FromJust());
3181 CHECK(obj->HasPrivate(env.local(), priv1).FromJust());
3182 CHECK_EQ(2002, obj->GetPrivate(env.local(), priv1)
3183 .ToLocalChecked()
3184 ->Int32Value(env.local())
3185 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003186
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003187 CHECK_EQ(0u,
3188 obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
3189 unsigned num_props =
3190 obj->GetPropertyNames(env.local()).ToLocalChecked()->Length();
3191 CHECK(obj->Set(env.local(), v8::String::NewFromUtf8(
3192 isolate, "bla", v8::NewStringType::kNormal)
3193 .ToLocalChecked(),
3194 v8::Integer::New(isolate, 20))
3195 .FromJust());
3196 CHECK_EQ(1u,
3197 obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
3198 CHECK_EQ(num_props + 1,
3199 obj->GetPropertyNames(env.local()).ToLocalChecked()->Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003200
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003201 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003202
3203 // Add another property and delete it afterwards to force the object in
3204 // slow case.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003205 CHECK(obj->SetPrivate(env.local(), priv2, v8::Integer::New(isolate, 2008))
3206 .FromJust());
3207 CHECK_EQ(2002, obj->GetPrivate(env.local(), priv1)
3208 .ToLocalChecked()
3209 ->Int32Value(env.local())
3210 .FromJust());
3211 CHECK_EQ(2008, obj->GetPrivate(env.local(), priv2)
3212 .ToLocalChecked()
3213 ->Int32Value(env.local())
3214 .FromJust());
3215 CHECK_EQ(2002, obj->GetPrivate(env.local(), priv1)
3216 .ToLocalChecked()
3217 ->Int32Value(env.local())
3218 .FromJust());
3219 CHECK_EQ(1u,
3220 obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003221
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003222 CHECK(obj->HasPrivate(env.local(), priv1).FromJust());
3223 CHECK(obj->HasPrivate(env.local(), priv2).FromJust());
3224 CHECK(obj->DeletePrivate(env.local(), priv2).FromJust());
3225 CHECK(obj->HasPrivate(env.local(), priv1).FromJust());
3226 CHECK(!obj->HasPrivate(env.local(), priv2).FromJust());
3227 CHECK_EQ(2002, obj->GetPrivate(env.local(), priv1)
3228 .ToLocalChecked()
3229 ->Int32Value(env.local())
3230 .FromJust());
3231 CHECK_EQ(1u,
3232 obj->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003233
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003234 // Private properties are not inherited (for the time being).
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003235 v8::Local<v8::Object> child = v8::Object::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003236 CHECK(child->SetPrototype(env.local(), obj).FromJust());
3237 CHECK(!child->HasPrivate(env.local(), priv1).FromJust());
3238 CHECK_EQ(0u,
3239 child->GetOwnPropertyNames(env.local()).ToLocalChecked()->Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003240}
3241
3242
3243THREADED_TEST(GlobalSymbols) {
3244 LocalContext env;
3245 v8::Isolate* isolate = env->GetIsolate();
3246 v8::HandleScope scope(isolate);
3247
3248 v8::Local<String> name = v8_str("my-symbol");
3249 v8::Local<v8::Symbol> glob = v8::Symbol::For(isolate, name);
3250 v8::Local<v8::Symbol> glob2 = v8::Symbol::For(isolate, name);
3251 CHECK(glob2->SameValue(glob));
3252
3253 v8::Local<v8::Symbol> glob_api = v8::Symbol::ForApi(isolate, name);
3254 v8::Local<v8::Symbol> glob_api2 = v8::Symbol::ForApi(isolate, name);
3255 CHECK(glob_api2->SameValue(glob_api));
3256 CHECK(!glob_api->SameValue(glob));
3257
3258 v8::Local<v8::Symbol> sym = v8::Symbol::New(isolate, name);
3259 CHECK(!sym->SameValue(glob));
3260
3261 CompileRun("var sym2 = Symbol.for('my-symbol')");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003262 v8::Local<Value> sym2 =
3263 env->Global()->Get(env.local(), v8_str("sym2")).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003264 CHECK(sym2->SameValue(glob));
3265 CHECK(!sym2->SameValue(glob_api));
3266}
3267
3268
3269static void CheckWellKnownSymbol(v8::Local<v8::Symbol>(*getter)(v8::Isolate*),
3270 const char* name) {
3271 LocalContext env;
3272 v8::Isolate* isolate = env->GetIsolate();
3273 v8::HandleScope scope(isolate);
3274
3275 v8::Local<v8::Symbol> symbol = getter(isolate);
3276 std::string script = std::string("var sym = ") + name;
3277 CompileRun(script.c_str());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003278 v8::Local<Value> value =
3279 env->Global()->Get(env.local(), v8_str("sym")).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003280
3281 CHECK(!value.IsEmpty());
3282 CHECK(!symbol.IsEmpty());
3283 CHECK(value->SameValue(symbol));
3284}
3285
3286
3287THREADED_TEST(WellKnownSymbols) {
3288 CheckWellKnownSymbol(v8::Symbol::GetIterator, "Symbol.iterator");
3289 CheckWellKnownSymbol(v8::Symbol::GetUnscopables, "Symbol.unscopables");
3290}
3291
3292
3293THREADED_TEST(GlobalPrivates) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003294 i::FLAG_allow_natives_syntax = true;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003295 LocalContext env;
3296 v8::Isolate* isolate = env->GetIsolate();
3297 v8::HandleScope scope(isolate);
3298
3299 v8::Local<String> name = v8_str("my-private");
3300 v8::Local<v8::Private> glob = v8::Private::ForApi(isolate, name);
3301 v8::Local<v8::Object> obj = v8::Object::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003302 CHECK(obj->SetPrivate(env.local(), glob, v8::Integer::New(isolate, 3))
3303 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003304
3305 v8::Local<v8::Private> glob2 = v8::Private::ForApi(isolate, name);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003306 CHECK(obj->HasPrivate(env.local(), glob2).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003307
3308 v8::Local<v8::Private> priv = v8::Private::New(isolate, name);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003309 CHECK(!obj->HasPrivate(env.local(), priv).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003310
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003311 CompileRun("var intern = %CreatePrivateSymbol('my-private')");
3312 v8::Local<Value> intern =
3313 env->Global()->Get(env.local(), v8_str("intern")).ToLocalChecked();
3314 CHECK(!obj->Has(env.local(), intern).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003315}
3316
3317
3318class ScopedArrayBufferContents {
3319 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003320 explicit ScopedArrayBufferContents(const v8::ArrayBuffer::Contents& contents)
3321 : contents_(contents) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003322 ~ScopedArrayBufferContents() { free(contents_.Data()); }
3323 void* Data() const { return contents_.Data(); }
3324 size_t ByteLength() const { return contents_.ByteLength(); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003325
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003326 private:
3327 const v8::ArrayBuffer::Contents contents_;
3328};
3329
3330template <typename T>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003331static void CheckInternalFieldsAreZero(v8::Local<T> value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003332 CHECK_EQ(T::kInternalFieldCount, value->InternalFieldCount());
3333 for (int i = 0; i < value->InternalFieldCount(); i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003334 CHECK_EQ(0, value->GetInternalField(i)
3335 ->Int32Value(CcTest::isolate()->GetCurrentContext())
3336 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003337 }
3338}
3339
3340
3341THREADED_TEST(ArrayBuffer_ApiInternalToExternal) {
3342 LocalContext env;
3343 v8::Isolate* isolate = env->GetIsolate();
3344 v8::HandleScope handle_scope(isolate);
3345
3346 Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, 1024);
3347 CheckInternalFieldsAreZero(ab);
3348 CHECK_EQ(1024, static_cast<int>(ab->ByteLength()));
3349 CHECK(!ab->IsExternal());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003350 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003351
3352 ScopedArrayBufferContents ab_contents(ab->Externalize());
3353 CHECK(ab->IsExternal());
3354
3355 CHECK_EQ(1024, static_cast<int>(ab_contents.ByteLength()));
3356 uint8_t* data = static_cast<uint8_t*>(ab_contents.Data());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003357 CHECK(data != NULL);
3358 CHECK(env->Global()->Set(env.local(), v8_str("ab"), ab).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003359
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003360 v8::Local<v8::Value> result = CompileRun("ab.byteLength");
3361 CHECK_EQ(1024, result->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003362
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003363 result = CompileRun(
3364 "var u8 = new Uint8Array(ab);"
3365 "u8[0] = 0xFF;"
3366 "u8[1] = 0xAA;"
3367 "u8.length");
3368 CHECK_EQ(1024, result->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003369 CHECK_EQ(0xFF, data[0]);
3370 CHECK_EQ(0xAA, data[1]);
3371 data[0] = 0xCC;
3372 data[1] = 0x11;
3373 result = CompileRun("u8[0] + u8[1]");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003374 CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003375}
3376
3377
3378THREADED_TEST(ArrayBuffer_JSInternalToExternal) {
3379 LocalContext env;
3380 v8::Isolate* isolate = env->GetIsolate();
3381 v8::HandleScope handle_scope(isolate);
3382
3383
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003384 v8::Local<v8::Value> result = CompileRun(
3385 "var ab1 = new ArrayBuffer(2);"
3386 "var u8_a = new Uint8Array(ab1);"
3387 "u8_a[0] = 0xAA;"
3388 "u8_a[1] = 0xFF; u8_a.buffer");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003389 Local<v8::ArrayBuffer> ab1 = Local<v8::ArrayBuffer>::Cast(result);
3390 CheckInternalFieldsAreZero(ab1);
3391 CHECK_EQ(2, static_cast<int>(ab1->ByteLength()));
3392 CHECK(!ab1->IsExternal());
3393 ScopedArrayBufferContents ab1_contents(ab1->Externalize());
3394 CHECK(ab1->IsExternal());
3395
3396 result = CompileRun("ab1.byteLength");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003397 CHECK_EQ(2, result->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003398 result = CompileRun("u8_a[0]");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003399 CHECK_EQ(0xAA, result->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003400 result = CompileRun("u8_a[1]");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003401 CHECK_EQ(0xFF, result->Int32Value(env.local()).FromJust());
3402 result = CompileRun(
3403 "var u8_b = new Uint8Array(ab1);"
3404 "u8_b[0] = 0xBB;"
3405 "u8_a[0]");
3406 CHECK_EQ(0xBB, result->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003407 result = CompileRun("u8_b[1]");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003408 CHECK_EQ(0xFF, result->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003409
3410 CHECK_EQ(2, static_cast<int>(ab1_contents.ByteLength()));
3411 uint8_t* ab1_data = static_cast<uint8_t*>(ab1_contents.Data());
3412 CHECK_EQ(0xBB, ab1_data[0]);
3413 CHECK_EQ(0xFF, ab1_data[1]);
3414 ab1_data[0] = 0xCC;
3415 ab1_data[1] = 0x11;
3416 result = CompileRun("u8_a[0] + u8_a[1]");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003417 CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003418}
3419
3420
3421THREADED_TEST(ArrayBuffer_External) {
3422 LocalContext env;
3423 v8::Isolate* isolate = env->GetIsolate();
3424 v8::HandleScope handle_scope(isolate);
3425
3426 i::ScopedVector<uint8_t> my_data(100);
3427 memset(my_data.start(), 0, 100);
3428 Local<v8::ArrayBuffer> ab3 =
3429 v8::ArrayBuffer::New(isolate, my_data.start(), 100);
3430 CheckInternalFieldsAreZero(ab3);
3431 CHECK_EQ(100, static_cast<int>(ab3->ByteLength()));
3432 CHECK(ab3->IsExternal());
3433
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003434 CHECK(env->Global()->Set(env.local(), v8_str("ab3"), ab3).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003435
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003436 v8::Local<v8::Value> result = CompileRun("ab3.byteLength");
3437 CHECK_EQ(100, result->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003438
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003439 result = CompileRun(
3440 "var u8_b = new Uint8Array(ab3);"
3441 "u8_b[0] = 0xBB;"
3442 "u8_b[1] = 0xCC;"
3443 "u8_b.length");
3444 CHECK_EQ(100, result->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003445 CHECK_EQ(0xBB, my_data[0]);
3446 CHECK_EQ(0xCC, my_data[1]);
3447 my_data[0] = 0xCC;
3448 my_data[1] = 0x11;
3449 result = CompileRun("u8_b[0] + u8_b[1]");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003450 CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003451}
3452
3453
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003454THREADED_TEST(ArrayBuffer_DisableNeuter) {
3455 LocalContext env;
3456 v8::Isolate* isolate = env->GetIsolate();
3457 v8::HandleScope handle_scope(isolate);
3458
3459 i::ScopedVector<uint8_t> my_data(100);
3460 memset(my_data.start(), 0, 100);
3461 Local<v8::ArrayBuffer> ab =
3462 v8::ArrayBuffer::New(isolate, my_data.start(), 100);
3463 CHECK(ab->IsNeuterable());
3464
3465 i::Handle<i::JSArrayBuffer> buf = v8::Utils::OpenHandle(*ab);
3466 buf->set_is_neuterable(false);
3467
3468 CHECK(!ab->IsNeuterable());
3469}
3470
3471
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003472static void CheckDataViewIsNeutered(v8::Local<v8::DataView> dv) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003473 CHECK_EQ(0, static_cast<int>(dv->ByteLength()));
3474 CHECK_EQ(0, static_cast<int>(dv->ByteOffset()));
3475}
3476
3477
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003478static void CheckIsNeutered(v8::Local<v8::TypedArray> ta) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003479 CHECK_EQ(0, static_cast<int>(ta->ByteLength()));
3480 CHECK_EQ(0, static_cast<int>(ta->Length()));
3481 CHECK_EQ(0, static_cast<int>(ta->ByteOffset()));
3482}
3483
3484
3485static void CheckIsTypedArrayVarNeutered(const char* name) {
3486 i::ScopedVector<char> source(1024);
3487 i::SNPrintF(source,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003488 "%s.byteLength == 0 && %s.byteOffset == 0 && %s.length == 0",
3489 name, name, name);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003490 CHECK(CompileRun(source.start())->IsTrue());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003491 v8::Local<v8::TypedArray> ta =
3492 v8::Local<v8::TypedArray>::Cast(CompileRun(name));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003493 CheckIsNeutered(ta);
3494}
3495
3496
3497template <typename TypedArray, int kElementSize>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003498static Local<TypedArray> CreateAndCheck(Local<v8::ArrayBuffer> ab,
3499 int byteOffset, int length) {
3500 v8::Local<TypedArray> ta = TypedArray::New(ab, byteOffset, length);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003501 CheckInternalFieldsAreZero<v8::ArrayBufferView>(ta);
3502 CHECK_EQ(byteOffset, static_cast<int>(ta->ByteOffset()));
3503 CHECK_EQ(length, static_cast<int>(ta->Length()));
3504 CHECK_EQ(length * kElementSize, static_cast<int>(ta->ByteLength()));
3505 return ta;
3506}
3507
3508
3509THREADED_TEST(ArrayBuffer_NeuteringApi) {
3510 LocalContext env;
3511 v8::Isolate* isolate = env->GetIsolate();
3512 v8::HandleScope handle_scope(isolate);
3513
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003514 v8::Local<v8::ArrayBuffer> buffer = v8::ArrayBuffer::New(isolate, 1024);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003515
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003516 v8::Local<v8::Uint8Array> u8a =
3517 CreateAndCheck<v8::Uint8Array, 1>(buffer, 1, 1023);
3518 v8::Local<v8::Uint8ClampedArray> u8c =
3519 CreateAndCheck<v8::Uint8ClampedArray, 1>(buffer, 1, 1023);
3520 v8::Local<v8::Int8Array> i8a =
3521 CreateAndCheck<v8::Int8Array, 1>(buffer, 1, 1023);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003522
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003523 v8::Local<v8::Uint16Array> u16a =
3524 CreateAndCheck<v8::Uint16Array, 2>(buffer, 2, 511);
3525 v8::Local<v8::Int16Array> i16a =
3526 CreateAndCheck<v8::Int16Array, 2>(buffer, 2, 511);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003527
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003528 v8::Local<v8::Uint32Array> u32a =
3529 CreateAndCheck<v8::Uint32Array, 4>(buffer, 4, 255);
3530 v8::Local<v8::Int32Array> i32a =
3531 CreateAndCheck<v8::Int32Array, 4>(buffer, 4, 255);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003532
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003533 v8::Local<v8::Float32Array> f32a =
3534 CreateAndCheck<v8::Float32Array, 4>(buffer, 4, 255);
3535 v8::Local<v8::Float64Array> f64a =
3536 CreateAndCheck<v8::Float64Array, 8>(buffer, 8, 127);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003537
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003538 v8::Local<v8::DataView> dv = v8::DataView::New(buffer, 1, 1023);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003539 CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
3540 CHECK_EQ(1, static_cast<int>(dv->ByteOffset()));
3541 CHECK_EQ(1023, static_cast<int>(dv->ByteLength()));
3542
3543 ScopedArrayBufferContents contents(buffer->Externalize());
3544 buffer->Neuter();
3545 CHECK_EQ(0, static_cast<int>(buffer->ByteLength()));
3546 CheckIsNeutered(u8a);
3547 CheckIsNeutered(u8c);
3548 CheckIsNeutered(i8a);
3549 CheckIsNeutered(u16a);
3550 CheckIsNeutered(i16a);
3551 CheckIsNeutered(u32a);
3552 CheckIsNeutered(i32a);
3553 CheckIsNeutered(f32a);
3554 CheckIsNeutered(f64a);
3555 CheckDataViewIsNeutered(dv);
3556}
3557
3558
3559THREADED_TEST(ArrayBuffer_NeuteringScript) {
3560 LocalContext env;
3561 v8::Isolate* isolate = env->GetIsolate();
3562 v8::HandleScope handle_scope(isolate);
3563
3564 CompileRun(
3565 "var ab = new ArrayBuffer(1024);"
3566 "var u8a = new Uint8Array(ab, 1, 1023);"
3567 "var u8c = new Uint8ClampedArray(ab, 1, 1023);"
3568 "var i8a = new Int8Array(ab, 1, 1023);"
3569 "var u16a = new Uint16Array(ab, 2, 511);"
3570 "var i16a = new Int16Array(ab, 2, 511);"
3571 "var u32a = new Uint32Array(ab, 4, 255);"
3572 "var i32a = new Int32Array(ab, 4, 255);"
3573 "var f32a = new Float32Array(ab, 4, 255);"
3574 "var f64a = new Float64Array(ab, 8, 127);"
3575 "var dv = new DataView(ab, 1, 1023);");
3576
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003577 v8::Local<v8::ArrayBuffer> ab =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003578 Local<v8::ArrayBuffer>::Cast(CompileRun("ab"));
3579
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003580 v8::Local<v8::DataView> dv = v8::Local<v8::DataView>::Cast(CompileRun("dv"));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003581
3582 ScopedArrayBufferContents contents(ab->Externalize());
3583 ab->Neuter();
3584 CHECK_EQ(0, static_cast<int>(ab->ByteLength()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003585 CHECK_EQ(0, v8_run_int32value(v8_compile("ab.byteLength")));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003586
3587 CheckIsTypedArrayVarNeutered("u8a");
3588 CheckIsTypedArrayVarNeutered("u8c");
3589 CheckIsTypedArrayVarNeutered("i8a");
3590 CheckIsTypedArrayVarNeutered("u16a");
3591 CheckIsTypedArrayVarNeutered("i16a");
3592 CheckIsTypedArrayVarNeutered("u32a");
3593 CheckIsTypedArrayVarNeutered("i32a");
3594 CheckIsTypedArrayVarNeutered("f32a");
3595 CheckIsTypedArrayVarNeutered("f64a");
3596
3597 CHECK(CompileRun("dv.byteLength == 0 && dv.byteOffset == 0")->IsTrue());
3598 CheckDataViewIsNeutered(dv);
3599}
3600
3601
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003602class ScopedSharedArrayBufferContents {
3603 public:
3604 explicit ScopedSharedArrayBufferContents(
3605 const v8::SharedArrayBuffer::Contents& contents)
3606 : contents_(contents) {}
3607 ~ScopedSharedArrayBufferContents() { free(contents_.Data()); }
3608 void* Data() const { return contents_.Data(); }
3609 size_t ByteLength() const { return contents_.ByteLength(); }
3610
3611 private:
3612 const v8::SharedArrayBuffer::Contents contents_;
3613};
3614
3615
3616THREADED_TEST(SharedArrayBuffer_ApiInternalToExternal) {
3617 i::FLAG_harmony_sharedarraybuffer = true;
3618 LocalContext env;
3619 v8::Isolate* isolate = env->GetIsolate();
3620 v8::HandleScope handle_scope(isolate);
3621
3622 Local<v8::SharedArrayBuffer> ab = v8::SharedArrayBuffer::New(isolate, 1024);
3623 CheckInternalFieldsAreZero(ab);
3624 CHECK_EQ(1024, static_cast<int>(ab->ByteLength()));
3625 CHECK(!ab->IsExternal());
3626 CcTest::heap()->CollectAllGarbage();
3627
3628 ScopedSharedArrayBufferContents ab_contents(ab->Externalize());
3629 CHECK(ab->IsExternal());
3630
3631 CHECK_EQ(1024, static_cast<int>(ab_contents.ByteLength()));
3632 uint8_t* data = static_cast<uint8_t*>(ab_contents.Data());
3633 CHECK(data != NULL);
3634 CHECK(env->Global()->Set(env.local(), v8_str("ab"), ab).FromJust());
3635
3636 v8::Local<v8::Value> result = CompileRun("ab.byteLength");
3637 CHECK_EQ(1024, result->Int32Value(env.local()).FromJust());
3638
3639 result = CompileRun(
3640 "var u8 = new Uint8Array(ab);"
3641 "u8[0] = 0xFF;"
3642 "u8[1] = 0xAA;"
3643 "u8.length");
3644 CHECK_EQ(1024, result->Int32Value(env.local()).FromJust());
3645 CHECK_EQ(0xFF, data[0]);
3646 CHECK_EQ(0xAA, data[1]);
3647 data[0] = 0xCC;
3648 data[1] = 0x11;
3649 result = CompileRun("u8[0] + u8[1]");
3650 CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
3651}
3652
3653
3654THREADED_TEST(SharedArrayBuffer_JSInternalToExternal) {
3655 i::FLAG_harmony_sharedarraybuffer = true;
3656 LocalContext env;
3657 v8::Isolate* isolate = env->GetIsolate();
3658 v8::HandleScope handle_scope(isolate);
3659
3660
3661 v8::Local<v8::Value> result = CompileRun(
3662 "var ab1 = new SharedArrayBuffer(2);"
3663 "var u8_a = new Uint8Array(ab1);"
3664 "u8_a[0] = 0xAA;"
3665 "u8_a[1] = 0xFF; u8_a.buffer");
3666 Local<v8::SharedArrayBuffer> ab1 = Local<v8::SharedArrayBuffer>::Cast(result);
3667 CheckInternalFieldsAreZero(ab1);
3668 CHECK_EQ(2, static_cast<int>(ab1->ByteLength()));
3669 CHECK(!ab1->IsExternal());
3670 ScopedSharedArrayBufferContents ab1_contents(ab1->Externalize());
3671 CHECK(ab1->IsExternal());
3672
3673 result = CompileRun("ab1.byteLength");
3674 CHECK_EQ(2, result->Int32Value(env.local()).FromJust());
3675 result = CompileRun("u8_a[0]");
3676 CHECK_EQ(0xAA, result->Int32Value(env.local()).FromJust());
3677 result = CompileRun("u8_a[1]");
3678 CHECK_EQ(0xFF, result->Int32Value(env.local()).FromJust());
3679 result = CompileRun(
3680 "var u8_b = new Uint8Array(ab1);"
3681 "u8_b[0] = 0xBB;"
3682 "u8_a[0]");
3683 CHECK_EQ(0xBB, result->Int32Value(env.local()).FromJust());
3684 result = CompileRun("u8_b[1]");
3685 CHECK_EQ(0xFF, result->Int32Value(env.local()).FromJust());
3686
3687 CHECK_EQ(2, static_cast<int>(ab1_contents.ByteLength()));
3688 uint8_t* ab1_data = static_cast<uint8_t*>(ab1_contents.Data());
3689 CHECK_EQ(0xBB, ab1_data[0]);
3690 CHECK_EQ(0xFF, ab1_data[1]);
3691 ab1_data[0] = 0xCC;
3692 ab1_data[1] = 0x11;
3693 result = CompileRun("u8_a[0] + u8_a[1]");
3694 CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
3695}
3696
3697
3698THREADED_TEST(SharedArrayBuffer_External) {
3699 i::FLAG_harmony_sharedarraybuffer = true;
3700 LocalContext env;
3701 v8::Isolate* isolate = env->GetIsolate();
3702 v8::HandleScope handle_scope(isolate);
3703
3704 i::ScopedVector<uint8_t> my_data(100);
3705 memset(my_data.start(), 0, 100);
3706 Local<v8::SharedArrayBuffer> ab3 =
3707 v8::SharedArrayBuffer::New(isolate, my_data.start(), 100);
3708 CheckInternalFieldsAreZero(ab3);
3709 CHECK_EQ(100, static_cast<int>(ab3->ByteLength()));
3710 CHECK(ab3->IsExternal());
3711
3712 CHECK(env->Global()->Set(env.local(), v8_str("ab3"), ab3).FromJust());
3713
3714 v8::Local<v8::Value> result = CompileRun("ab3.byteLength");
3715 CHECK_EQ(100, result->Int32Value(env.local()).FromJust());
3716
3717 result = CompileRun(
3718 "var u8_b = new Uint8Array(ab3);"
3719 "u8_b[0] = 0xBB;"
3720 "u8_b[1] = 0xCC;"
3721 "u8_b.length");
3722 CHECK_EQ(100, result->Int32Value(env.local()).FromJust());
3723 CHECK_EQ(0xBB, my_data[0]);
3724 CHECK_EQ(0xCC, my_data[1]);
3725 my_data[0] = 0xCC;
3726 my_data[1] = 0x11;
3727 result = CompileRun("u8_b[0] + u8_b[1]");
3728 CHECK_EQ(0xDD, result->Int32Value(env.local()).FromJust());
3729}
3730
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003731
3732THREADED_TEST(HiddenProperties) {
3733 LocalContext env;
3734 v8::Isolate* isolate = env->GetIsolate();
3735 v8::HandleScope scope(isolate);
3736
3737 v8::Local<v8::Object> obj = v8::Object::New(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003738 v8::Local<v8::Private> key =
3739 v8::Private::ForApi(isolate, v8_str("api-test::hidden-key"));
Steve Blocka7e24c12009-10-30 11:49:00 +00003740 v8::Local<v8::String> empty = v8_str("");
3741 v8::Local<v8::String> prop_name = v8_str("prop_name");
3742
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003743 CcTest::heap()->CollectAllGarbage();
Steve Blocka7e24c12009-10-30 11:49:00 +00003744
3745 // Make sure delete of a non-existent hidden value works
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003746 obj->DeletePrivate(env.local(), key).FromJust();
Steve Blocka7e24c12009-10-30 11:49:00 +00003747
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003748 CHECK(obj->SetPrivate(env.local(), key, v8::Integer::New(isolate, 1503))
3749 .FromJust());
3750 CHECK_EQ(1503, obj->GetPrivate(env.local(), key)
3751 .ToLocalChecked()
3752 ->Int32Value(env.local())
3753 .FromJust());
3754 CHECK(obj->SetPrivate(env.local(), key, v8::Integer::New(isolate, 2002))
3755 .FromJust());
3756 CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
3757 .ToLocalChecked()
3758 ->Int32Value(env.local())
3759 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00003760
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003761 CcTest::heap()->CollectAllGarbage();
Steve Blocka7e24c12009-10-30 11:49:00 +00003762
3763 // Make sure we do not find the hidden property.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003764 CHECK(!obj->Has(env.local(), empty).FromJust());
3765 CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
3766 .ToLocalChecked()
3767 ->Int32Value(env.local())
3768 .FromJust());
3769 CHECK(obj->Get(env.local(), empty).ToLocalChecked()->IsUndefined());
3770 CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
3771 .ToLocalChecked()
3772 ->Int32Value(env.local())
3773 .FromJust());
3774 CHECK(
3775 obj->Set(env.local(), empty, v8::Integer::New(isolate, 2003)).FromJust());
3776 CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
3777 .ToLocalChecked()
3778 ->Int32Value(env.local())
3779 .FromJust());
3780 CHECK_EQ(2003, obj->Get(env.local(), empty)
3781 .ToLocalChecked()
3782 ->Int32Value(env.local())
3783 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00003784
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003785 CcTest::heap()->CollectAllGarbage();
Steve Blocka7e24c12009-10-30 11:49:00 +00003786
3787 // Add another property and delete it afterwards to force the object in
3788 // slow case.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003789 CHECK(obj->Set(env.local(), prop_name, v8::Integer::New(isolate, 2008))
3790 .FromJust());
3791 CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
3792 .ToLocalChecked()
3793 ->Int32Value(env.local())
3794 .FromJust());
3795 CHECK_EQ(2008, obj->Get(env.local(), prop_name)
3796 .ToLocalChecked()
3797 ->Int32Value(env.local())
3798 .FromJust());
3799 CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
3800 .ToLocalChecked()
3801 ->Int32Value(env.local())
3802 .FromJust());
3803 CHECK(obj->Delete(env.local(), prop_name).FromJust());
3804 CHECK_EQ(2002, obj->GetPrivate(env.local(), key)
3805 .ToLocalChecked()
3806 ->Int32Value(env.local())
3807 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00003808
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003809 CcTest::heap()->CollectAllGarbage();
Steve Blocka7e24c12009-10-30 11:49:00 +00003810
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003811 CHECK(obj->SetPrivate(env.local(), key, v8::Integer::New(isolate, 2002))
3812 .FromJust());
3813 CHECK(obj->DeletePrivate(env.local(), key).FromJust());
3814 CHECK(!obj->HasPrivate(env.local(), key).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00003815}
3816
3817
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003818THREADED_TEST(Regress97784) {
3819 // Regression test for crbug.com/97784
3820 // Messing with the Object.prototype should not have effect on
3821 // hidden properties.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003822 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003823 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003824
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003825 v8::Local<v8::Object> obj = v8::Object::New(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003826 v8::Local<v8::Private> key =
3827 v8::Private::New(env->GetIsolate(), v8_str("hidden"));
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003828
3829 CompileRun(
3830 "set_called = false;"
3831 "Object.defineProperty("
3832 " Object.prototype,"
3833 " 'hidden',"
3834 " {get: function() { return 45; },"
3835 " set: function() { set_called = true; }})");
3836
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003837 CHECK(!obj->HasPrivate(env.local(), key).FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003838 // Make sure that the getter and setter from Object.prototype is not invoked.
3839 // If it did we would have full access to the hidden properties in
3840 // the accessor.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003841 CHECK(
3842 obj->SetPrivate(env.local(), key, v8::Integer::New(env->GetIsolate(), 42))
3843 .FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003844 ExpectFalse("set_called");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003845 CHECK_EQ(42, obj->GetPrivate(env.local(), key)
3846 .ToLocalChecked()
3847 ->Int32Value(env.local())
3848 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00003849}
3850
3851
3852THREADED_TEST(External) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003853 v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00003854 int x = 3;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003855 Local<v8::External> ext = v8::External::New(CcTest::isolate(), &x);
Steve Blocka7e24c12009-10-30 11:49:00 +00003856 LocalContext env;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003857 CHECK(env->Global()->Set(env.local(), v8_str("ext"), ext).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003858 Local<Value> reext_obj = CompileRun("this.ext");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003859 v8::Local<v8::External> reext = reext_obj.As<v8::External>();
Steve Blocka7e24c12009-10-30 11:49:00 +00003860 int* ptr = static_cast<int*>(reext->Value());
3861 CHECK_EQ(x, 3);
3862 *ptr = 10;
3863 CHECK_EQ(x, 10);
3864
3865 // Make sure unaligned pointers are wrapped properly.
3866 char* data = i::StrDup("0123456789");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003867 Local<v8::Value> zero = v8::External::New(CcTest::isolate(), &data[0]);
3868 Local<v8::Value> one = v8::External::New(CcTest::isolate(), &data[1]);
3869 Local<v8::Value> two = v8::External::New(CcTest::isolate(), &data[2]);
3870 Local<v8::Value> three = v8::External::New(CcTest::isolate(), &data[3]);
Steve Blocka7e24c12009-10-30 11:49:00 +00003871
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003872 char* char_ptr = reinterpret_cast<char*>(v8::External::Cast(*zero)->Value());
Steve Blocka7e24c12009-10-30 11:49:00 +00003873 CHECK_EQ('0', *char_ptr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003874 char_ptr = reinterpret_cast<char*>(v8::External::Cast(*one)->Value());
Steve Blocka7e24c12009-10-30 11:49:00 +00003875 CHECK_EQ('1', *char_ptr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003876 char_ptr = reinterpret_cast<char*>(v8::External::Cast(*two)->Value());
Steve Blocka7e24c12009-10-30 11:49:00 +00003877 CHECK_EQ('2', *char_ptr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003878 char_ptr = reinterpret_cast<char*>(v8::External::Cast(*three)->Value());
Steve Blocka7e24c12009-10-30 11:49:00 +00003879 CHECK_EQ('3', *char_ptr);
3880 i::DeleteArray(data);
3881}
3882
3883
3884THREADED_TEST(GlobalHandle) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003885 v8::Isolate* isolate = CcTest::isolate();
Steve Blocka7e24c12009-10-30 11:49:00 +00003886 v8::Persistent<String> global;
3887 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003888 v8::HandleScope scope(isolate);
3889 global.Reset(isolate, v8_str("str"));
Steve Blocka7e24c12009-10-30 11:49:00 +00003890 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003891 {
3892 v8::HandleScope scope(isolate);
3893 CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
3894 }
3895 global.Reset();
3896 {
3897 v8::HandleScope scope(isolate);
3898 global.Reset(isolate, v8_str("str"));
3899 }
3900 {
3901 v8::HandleScope scope(isolate);
3902 CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
3903 }
3904 global.Reset();
3905}
3906
3907
3908THREADED_TEST(ResettingGlobalHandle) {
3909 v8::Isolate* isolate = CcTest::isolate();
3910 v8::Persistent<String> global;
3911 {
3912 v8::HandleScope scope(isolate);
3913 global.Reset(isolate, v8_str("str"));
3914 }
3915 v8::internal::GlobalHandles* global_handles =
3916 reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
3917 int initial_handle_count = global_handles->global_handles_count();
3918 {
3919 v8::HandleScope scope(isolate);
3920 CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
3921 }
3922 {
3923 v8::HandleScope scope(isolate);
3924 global.Reset(isolate, v8_str("longer"));
3925 }
3926 CHECK_EQ(global_handles->global_handles_count(), initial_handle_count);
3927 {
3928 v8::HandleScope scope(isolate);
3929 CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 6);
3930 }
3931 global.Reset();
3932 CHECK_EQ(global_handles->global_handles_count(), initial_handle_count - 1);
3933}
3934
3935
3936THREADED_TEST(ResettingGlobalHandleToEmpty) {
3937 v8::Isolate* isolate = CcTest::isolate();
3938 v8::Persistent<String> global;
3939 {
3940 v8::HandleScope scope(isolate);
3941 global.Reset(isolate, v8_str("str"));
3942 }
3943 v8::internal::GlobalHandles* global_handles =
3944 reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
3945 int initial_handle_count = global_handles->global_handles_count();
3946 {
3947 v8::HandleScope scope(isolate);
3948 CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
3949 }
3950 {
3951 v8::HandleScope scope(isolate);
3952 Local<String> empty;
3953 global.Reset(isolate, empty);
3954 }
3955 CHECK(global.IsEmpty());
3956 CHECK_EQ(global_handles->global_handles_count(), initial_handle_count - 1);
3957}
3958
3959
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003960template <class T>
3961static v8::Global<T> PassUnique(v8::Global<T> unique) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003962 return unique.Pass();
3963}
3964
3965
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003966template <class T>
3967static v8::Global<T> ReturnUnique(v8::Isolate* isolate,
3968 const v8::Persistent<T>& global) {
3969 v8::Global<String> unique(isolate, global);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003970 return unique.Pass();
3971}
3972
3973
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003974THREADED_TEST(Global) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003975 v8::Isolate* isolate = CcTest::isolate();
3976 v8::Persistent<String> global;
3977 {
3978 v8::HandleScope scope(isolate);
3979 global.Reset(isolate, v8_str("str"));
3980 }
3981 v8::internal::GlobalHandles* global_handles =
3982 reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
3983 int initial_handle_count = global_handles->global_handles_count();
3984 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003985 v8::Global<String> unique(isolate, global);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003986 CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
3987 // Test assignment via Pass
3988 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003989 v8::Global<String> copy = unique.Pass();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003990 CHECK(unique.IsEmpty());
3991 CHECK(copy == global);
3992 CHECK_EQ(initial_handle_count + 1,
3993 global_handles->global_handles_count());
3994 unique = copy.Pass();
3995 }
3996 // Test ctor via Pass
3997 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003998 v8::Global<String> copy(unique.Pass());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003999 CHECK(unique.IsEmpty());
4000 CHECK(copy == global);
4001 CHECK_EQ(initial_handle_count + 1,
4002 global_handles->global_handles_count());
4003 unique = copy.Pass();
4004 }
4005 // Test pass through function call
4006 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004007 v8::Global<String> copy = PassUnique(unique.Pass());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004008 CHECK(unique.IsEmpty());
4009 CHECK(copy == global);
4010 CHECK_EQ(initial_handle_count + 1,
4011 global_handles->global_handles_count());
4012 unique = copy.Pass();
4013 }
4014 CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
4015 }
4016 // Test pass from function call
4017 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004018 v8::Global<String> unique = ReturnUnique(isolate, global);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004019 CHECK(unique == global);
4020 CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
4021 }
4022 CHECK_EQ(initial_handle_count, global_handles->global_handles_count());
4023 global.Reset();
4024}
4025
4026
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004027namespace {
4028
4029class TwoPassCallbackData;
4030void FirstPassCallback(const v8::WeakCallbackInfo<TwoPassCallbackData>& data);
4031void SecondPassCallback(const v8::WeakCallbackInfo<TwoPassCallbackData>& data);
4032
4033
4034class TwoPassCallbackData {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004035 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004036 TwoPassCallbackData(v8::Isolate* isolate, int* instance_counter)
4037 : first_pass_called_(false),
4038 second_pass_called_(false),
4039 trigger_gc_(false),
4040 instance_counter_(instance_counter) {
4041 HandleScope scope(isolate);
4042 i::ScopedVector<char> buffer(40);
4043 i::SNPrintF(buffer, "%p", static_cast<void*>(this));
4044 auto string =
4045 v8::String::NewFromUtf8(isolate, buffer.start(),
4046 v8::NewStringType::kNormal).ToLocalChecked();
4047 cell_.Reset(isolate, string);
4048 (*instance_counter_)++;
4049 }
4050
4051 ~TwoPassCallbackData() {
4052 CHECK(first_pass_called_);
4053 CHECK(second_pass_called_);
4054 CHECK(cell_.IsEmpty());
4055 (*instance_counter_)--;
4056 }
4057
4058 void FirstPass() {
4059 CHECK(!first_pass_called_);
4060 CHECK(!second_pass_called_);
4061 CHECK(!cell_.IsEmpty());
4062 cell_.Reset();
4063 first_pass_called_ = true;
4064 }
4065
4066 void SecondPass() {
4067 CHECK(first_pass_called_);
4068 CHECK(!second_pass_called_);
4069 CHECK(cell_.IsEmpty());
4070 second_pass_called_ = true;
4071 delete this;
4072 }
4073
4074 void SetWeak() {
4075 cell_.SetWeak(this, FirstPassCallback, v8::WeakCallbackType::kParameter);
4076 }
4077
4078 void MarkTriggerGc() { trigger_gc_ = true; }
4079 bool trigger_gc() { return trigger_gc_; }
4080
4081 int* instance_counter() { return instance_counter_; }
4082
4083 private:
4084 bool first_pass_called_;
4085 bool second_pass_called_;
4086 bool trigger_gc_;
4087 v8::Global<v8::String> cell_;
4088 int* instance_counter_;
4089};
4090
4091
4092void SecondPassCallback(const v8::WeakCallbackInfo<TwoPassCallbackData>& data) {
4093 ApiTestFuzzer::Fuzz();
4094 bool trigger_gc = data.GetParameter()->trigger_gc();
4095 int* instance_counter = data.GetParameter()->instance_counter();
4096 data.GetParameter()->SecondPass();
4097 if (!trigger_gc) return;
4098 auto data_2 = new TwoPassCallbackData(data.GetIsolate(), instance_counter);
4099 data_2->SetWeak();
4100 CcTest::heap()->CollectAllGarbage();
4101}
4102
4103
4104void FirstPassCallback(const v8::WeakCallbackInfo<TwoPassCallbackData>& data) {
4105 data.GetParameter()->FirstPass();
4106 data.SetSecondPassCallback(SecondPassCallback);
4107}
4108
4109} // namespace
4110
4111
4112TEST(TwoPassPhantomCallbacks) {
4113 auto isolate = CcTest::isolate();
4114 const size_t kLength = 20;
4115 int instance_counter = 0;
4116 for (size_t i = 0; i < kLength; ++i) {
4117 auto data = new TwoPassCallbackData(isolate, &instance_counter);
4118 data->SetWeak();
4119 }
4120 CHECK_EQ(static_cast<int>(kLength), instance_counter);
4121 CcTest::heap()->CollectAllGarbage();
4122 EmptyMessageQueues(isolate);
4123 CHECK_EQ(0, instance_counter);
4124}
4125
4126
4127TEST(TwoPassPhantomCallbacksNestedGc) {
4128 auto isolate = CcTest::isolate();
4129 const size_t kLength = 20;
4130 TwoPassCallbackData* array[kLength];
4131 int instance_counter = 0;
4132 for (size_t i = 0; i < kLength; ++i) {
4133 array[i] = new TwoPassCallbackData(isolate, &instance_counter);
4134 array[i]->SetWeak();
4135 }
4136 array[5]->MarkTriggerGc();
4137 array[10]->MarkTriggerGc();
4138 array[15]->MarkTriggerGc();
4139 CHECK_EQ(static_cast<int>(kLength), instance_counter);
4140 CcTest::heap()->CollectAllGarbage();
4141 EmptyMessageQueues(isolate);
4142 CHECK_EQ(0, instance_counter);
4143}
4144
4145
4146namespace {
4147
4148void* IntKeyToVoidPointer(int key) { return reinterpret_cast<void*>(key << 1); }
4149
4150
4151Local<v8::Object> NewObjectForIntKey(
4152 v8::Isolate* isolate, const v8::Global<v8::ObjectTemplate>& templ,
4153 int key) {
4154 auto local = Local<v8::ObjectTemplate>::New(isolate, templ);
4155 auto obj = local->NewInstance(isolate->GetCurrentContext()).ToLocalChecked();
4156 obj->SetAlignedPointerInInternalField(0, IntKeyToVoidPointer(key));
4157 return obj;
4158}
4159
4160
4161template <typename K, typename V>
4162class PhantomStdMapTraits : public v8::StdMapTraits<K, V> {
4163 public:
4164 typedef typename v8::GlobalValueMap<K, V, PhantomStdMapTraits<K, V>> MapType;
4165 static const v8::PersistentContainerCallbackType kCallbackType =
4166 v8::kWeakWithInternalFields;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004167 struct WeakCallbackDataType {
4168 MapType* map;
4169 K key;
4170 };
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004171 static WeakCallbackDataType* WeakCallbackParameter(MapType* map, const K& key,
4172 Local<V> value) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004173 WeakCallbackDataType* data = new WeakCallbackDataType;
4174 data->map = map;
4175 data->key = key;
4176 return data;
4177 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004178 static MapType* MapFromWeakCallbackInfo(
4179 const v8::WeakCallbackInfo<WeakCallbackDataType>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004180 return data.GetParameter()->map;
4181 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004182 static K KeyFromWeakCallbackInfo(
4183 const v8::WeakCallbackInfo<WeakCallbackDataType>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004184 return data.GetParameter()->key;
4185 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004186 static void DisposeCallbackData(WeakCallbackDataType* data) { delete data; }
4187 static void Dispose(v8::Isolate* isolate, v8::Global<V> value, K key) {
4188 CHECK_EQ(IntKeyToVoidPointer(key),
4189 v8::Object::GetAlignedPointerFromInternalField(value, 0));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004190 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004191 static void OnWeakCallback(
4192 const v8::WeakCallbackInfo<WeakCallbackDataType>&) {}
4193 static void DisposeWeak(
4194 const v8::WeakCallbackInfo<WeakCallbackDataType>& info) {
4195 K key = KeyFromWeakCallbackInfo(info);
4196 CHECK_EQ(IntKeyToVoidPointer(key), info.GetInternalField(0));
4197 DisposeCallbackData(info.GetParameter());
4198 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004199};
4200
4201
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004202template <typename Map>
4203void TestGlobalValueMap() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004204 LocalContext env;
4205 v8::Isolate* isolate = env->GetIsolate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004206 v8::Global<ObjectTemplate> templ;
4207 {
4208 HandleScope scope(isolate);
4209 auto t = ObjectTemplate::New(isolate);
4210 t->SetInternalFieldCount(1);
4211 templ.Reset(isolate, t);
4212 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004213 Map map(isolate);
4214 v8::internal::GlobalHandles* global_handles =
4215 reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
4216 int initial_handle_count = global_handles->global_handles_count();
4217 CHECK_EQ(0, static_cast<int>(map.Size()));
4218 {
4219 HandleScope scope(isolate);
4220 Local<v8::Object> obj = map.Get(7);
4221 CHECK(obj.IsEmpty());
4222 Local<v8::Object> expected = v8::Object::New(isolate);
4223 map.Set(7, expected);
4224 CHECK_EQ(1, static_cast<int>(map.Size()));
4225 obj = map.Get(7);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004226 CHECK(expected->Equals(env.local(), obj).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004227 {
4228 typename Map::PersistentValueReference ref = map.GetReference(7);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004229 CHECK(expected->Equals(env.local(), ref.NewLocal(isolate)).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004230 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004231 v8::Global<v8::Object> removed = map.Remove(7);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004232 CHECK_EQ(0, static_cast<int>(map.Size()));
4233 CHECK(expected == removed);
4234 removed = map.Remove(7);
4235 CHECK(removed.IsEmpty());
4236 map.Set(8, expected);
4237 CHECK_EQ(1, static_cast<int>(map.Size()));
4238 map.Set(8, expected);
4239 CHECK_EQ(1, static_cast<int>(map.Size()));
4240 {
4241 typename Map::PersistentValueReference ref;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004242 Local<v8::Object> expected2 = NewObjectForIntKey(isolate, templ, 8);
4243 removed = map.Set(8, v8::Global<v8::Object>(isolate, expected2), &ref);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004244 CHECK_EQ(1, static_cast<int>(map.Size()));
4245 CHECK(expected == removed);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004246 CHECK(expected2->Equals(env.local(), ref.NewLocal(isolate)).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004247 }
4248 }
4249 CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
4250 if (map.IsWeak()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004251 CcTest::i_isolate()->heap()->CollectAllGarbage(
4252 i::Heap::kAbortIncrementalMarkingMask);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004253 } else {
4254 map.Clear();
4255 }
4256 CHECK_EQ(0, static_cast<int>(map.Size()));
4257 CHECK_EQ(initial_handle_count, global_handles->global_handles_count());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004258 {
4259 HandleScope scope(isolate);
4260 Local<v8::Object> value = NewObjectForIntKey(isolate, templ, 9);
4261 map.Set(9, value);
4262 map.Clear();
4263 }
4264 CHECK_EQ(0, static_cast<int>(map.Size()));
4265 CHECK_EQ(initial_handle_count, global_handles->global_handles_count());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004266}
4267
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004268} // namespace
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004269
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004270
4271TEST(GlobalValueMap) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004272 // Default case, w/o weak callbacks:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004273 TestGlobalValueMap<v8::StdGlobalValueMap<int, v8::Object>>();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004274
4275 // Custom traits with weak callbacks:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004276 typedef v8::GlobalValueMap<int, v8::Object,
4277 PhantomStdMapTraits<int, v8::Object>> WeakMap;
4278 TestGlobalValueMap<WeakMap>();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004279}
4280
4281
4282TEST(PersistentValueVector) {
4283 LocalContext env;
4284 v8::Isolate* isolate = env->GetIsolate();
4285 v8::internal::GlobalHandles* global_handles =
4286 reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
4287 int handle_count = global_handles->global_handles_count();
4288 HandleScope scope(isolate);
4289
4290 v8::PersistentValueVector<v8::Object> vector(isolate);
4291
4292 Local<v8::Object> obj1 = v8::Object::New(isolate);
4293 Local<v8::Object> obj2 = v8::Object::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004294 v8::Global<v8::Object> obj3(isolate, v8::Object::New(isolate));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004295
4296 CHECK(vector.IsEmpty());
4297 CHECK_EQ(0, static_cast<int>(vector.Size()));
4298
4299 vector.ReserveCapacity(3);
4300 CHECK(vector.IsEmpty());
4301
4302 vector.Append(obj1);
4303 vector.Append(obj2);
4304 vector.Append(obj1);
4305 vector.Append(obj3.Pass());
4306 vector.Append(obj1);
4307
4308 CHECK(!vector.IsEmpty());
4309 CHECK_EQ(5, static_cast<int>(vector.Size()));
4310 CHECK(obj3.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004311 CHECK(obj1->Equals(env.local(), vector.Get(0)).FromJust());
4312 CHECK(obj1->Equals(env.local(), vector.Get(2)).FromJust());
4313 CHECK(obj1->Equals(env.local(), vector.Get(4)).FromJust());
4314 CHECK(obj2->Equals(env.local(), vector.Get(1)).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004315
4316 CHECK_EQ(5 + handle_count, global_handles->global_handles_count());
4317
4318 vector.Clear();
4319 CHECK(vector.IsEmpty());
4320 CHECK_EQ(0, static_cast<int>(vector.Size()));
4321 CHECK_EQ(handle_count, global_handles->global_handles_count());
4322}
4323
4324
4325THREADED_TEST(GlobalHandleUpcast) {
4326 v8::Isolate* isolate = CcTest::isolate();
4327 v8::HandleScope scope(isolate);
4328 v8::Local<String> local = v8::Local<String>::New(isolate, v8_str("str"));
4329 v8::Persistent<String> global_string(isolate, local);
4330 v8::Persistent<Value>& global_value =
4331 v8::Persistent<Value>::Cast(global_string);
4332 CHECK(v8::Local<v8::Value>::New(isolate, global_value)->IsString());
4333 CHECK(global_string == v8::Persistent<String>::Cast(global_value));
4334 global_string.Reset();
4335}
4336
4337
4338THREADED_TEST(HandleEquality) {
4339 v8::Isolate* isolate = CcTest::isolate();
4340 v8::Persistent<String> global1;
4341 v8::Persistent<String> global2;
4342 {
4343 v8::HandleScope scope(isolate);
4344 global1.Reset(isolate, v8_str("str"));
4345 global2.Reset(isolate, v8_str("str2"));
4346 }
4347 CHECK_EQ(global1 == global1, true);
4348 CHECK_EQ(global1 != global1, false);
4349 {
4350 v8::HandleScope scope(isolate);
4351 Local<String> local1 = Local<String>::New(isolate, global1);
4352 Local<String> local2 = Local<String>::New(isolate, global2);
4353
4354 CHECK_EQ(global1 == local1, true);
4355 CHECK_EQ(global1 != local1, false);
4356 CHECK_EQ(local1 == global1, true);
4357 CHECK_EQ(local1 != global1, false);
4358
4359 CHECK_EQ(global1 == local2, false);
4360 CHECK_EQ(global1 != local2, true);
4361 CHECK_EQ(local2 == global1, false);
4362 CHECK_EQ(local2 != global1, true);
4363
4364 CHECK_EQ(local1 == local2, false);
4365 CHECK_EQ(local1 != local2, true);
4366
4367 Local<String> anotherLocal1 = Local<String>::New(isolate, global1);
4368 CHECK_EQ(local1 == anotherLocal1, true);
4369 CHECK_EQ(local1 != anotherLocal1, false);
4370 }
4371 global1.Reset();
4372 global2.Reset();
4373}
4374
4375
4376THREADED_TEST(LocalHandle) {
4377 v8::HandleScope scope(CcTest::isolate());
4378 v8::Local<String> local =
4379 v8::Local<String>::New(CcTest::isolate(), v8_str("str"));
4380 CHECK_EQ(local->Length(), 3);
Steve Blocka7e24c12009-10-30 11:49:00 +00004381}
4382
4383
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004384class WeakCallCounter {
4385 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004386 explicit WeakCallCounter(int id) : id_(id), number_of_weak_calls_(0) {}
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004387 int id() { return id_; }
4388 void increment() { number_of_weak_calls_++; }
4389 int NumberOfWeakCalls() { return number_of_weak_calls_; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004390
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004391 private:
4392 int id_;
4393 int number_of_weak_calls_;
4394};
4395
4396
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004397template <typename T>
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004398struct WeakCallCounterAndPersistent {
4399 explicit WeakCallCounterAndPersistent(WeakCallCounter* counter)
4400 : counter(counter) {}
4401 WeakCallCounter* counter;
4402 v8::Persistent<T> handle;
4403};
4404
4405
4406template <typename T>
4407static void WeakPointerCallback(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004408 const v8::WeakCallbackInfo<WeakCallCounterAndPersistent<T>>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004409 CHECK_EQ(1234, data.GetParameter()->counter->id());
4410 data.GetParameter()->counter->increment();
4411 data.GetParameter()->handle.Reset();
4412}
4413
4414
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004415template <typename T>
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004416static UniqueId MakeUniqueId(const Persistent<T>& p) {
4417 return UniqueId(reinterpret_cast<uintptr_t>(*v8::Utils::OpenPersistent(p)));
Steve Block44f0eee2011-05-26 01:26:41 +01004418}
4419
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004420
Steve Block44f0eee2011-05-26 01:26:41 +01004421THREADED_TEST(ApiObjectGroups) {
Steve Block44f0eee2011-05-26 01:26:41 +01004422 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004423 v8::Isolate* iso = env->GetIsolate();
4424 HandleScope scope(iso);
Steve Block44f0eee2011-05-26 01:26:41 +01004425
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004426 WeakCallCounter counter(1234);
4427
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004428 WeakCallCounterAndPersistent<Value> g1s1(&counter);
4429 WeakCallCounterAndPersistent<Value> g1s2(&counter);
4430 WeakCallCounterAndPersistent<Value> g1c1(&counter);
4431 WeakCallCounterAndPersistent<Value> g2s1(&counter);
4432 WeakCallCounterAndPersistent<Value> g2s2(&counter);
4433 WeakCallCounterAndPersistent<Value> g2c1(&counter);
Steve Block44f0eee2011-05-26 01:26:41 +01004434
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004435 {
4436 HandleScope scope(iso);
4437 g1s1.handle.Reset(iso, Object::New(iso));
4438 g1s2.handle.Reset(iso, Object::New(iso));
4439 g1c1.handle.Reset(iso, Object::New(iso));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004440 g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback,
4441 v8::WeakCallbackType::kParameter);
4442 g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback,
4443 v8::WeakCallbackType::kParameter);
4444 g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback,
4445 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004446
4447 g2s1.handle.Reset(iso, Object::New(iso));
4448 g2s2.handle.Reset(iso, Object::New(iso));
4449 g2c1.handle.Reset(iso, Object::New(iso));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004450 g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback,
4451 v8::WeakCallbackType::kParameter);
4452 g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback,
4453 v8::WeakCallbackType::kParameter);
4454 g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback,
4455 v8::WeakCallbackType::kParameter);
Steve Block44f0eee2011-05-26 01:26:41 +01004456 }
4457
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004458 WeakCallCounterAndPersistent<Value> root(&counter);
4459 root.handle.Reset(iso, g1s1.handle); // make a root.
Steve Block44f0eee2011-05-26 01:26:41 +01004460
4461 // Connect group 1 and 2, make a cycle.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004462 {
4463 HandleScope scope(iso);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004464 CHECK(Local<Object>::New(iso, g1s2.handle.As<Object>())
4465 ->Set(env.local(), 0, Local<Value>::New(iso, g2s2.handle))
4466 .FromJust());
4467 CHECK(Local<Object>::New(iso, g2s1.handle.As<Object>())
4468 ->Set(env.local(), 0, Local<Value>::New(iso, g1s1.handle))
4469 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004470 }
Steve Block44f0eee2011-05-26 01:26:41 +01004471
4472 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004473 UniqueId id1 = MakeUniqueId(g1s1.handle);
4474 UniqueId id2 = MakeUniqueId(g2s2.handle);
4475 iso->SetObjectGroupId(g1s1.handle, id1);
4476 iso->SetObjectGroupId(g1s2.handle, id1);
4477 iso->SetReferenceFromGroup(id1, g1c1.handle);
4478 iso->SetObjectGroupId(g2s1.handle, id2);
4479 iso->SetObjectGroupId(g2s2.handle, id2);
4480 iso->SetReferenceFromGroup(id2, g2c1.handle);
Steve Block44f0eee2011-05-26 01:26:41 +01004481 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004482 // Do a single full GC, ensure incremental marking is stopped.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004483 v8::internal::Heap* heap =
4484 reinterpret_cast<v8::internal::Isolate*>(iso)->heap();
4485 heap->CollectAllGarbage();
Steve Block44f0eee2011-05-26 01:26:41 +01004486
4487 // All object should be alive.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004488 CHECK_EQ(0, counter.NumberOfWeakCalls());
Steve Block44f0eee2011-05-26 01:26:41 +01004489
4490 // Weaken the root.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004491 root.handle.SetWeak(&root, &WeakPointerCallback,
4492 v8::WeakCallbackType::kParameter);
Steve Block44f0eee2011-05-26 01:26:41 +01004493 // But make children strong roots---all the objects (except for children)
4494 // should be collectable now.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004495 g1c1.handle.ClearWeak();
4496 g2c1.handle.ClearWeak();
Steve Block44f0eee2011-05-26 01:26:41 +01004497
4498 // Groups are deleted, rebuild groups.
4499 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004500 UniqueId id1 = MakeUniqueId(g1s1.handle);
4501 UniqueId id2 = MakeUniqueId(g2s2.handle);
4502 iso->SetObjectGroupId(g1s1.handle, id1);
4503 iso->SetObjectGroupId(g1s2.handle, id1);
4504 iso->SetReferenceFromGroup(id1, g1c1.handle);
4505 iso->SetObjectGroupId(g2s1.handle, id2);
4506 iso->SetObjectGroupId(g2s2.handle, id2);
4507 iso->SetReferenceFromGroup(id2, g2c1.handle);
Steve Block44f0eee2011-05-26 01:26:41 +01004508 }
4509
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004510 heap->CollectAllGarbage();
Steve Block44f0eee2011-05-26 01:26:41 +01004511
4512 // All objects should be gone. 5 global handles in total.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004513 CHECK_EQ(5, counter.NumberOfWeakCalls());
Steve Block44f0eee2011-05-26 01:26:41 +01004514
4515 // And now make children weak again and collect them.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004516 g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback,
4517 v8::WeakCallbackType::kParameter);
4518 g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback,
4519 v8::WeakCallbackType::kParameter);
Steve Block44f0eee2011-05-26 01:26:41 +01004520
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004521 heap->CollectAllGarbage();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004522 CHECK_EQ(7, counter.NumberOfWeakCalls());
Steve Block44f0eee2011-05-26 01:26:41 +01004523}
4524
4525
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004526THREADED_TEST(ApiObjectGroupsForSubtypes) {
Steve Block44f0eee2011-05-26 01:26:41 +01004527 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004528 v8::Isolate* iso = env->GetIsolate();
4529 HandleScope scope(iso);
Steve Block44f0eee2011-05-26 01:26:41 +01004530
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004531 WeakCallCounter counter(1234);
Steve Block44f0eee2011-05-26 01:26:41 +01004532
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004533 WeakCallCounterAndPersistent<Object> g1s1(&counter);
4534 WeakCallCounterAndPersistent<String> g1s2(&counter);
4535 WeakCallCounterAndPersistent<String> g1c1(&counter);
4536 WeakCallCounterAndPersistent<Object> g2s1(&counter);
4537 WeakCallCounterAndPersistent<String> g2s2(&counter);
4538 WeakCallCounterAndPersistent<String> g2c1(&counter);
Steve Block44f0eee2011-05-26 01:26:41 +01004539
4540 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004541 HandleScope scope(iso);
4542 g1s1.handle.Reset(iso, Object::New(iso));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004543 g1s2.handle.Reset(iso, v8_str("foo1"));
4544 g1c1.handle.Reset(iso, v8_str("foo2"));
4545 g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback,
4546 v8::WeakCallbackType::kParameter);
4547 g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback,
4548 v8::WeakCallbackType::kParameter);
4549 g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback,
4550 v8::WeakCallbackType::kParameter);
Steve Block44f0eee2011-05-26 01:26:41 +01004551
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004552 g2s1.handle.Reset(iso, Object::New(iso));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004553 g2s2.handle.Reset(iso, v8_str("foo3"));
4554 g2c1.handle.Reset(iso, v8_str("foo4"));
4555 g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback,
4556 v8::WeakCallbackType::kParameter);
4557 g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback,
4558 v8::WeakCallbackType::kParameter);
4559 g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback,
4560 v8::WeakCallbackType::kParameter);
Steve Block44f0eee2011-05-26 01:26:41 +01004561 }
4562
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004563 WeakCallCounterAndPersistent<Value> root(&counter);
4564 root.handle.Reset(iso, g1s1.handle); // make a root.
Steve Block44f0eee2011-05-26 01:26:41 +01004565
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004566 // Connect group 1 and 2, make a cycle.
Steve Block44f0eee2011-05-26 01:26:41 +01004567 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004568 HandleScope scope(iso);
4569 CHECK(Local<Object>::New(iso, g1s1.handle)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004570 ->Set(env.local(), 0, Local<Object>::New(iso, g2s1.handle))
4571 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004572 CHECK(Local<Object>::New(iso, g2s1.handle)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004573 ->Set(env.local(), 0, Local<Object>::New(iso, g1s1.handle))
4574 .FromJust());
Steve Block44f0eee2011-05-26 01:26:41 +01004575 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004576
4577 {
4578 UniqueId id1 = MakeUniqueId(g1s1.handle);
4579 UniqueId id2 = MakeUniqueId(g2s2.handle);
4580 iso->SetObjectGroupId(g1s1.handle, id1);
4581 iso->SetObjectGroupId(g1s2.handle, id1);
4582 iso->SetReference(g1s1.handle, g1c1.handle);
4583 iso->SetObjectGroupId(g2s1.handle, id2);
4584 iso->SetObjectGroupId(g2s2.handle, id2);
4585 iso->SetReferenceFromGroup(id2, g2c1.handle);
4586 }
4587 // Do a single full GC, ensure incremental marking is stopped.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004588 v8::internal::Heap* heap =
4589 reinterpret_cast<v8::internal::Isolate*>(iso)->heap();
4590 heap->CollectAllGarbage();
Steve Block44f0eee2011-05-26 01:26:41 +01004591
4592 // All object should be alive.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01004593 CHECK_EQ(0, counter.NumberOfWeakCalls());
Steve Block44f0eee2011-05-26 01:26:41 +01004594
4595 // Weaken the root.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004596 root.handle.SetWeak(&root, &WeakPointerCallback,
4597 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004598 // But make children strong roots---all the objects (except for children)
4599 // should be collectable now.
4600 g1c1.handle.ClearWeak();
4601 g2c1.handle.ClearWeak();
Steve Block44f0eee2011-05-26 01:26:41 +01004602
4603 // Groups are deleted, rebuild groups.
4604 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004605 UniqueId id1 = MakeUniqueId(g1s1.handle);
4606 UniqueId id2 = MakeUniqueId(g2s2.handle);
4607 iso->SetObjectGroupId(g1s1.handle, id1);
4608 iso->SetObjectGroupId(g1s2.handle, id1);
4609 iso->SetReference(g1s1.handle, g1c1.handle);
4610 iso->SetObjectGroupId(g2s1.handle, id2);
4611 iso->SetObjectGroupId(g2s2.handle, id2);
4612 iso->SetReferenceFromGroup(id2, g2c1.handle);
Steve Block44f0eee2011-05-26 01:26:41 +01004613 }
4614
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004615 heap->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004616
4617 // All objects should be gone. 5 global handles in total.
4618 CHECK_EQ(5, counter.NumberOfWeakCalls());
4619
4620 // And now make children weak again and collect them.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004621 g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback,
4622 v8::WeakCallbackType::kParameter);
4623 g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback,
4624 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004625
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004626 heap->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004627 CHECK_EQ(7, counter.NumberOfWeakCalls());
4628}
4629
4630
4631THREADED_TEST(ApiObjectGroupsCycle) {
4632 LocalContext env;
4633 v8::Isolate* iso = env->GetIsolate();
4634 HandleScope scope(iso);
4635
4636 WeakCallCounter counter(1234);
4637
4638 WeakCallCounterAndPersistent<Value> g1s1(&counter);
4639 WeakCallCounterAndPersistent<Value> g1s2(&counter);
4640 WeakCallCounterAndPersistent<Value> g2s1(&counter);
4641 WeakCallCounterAndPersistent<Value> g2s2(&counter);
4642 WeakCallCounterAndPersistent<Value> g3s1(&counter);
4643 WeakCallCounterAndPersistent<Value> g3s2(&counter);
4644 WeakCallCounterAndPersistent<Value> g4s1(&counter);
4645 WeakCallCounterAndPersistent<Value> g4s2(&counter);
4646
4647 {
4648 HandleScope scope(iso);
4649 g1s1.handle.Reset(iso, Object::New(iso));
4650 g1s2.handle.Reset(iso, Object::New(iso));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004651 g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback,
4652 v8::WeakCallbackType::kParameter);
4653 g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback,
4654 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004655 CHECK(g1s1.handle.IsWeak());
4656 CHECK(g1s2.handle.IsWeak());
4657
4658 g2s1.handle.Reset(iso, Object::New(iso));
4659 g2s2.handle.Reset(iso, Object::New(iso));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004660 g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback,
4661 v8::WeakCallbackType::kParameter);
4662 g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback,
4663 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004664 CHECK(g2s1.handle.IsWeak());
4665 CHECK(g2s2.handle.IsWeak());
4666
4667 g3s1.handle.Reset(iso, Object::New(iso));
4668 g3s2.handle.Reset(iso, Object::New(iso));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004669 g3s1.handle.SetWeak(&g3s1, &WeakPointerCallback,
4670 v8::WeakCallbackType::kParameter);
4671 g3s2.handle.SetWeak(&g3s2, &WeakPointerCallback,
4672 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004673 CHECK(g3s1.handle.IsWeak());
4674 CHECK(g3s2.handle.IsWeak());
4675
4676 g4s1.handle.Reset(iso, Object::New(iso));
4677 g4s2.handle.Reset(iso, Object::New(iso));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004678 g4s1.handle.SetWeak(&g4s1, &WeakPointerCallback,
4679 v8::WeakCallbackType::kParameter);
4680 g4s2.handle.SetWeak(&g4s2, &WeakPointerCallback,
4681 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004682 CHECK(g4s1.handle.IsWeak());
4683 CHECK(g4s2.handle.IsWeak());
4684 }
4685
4686 WeakCallCounterAndPersistent<Value> root(&counter);
4687 root.handle.Reset(iso, g1s1.handle); // make a root.
4688
4689 // Connect groups. We're building the following cycle:
4690 // G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other
4691 // groups.
4692 {
4693 UniqueId id1 = MakeUniqueId(g1s1.handle);
4694 UniqueId id2 = MakeUniqueId(g2s1.handle);
4695 UniqueId id3 = MakeUniqueId(g3s1.handle);
4696 UniqueId id4 = MakeUniqueId(g4s1.handle);
4697 iso->SetObjectGroupId(g1s1.handle, id1);
4698 iso->SetObjectGroupId(g1s2.handle, id1);
4699 iso->SetReferenceFromGroup(id1, g2s1.handle);
4700 iso->SetObjectGroupId(g2s1.handle, id2);
4701 iso->SetObjectGroupId(g2s2.handle, id2);
4702 iso->SetReferenceFromGroup(id2, g3s1.handle);
4703 iso->SetObjectGroupId(g3s1.handle, id3);
4704 iso->SetObjectGroupId(g3s2.handle, id3);
4705 iso->SetReferenceFromGroup(id3, g4s1.handle);
4706 iso->SetObjectGroupId(g4s1.handle, id4);
4707 iso->SetObjectGroupId(g4s2.handle, id4);
4708 iso->SetReferenceFromGroup(id4, g1s1.handle);
4709 }
4710 // Do a single full GC
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004711 v8::internal::Heap* heap =
4712 reinterpret_cast<v8::internal::Isolate*>(iso)->heap();
4713 heap->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004714
4715 // All object should be alive.
4716 CHECK_EQ(0, counter.NumberOfWeakCalls());
4717
4718 // Weaken the root.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004719 root.handle.SetWeak(&root, &WeakPointerCallback,
4720 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004721
4722 // Groups are deleted, rebuild groups.
4723 {
4724 UniqueId id1 = MakeUniqueId(g1s1.handle);
4725 UniqueId id2 = MakeUniqueId(g2s1.handle);
4726 UniqueId id3 = MakeUniqueId(g3s1.handle);
4727 UniqueId id4 = MakeUniqueId(g4s1.handle);
4728 iso->SetObjectGroupId(g1s1.handle, id1);
4729 iso->SetObjectGroupId(g1s2.handle, id1);
4730 iso->SetReferenceFromGroup(id1, g2s1.handle);
4731 iso->SetObjectGroupId(g2s1.handle, id2);
4732 iso->SetObjectGroupId(g2s2.handle, id2);
4733 iso->SetReferenceFromGroup(id2, g3s1.handle);
4734 iso->SetObjectGroupId(g3s1.handle, id3);
4735 iso->SetObjectGroupId(g3s2.handle, id3);
4736 iso->SetReferenceFromGroup(id3, g4s1.handle);
4737 iso->SetObjectGroupId(g4s1.handle, id4);
4738 iso->SetObjectGroupId(g4s2.handle, id4);
4739 iso->SetReferenceFromGroup(id4, g1s1.handle);
4740 }
4741
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004742 heap->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004743
4744 // All objects should be gone. 9 global handles in total.
4745 CHECK_EQ(9, counter.NumberOfWeakCalls());
4746}
4747
4748
Steve Blocka7e24c12009-10-30 11:49:00 +00004749THREADED_TEST(ScriptException) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004750 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004751 v8::HandleScope scope(env->GetIsolate());
4752 Local<Script> script = v8_compile("throw 'panama!';");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004753 v8::TryCatch try_catch(env->GetIsolate());
4754 v8::MaybeLocal<Value> result = script->Run(env.local());
Steve Blocka7e24c12009-10-30 11:49:00 +00004755 CHECK(result.IsEmpty());
4756 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004757 String::Utf8Value exception_value(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004758 CHECK_EQ(0, strcmp(*exception_value, "panama!"));
Steve Blocka7e24c12009-10-30 11:49:00 +00004759}
4760
4761
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004762TEST(TryCatchCustomException) {
4763 LocalContext env;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04004764 v8::Isolate* isolate = env->GetIsolate();
4765 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004766 v8::TryCatch try_catch(isolate);
4767 CompileRun(
4768 "function CustomError() { this.a = 'b'; }"
4769 "(function f() { throw new CustomError(); })();");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004770 CHECK(try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004771 CHECK(try_catch.Exception()
4772 ->ToObject(env.local())
4773 .ToLocalChecked()
4774 ->Get(env.local(), v8_str("a"))
4775 .ToLocalChecked()
4776 ->Equals(env.local(), v8_str("b"))
4777 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004778}
4779
4780
Steve Blocka7e24c12009-10-30 11:49:00 +00004781bool message_received;
4782
4783
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004784static void check_message_0(v8::Local<v8::Message> message,
4785 v8::Local<Value> data) {
4786 CHECK_EQ(5.76, data->NumberValue(CcTest::isolate()->GetCurrentContext())
4787 .FromJust());
4788 CHECK_EQ(6.75, message->GetScriptOrigin()
4789 .ResourceName()
4790 ->NumberValue(CcTest::isolate()->GetCurrentContext())
4791 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004792 CHECK(!message->IsSharedCrossOrigin());
Steve Blocka7e24c12009-10-30 11:49:00 +00004793 message_received = true;
4794}
4795
4796
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004797THREADED_TEST(MessageHandler0) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004798 message_received = false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004799 v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00004800 CHECK(!message_received);
Steve Blocka7e24c12009-10-30 11:49:00 +00004801 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004802 CcTest::isolate()->AddMessageListener(check_message_0, v8_num(5.76));
4803 v8::Local<v8::Script> script = CompileWithOrigin("throw 'error'", "6.75");
4804 CHECK(script->Run(context.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00004805 CHECK(message_received);
4806 // clear out the message listener
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004807 CcTest::isolate()->RemoveMessageListeners(check_message_0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004808}
4809
4810
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004811static void check_message_1(v8::Local<v8::Message> message,
4812 v8::Local<Value> data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004813 CHECK(data->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004814 CHECK_EQ(1337,
4815 data->Int32Value(CcTest::isolate()->GetCurrentContext()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004816 CHECK(!message->IsSharedCrossOrigin());
4817 message_received = true;
4818}
4819
4820
4821TEST(MessageHandler1) {
4822 message_received = false;
4823 v8::HandleScope scope(CcTest::isolate());
4824 CHECK(!message_received);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004825 CcTest::isolate()->AddMessageListener(check_message_1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004826 LocalContext context;
4827 CompileRun("throw 1337;");
4828 CHECK(message_received);
4829 // clear out the message listener
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004830 CcTest::isolate()->RemoveMessageListeners(check_message_1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004831}
4832
4833
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004834static void check_message_2(v8::Local<v8::Message> message,
4835 v8::Local<Value> data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004836 LocalContext context;
4837 CHECK(data->IsObject());
4838 v8::Local<v8::Value> hidden_property =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004839 v8::Object::Cast(*data)
4840 ->GetPrivate(
4841 context.local(),
4842 v8::Private::ForApi(CcTest::isolate(), v8_str("hidden key")))
4843 .ToLocalChecked();
4844 CHECK(v8_str("hidden value")
4845 ->Equals(context.local(), hidden_property)
4846 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004847 CHECK(!message->IsSharedCrossOrigin());
4848 message_received = true;
4849}
4850
4851
4852TEST(MessageHandler2) {
4853 message_received = false;
4854 v8::HandleScope scope(CcTest::isolate());
4855 CHECK(!message_received);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004856 CcTest::isolate()->AddMessageListener(check_message_2);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004857 LocalContext context;
4858 v8::Local<v8::Value> error = v8::Exception::Error(v8_str("custom error"));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004859 v8::Object::Cast(*error)
4860 ->SetPrivate(context.local(),
4861 v8::Private::ForApi(CcTest::isolate(), v8_str("hidden key")),
4862 v8_str("hidden value"))
4863 .FromJust();
4864 CHECK(context->Global()
4865 ->Set(context.local(), v8_str("error"), error)
4866 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004867 CompileRun("throw error;");
4868 CHECK(message_received);
4869 // clear out the message listener
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004870 CcTest::isolate()->RemoveMessageListeners(check_message_2);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004871}
4872
4873
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004874static void check_message_3(v8::Local<v8::Message> message,
4875 v8::Local<Value> data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004876 CHECK(message->IsSharedCrossOrigin());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004877 CHECK(message->GetScriptOrigin().Options().IsSharedCrossOrigin());
4878 CHECK(message->GetScriptOrigin().Options().IsEmbedderDebugScript());
4879 CHECK(message->GetScriptOrigin().Options().IsOpaque());
4880 CHECK_EQ(6.75, message->GetScriptOrigin()
4881 .ResourceName()
4882 ->NumberValue(CcTest::isolate()->GetCurrentContext())
4883 .FromJust());
4884 CHECK_EQ(7.40, message->GetScriptOrigin()
4885 .SourceMapUrl()
4886 ->NumberValue(CcTest::isolate()->GetCurrentContext())
4887 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004888 message_received = true;
4889}
4890
4891
4892TEST(MessageHandler3) {
4893 message_received = false;
4894 v8::Isolate* isolate = CcTest::isolate();
4895 v8::HandleScope scope(isolate);
4896 CHECK(!message_received);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004897 isolate->AddMessageListener(check_message_3);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004898 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004899 v8::ScriptOrigin origin = v8::ScriptOrigin(
4900 v8_str("6.75"), v8::Integer::New(isolate, 1),
4901 v8::Integer::New(isolate, 2), v8::True(isolate), Local<v8::Integer>(),
4902 v8::True(isolate), v8_str("7.40"), v8::True(isolate));
4903 v8::Local<v8::Script> script =
4904 Script::Compile(context.local(), v8_str("throw 'error'"), &origin)
4905 .ToLocalChecked();
4906 CHECK(script->Run(context.local()).IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004907 CHECK(message_received);
4908 // clear out the message listener
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004909 isolate->RemoveMessageListeners(check_message_3);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004910}
4911
4912
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004913static void check_message_4(v8::Local<v8::Message> message,
4914 v8::Local<Value> data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004915 CHECK(!message->IsSharedCrossOrigin());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004916 CHECK_EQ(6.75, message->GetScriptOrigin()
4917 .ResourceName()
4918 ->NumberValue(CcTest::isolate()->GetCurrentContext())
4919 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004920 message_received = true;
4921}
4922
4923
4924TEST(MessageHandler4) {
4925 message_received = false;
4926 v8::Isolate* isolate = CcTest::isolate();
4927 v8::HandleScope scope(isolate);
4928 CHECK(!message_received);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004929 isolate->AddMessageListener(check_message_4);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004930 LocalContext context;
4931 v8::ScriptOrigin origin =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004932 v8::ScriptOrigin(v8_str("6.75"), v8::Integer::New(isolate, 1),
4933 v8::Integer::New(isolate, 2), v8::False(isolate));
4934 v8::Local<v8::Script> script =
4935 Script::Compile(context.local(), v8_str("throw 'error'"), &origin)
4936 .ToLocalChecked();
4937 CHECK(script->Run(context.local()).IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004938 CHECK(message_received);
4939 // clear out the message listener
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004940 isolate->RemoveMessageListeners(check_message_4);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004941}
4942
4943
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004944static void check_message_5a(v8::Local<v8::Message> message,
4945 v8::Local<Value> data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004946 CHECK(message->IsSharedCrossOrigin());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004947 CHECK_EQ(6.75, message->GetScriptOrigin()
4948 .ResourceName()
4949 ->NumberValue(CcTest::isolate()->GetCurrentContext())
4950 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004951 message_received = true;
4952}
4953
4954
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004955static void check_message_5b(v8::Local<v8::Message> message,
4956 v8::Local<Value> data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004957 CHECK(!message->IsSharedCrossOrigin());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004958 CHECK_EQ(6.75, message->GetScriptOrigin()
4959 .ResourceName()
4960 ->NumberValue(CcTest::isolate()->GetCurrentContext())
4961 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004962 message_received = true;
4963}
4964
4965
4966TEST(MessageHandler5) {
4967 message_received = false;
4968 v8::Isolate* isolate = CcTest::isolate();
4969 v8::HandleScope scope(isolate);
4970 CHECK(!message_received);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004971 isolate->AddMessageListener(check_message_5a);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004972 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004973 v8::ScriptOrigin origin1 =
4974 v8::ScriptOrigin(v8_str("6.75"), v8::Integer::New(isolate, 1),
4975 v8::Integer::New(isolate, 2), v8::True(isolate));
4976 v8::Local<v8::Script> script =
4977 Script::Compile(context.local(), v8_str("throw 'error'"), &origin1)
4978 .ToLocalChecked();
4979 CHECK(script->Run(context.local()).IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004980 CHECK(message_received);
4981 // clear out the message listener
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004982 isolate->RemoveMessageListeners(check_message_5a);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004983
4984 message_received = false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004985 isolate->AddMessageListener(check_message_5b);
4986 v8::ScriptOrigin origin2 =
4987 v8::ScriptOrigin(v8_str("6.75"), v8::Integer::New(isolate, 1),
4988 v8::Integer::New(isolate, 2), v8::False(isolate));
4989 script = Script::Compile(context.local(), v8_str("throw 'error'"), &origin2)
4990 .ToLocalChecked();
4991 CHECK(script->Run(context.local()).IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00004992 CHECK(message_received);
4993 // clear out the message listener
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00004994 isolate->RemoveMessageListeners(check_message_5b);
4995}
4996
4997
4998TEST(NativeWeakMap) {
4999 v8::Isolate* isolate = CcTest::isolate();
5000 HandleScope scope(isolate);
5001 Local<v8::NativeWeakMap> weak_map(v8::NativeWeakMap::New(isolate));
5002 CHECK(!weak_map.IsEmpty());
5003
5004 LocalContext env;
5005 Local<Object> value = v8::Object::New(isolate);
5006
5007 Local<Object> local1 = v8::Object::New(isolate);
5008 CHECK(!weak_map->Has(local1));
5009 CHECK(weak_map->Get(local1)->IsUndefined());
5010 weak_map->Set(local1, value);
5011 CHECK(weak_map->Has(local1));
5012 CHECK(value->Equals(env.local(), weak_map->Get(local1)).FromJust());
5013
5014 WeakCallCounter counter(1234);
5015 WeakCallCounterAndPersistent<Value> o1(&counter);
5016 WeakCallCounterAndPersistent<Value> o2(&counter);
5017 WeakCallCounterAndPersistent<Value> s1(&counter);
5018 {
5019 HandleScope scope(isolate);
5020 Local<v8::Object> obj1 = v8::Object::New(isolate);
5021 Local<v8::Object> obj2 = v8::Object::New(isolate);
5022 Local<v8::Symbol> sym1 = v8::Symbol::New(isolate);
5023
5024 weak_map->Set(obj1, value);
5025 weak_map->Set(obj2, value);
5026 weak_map->Set(sym1, value);
5027
5028 o1.handle.Reset(isolate, obj1);
5029 o2.handle.Reset(isolate, obj2);
5030 s1.handle.Reset(isolate, sym1);
5031
5032 CHECK(weak_map->Has(local1));
5033 CHECK(weak_map->Has(obj1));
5034 CHECK(weak_map->Has(obj2));
5035 CHECK(weak_map->Has(sym1));
5036
5037 CHECK(value->Equals(env.local(), weak_map->Get(local1)).FromJust());
5038 CHECK(value->Equals(env.local(), weak_map->Get(obj1)).FromJust());
5039 CHECK(value->Equals(env.local(), weak_map->Get(obj2)).FromJust());
5040 CHECK(value->Equals(env.local(), weak_map->Get(sym1)).FromJust());
5041 }
5042 CcTest::heap()->CollectAllGarbage();
5043 {
5044 HandleScope scope(isolate);
5045 CHECK(value->Equals(env.local(), weak_map->Get(local1)).FromJust());
5046 CHECK(value->Equals(env.local(),
5047 weak_map->Get(Local<Value>::New(isolate, o1.handle)))
5048 .FromJust());
5049 CHECK(value->Equals(env.local(),
5050 weak_map->Get(Local<Value>::New(isolate, o2.handle)))
5051 .FromJust());
5052 CHECK(value->Equals(env.local(),
5053 weak_map->Get(Local<Value>::New(isolate, s1.handle)))
5054 .FromJust());
5055 }
5056
5057 o1.handle.SetWeak(&o1, &WeakPointerCallback,
5058 v8::WeakCallbackType::kParameter);
5059 o2.handle.SetWeak(&o2, &WeakPointerCallback,
5060 v8::WeakCallbackType::kParameter);
5061 s1.handle.SetWeak(&s1, &WeakPointerCallback,
5062 v8::WeakCallbackType::kParameter);
5063
5064 CcTest::heap()->CollectAllGarbage();
5065 CHECK_EQ(3, counter.NumberOfWeakCalls());
5066
5067 CHECK(o1.handle.IsEmpty());
5068 CHECK(o2.handle.IsEmpty());
5069 CHECK(s1.handle.IsEmpty());
5070
5071 CHECK(value->Equals(env.local(), weak_map->Get(local1)).FromJust());
5072 CHECK(weak_map->Delete(local1));
5073 CHECK(!weak_map->Has(local1));
5074 CHECK(weak_map->Get(local1)->IsUndefined());
Steve Blocka7e24c12009-10-30 11:49:00 +00005075}
5076
5077
5078THREADED_TEST(GetSetProperty) {
Steve Blocka7e24c12009-10-30 11:49:00 +00005079 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005080 v8::Isolate* isolate = context->GetIsolate();
5081 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005082 CHECK(context->Global()
5083 ->Set(context.local(), v8_str("foo"), v8_num(14))
5084 .FromJust());
5085 CHECK(context->Global()
5086 ->Set(context.local(), v8_str("12"), v8_num(92))
5087 .FromJust());
5088 CHECK(context->Global()
5089 ->Set(context.local(), v8::Integer::New(isolate, 16), v8_num(32))
5090 .FromJust());
5091 CHECK(context->Global()
5092 ->Set(context.local(), v8_num(13), v8_num(56))
5093 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005094 Local<Value> foo = CompileRun("this.foo");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005095 CHECK_EQ(14, foo->Int32Value(context.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005096 Local<Value> twelve = CompileRun("this[12]");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005097 CHECK_EQ(92, twelve->Int32Value(context.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005098 Local<Value> sixteen = CompileRun("this[16]");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005099 CHECK_EQ(32, sixteen->Int32Value(context.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005100 Local<Value> thirteen = CompileRun("this[13]");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005101 CHECK_EQ(56, thirteen->Int32Value(context.local()).FromJust());
5102 CHECK_EQ(92, context->Global()
5103 ->Get(context.local(), v8::Integer::New(isolate, 12))
5104 .ToLocalChecked()
5105 ->Int32Value(context.local())
5106 .FromJust());
5107 CHECK_EQ(92, context->Global()
5108 ->Get(context.local(), v8_str("12"))
5109 .ToLocalChecked()
5110 ->Int32Value(context.local())
5111 .FromJust());
5112 CHECK_EQ(92, context->Global()
5113 ->Get(context.local(), v8_num(12))
5114 .ToLocalChecked()
5115 ->Int32Value(context.local())
5116 .FromJust());
5117 CHECK_EQ(32, context->Global()
5118 ->Get(context.local(), v8::Integer::New(isolate, 16))
5119 .ToLocalChecked()
5120 ->Int32Value(context.local())
5121 .FromJust());
5122 CHECK_EQ(32, context->Global()
5123 ->Get(context.local(), v8_str("16"))
5124 .ToLocalChecked()
5125 ->Int32Value(context.local())
5126 .FromJust());
5127 CHECK_EQ(32, context->Global()
5128 ->Get(context.local(), v8_num(16))
5129 .ToLocalChecked()
5130 ->Int32Value(context.local())
5131 .FromJust());
5132 CHECK_EQ(56, context->Global()
5133 ->Get(context.local(), v8::Integer::New(isolate, 13))
5134 .ToLocalChecked()
5135 ->Int32Value(context.local())
5136 .FromJust());
5137 CHECK_EQ(56, context->Global()
5138 ->Get(context.local(), v8_str("13"))
5139 .ToLocalChecked()
5140 ->Int32Value(context.local())
5141 .FromJust());
5142 CHECK_EQ(56, context->Global()
5143 ->Get(context.local(), v8_num(13))
5144 .ToLocalChecked()
5145 ->Int32Value(context.local())
5146 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005147}
5148
5149
5150THREADED_TEST(PropertyAttributes) {
Steve Blocka7e24c12009-10-30 11:49:00 +00005151 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005152 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005153 // none
5154 Local<String> prop = v8_str("none");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005155 CHECK(context->Global()->Set(context.local(), prop, v8_num(7)).FromJust());
5156 CHECK_EQ(v8::None, context->Global()
5157 ->GetPropertyAttributes(context.local(), prop)
5158 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005159 // read-only
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005160 prop = v8_str("read_only");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005161 context->Global()
5162 ->DefineOwnProperty(context.local(), prop, v8_num(7), v8::ReadOnly)
5163 .FromJust();
5164 CHECK_EQ(7, context->Global()
5165 ->Get(context.local(), prop)
5166 .ToLocalChecked()
5167 ->Int32Value(context.local())
5168 .FromJust());
5169 CHECK_EQ(v8::ReadOnly, context->Global()
5170 ->GetPropertyAttributes(context.local(), prop)
5171 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005172 CompileRun("read_only = 9");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005173 CHECK_EQ(7, context->Global()
5174 ->Get(context.local(), prop)
5175 .ToLocalChecked()
5176 ->Int32Value(context.local())
5177 .FromJust());
5178 CHECK(context->Global()->Set(context.local(), prop, v8_num(10)).FromJust());
5179 CHECK_EQ(7, context->Global()
5180 ->Get(context.local(), prop)
5181 .ToLocalChecked()
5182 ->Int32Value(context.local())
5183 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005184 // dont-delete
5185 prop = v8_str("dont_delete");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005186 context->Global()
5187 ->DefineOwnProperty(context.local(), prop, v8_num(13), v8::DontDelete)
5188 .FromJust();
5189 CHECK_EQ(13, context->Global()
5190 ->Get(context.local(), prop)
5191 .ToLocalChecked()
5192 ->Int32Value(context.local())
5193 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005194 CompileRun("delete dont_delete");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005195 CHECK_EQ(13, context->Global()
5196 ->Get(context.local(), prop)
5197 .ToLocalChecked()
5198 ->Int32Value(context.local())
5199 .FromJust());
5200 CHECK_EQ(v8::DontDelete, context->Global()
5201 ->GetPropertyAttributes(context.local(), prop)
5202 .FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005203 // dont-enum
5204 prop = v8_str("dont_enum");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005205 context->Global()
5206 ->DefineOwnProperty(context.local(), prop, v8_num(28), v8::DontEnum)
5207 .FromJust();
5208 CHECK_EQ(v8::DontEnum, context->Global()
5209 ->GetPropertyAttributes(context.local(), prop)
5210 .FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005211 // absent
5212 prop = v8_str("absent");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005213 CHECK_EQ(v8::None, context->Global()
5214 ->GetPropertyAttributes(context.local(), prop)
5215 .FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005216 Local<Value> fake_prop = v8_num(1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005217 CHECK_EQ(v8::None, context->Global()
5218 ->GetPropertyAttributes(context.local(), fake_prop)
5219 .FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005220 // exception
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005221 TryCatch try_catch(context->GetIsolate());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005222 Local<Value> exception =
5223 CompileRun("({ toString: function() { throw 'exception';} })");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005224 CHECK(context->Global()
5225 ->GetPropertyAttributes(context.local(), exception)
5226 .IsNothing());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005227 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005228 String::Utf8Value exception_value(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005229 CHECK_EQ(0, strcmp("exception", *exception_value));
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00005230 try_catch.Reset();
Steve Blocka7e24c12009-10-30 11:49:00 +00005231}
5232
5233
5234THREADED_TEST(Array) {
Steve Blocka7e24c12009-10-30 11:49:00 +00005235 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005236 v8::HandleScope scope(context->GetIsolate());
5237 Local<v8::Array> array = v8::Array::New(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005238 CHECK_EQ(0u, array->Length());
5239 CHECK(array->Get(context.local(), 0).ToLocalChecked()->IsUndefined());
5240 CHECK(!array->Has(context.local(), 0).FromJust());
5241 CHECK(array->Get(context.local(), 100).ToLocalChecked()->IsUndefined());
5242 CHECK(!array->Has(context.local(), 100).FromJust());
5243 CHECK(array->Set(context.local(), 2, v8_num(7)).FromJust());
5244 CHECK_EQ(3u, array->Length());
5245 CHECK(!array->Has(context.local(), 0).FromJust());
5246 CHECK(!array->Has(context.local(), 1).FromJust());
5247 CHECK(array->Has(context.local(), 2).FromJust());
5248 CHECK_EQ(7, array->Get(context.local(), 2)
5249 .ToLocalChecked()
5250 ->Int32Value(context.local())
5251 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005252 Local<Value> obj = CompileRun("[1, 2, 3]");
Steve Block6ded16b2010-05-10 14:33:55 +01005253 Local<v8::Array> arr = obj.As<v8::Array>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005254 CHECK_EQ(3u, arr->Length());
5255 CHECK_EQ(1, arr->Get(context.local(), 0)
5256 .ToLocalChecked()
5257 ->Int32Value(context.local())
5258 .FromJust());
5259 CHECK_EQ(2, arr->Get(context.local(), 1)
5260 .ToLocalChecked()
5261 ->Int32Value(context.local())
5262 .FromJust());
5263 CHECK_EQ(3, arr->Get(context.local(), 2)
5264 .ToLocalChecked()
5265 ->Int32Value(context.local())
5266 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005267 array = v8::Array::New(context->GetIsolate(), 27);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005268 CHECK_EQ(27u, array->Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005269 array = v8::Array::New(context->GetIsolate(), -27);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005270 CHECK_EQ(0u, array->Length());
Steve Blocka7e24c12009-10-30 11:49:00 +00005271}
5272
5273
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005274void HandleF(const v8::FunctionCallbackInfo<v8::Value>& args) {
5275 v8::EscapableHandleScope scope(args.GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00005276 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005277 Local<v8::Array> result = v8::Array::New(args.GetIsolate(), args.Length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005278 for (int i = 0; i < args.Length(); i++) {
5279 CHECK(result->Set(CcTest::isolate()->GetCurrentContext(), i, args[i])
5280 .FromJust());
5281 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005282 args.GetReturnValue().Set(scope.Escape(result));
Steve Blocka7e24c12009-10-30 11:49:00 +00005283}
5284
5285
5286THREADED_TEST(Vector) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005287 v8::Isolate* isolate = CcTest::isolate();
5288 v8::HandleScope scope(isolate);
5289 Local<ObjectTemplate> global = ObjectTemplate::New(isolate);
5290 global->Set(v8_str("f"), v8::FunctionTemplate::New(isolate, HandleF));
Steve Blocka7e24c12009-10-30 11:49:00 +00005291 LocalContext context(0, global);
5292
5293 const char* fun = "f()";
Steve Block6ded16b2010-05-10 14:33:55 +01005294 Local<v8::Array> a0 = CompileRun(fun).As<v8::Array>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005295 CHECK_EQ(0u, a0->Length());
Steve Blocka7e24c12009-10-30 11:49:00 +00005296
5297 const char* fun2 = "f(11)";
Steve Block6ded16b2010-05-10 14:33:55 +01005298 Local<v8::Array> a1 = CompileRun(fun2).As<v8::Array>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005299 CHECK_EQ(1u, a1->Length());
5300 CHECK_EQ(11, a1->Get(context.local(), 0)
5301 .ToLocalChecked()
5302 ->Int32Value(context.local())
5303 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005304
5305 const char* fun3 = "f(12, 13)";
Steve Block6ded16b2010-05-10 14:33:55 +01005306 Local<v8::Array> a2 = CompileRun(fun3).As<v8::Array>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005307 CHECK_EQ(2u, a2->Length());
5308 CHECK_EQ(12, a2->Get(context.local(), 0)
5309 .ToLocalChecked()
5310 ->Int32Value(context.local())
5311 .FromJust());
5312 CHECK_EQ(13, a2->Get(context.local(), 1)
5313 .ToLocalChecked()
5314 ->Int32Value(context.local())
5315 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005316
5317 const char* fun4 = "f(14, 15, 16)";
Steve Block6ded16b2010-05-10 14:33:55 +01005318 Local<v8::Array> a3 = CompileRun(fun4).As<v8::Array>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005319 CHECK_EQ(3u, a3->Length());
5320 CHECK_EQ(14, a3->Get(context.local(), 0)
5321 .ToLocalChecked()
5322 ->Int32Value(context.local())
5323 .FromJust());
5324 CHECK_EQ(15, a3->Get(context.local(), 1)
5325 .ToLocalChecked()
5326 ->Int32Value(context.local())
5327 .FromJust());
5328 CHECK_EQ(16, a3->Get(context.local(), 2)
5329 .ToLocalChecked()
5330 ->Int32Value(context.local())
5331 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005332
5333 const char* fun5 = "f(17, 18, 19, 20)";
Steve Block6ded16b2010-05-10 14:33:55 +01005334 Local<v8::Array> a4 = CompileRun(fun5).As<v8::Array>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005335 CHECK_EQ(4u, a4->Length());
5336 CHECK_EQ(17, a4->Get(context.local(), 0)
5337 .ToLocalChecked()
5338 ->Int32Value(context.local())
5339 .FromJust());
5340 CHECK_EQ(18, a4->Get(context.local(), 1)
5341 .ToLocalChecked()
5342 ->Int32Value(context.local())
5343 .FromJust());
5344 CHECK_EQ(19, a4->Get(context.local(), 2)
5345 .ToLocalChecked()
5346 ->Int32Value(context.local())
5347 .FromJust());
5348 CHECK_EQ(20, a4->Get(context.local(), 3)
5349 .ToLocalChecked()
5350 ->Int32Value(context.local())
5351 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005352}
5353
5354
5355THREADED_TEST(FunctionCall) {
Steve Blocka7e24c12009-10-30 11:49:00 +00005356 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005357 v8::Isolate* isolate = context->GetIsolate();
5358 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00005359 CompileRun(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005360 "function Foo() {"
5361 " var result = [];"
5362 " for (var i = 0; i < arguments.length; i++) {"
5363 " result.push(arguments[i]);"
5364 " }"
5365 " return result;"
5366 "}"
5367 "function ReturnThisSloppy() {"
5368 " return this;"
5369 "}"
5370 "function ReturnThisStrict() {"
5371 " 'use strict';"
5372 " return this;"
5373 "}");
5374 Local<Function> Foo = Local<Function>::Cast(
5375 context->Global()->Get(context.local(), v8_str("Foo")).ToLocalChecked());
5376 Local<Function> ReturnThisSloppy = Local<Function>::Cast(
5377 context->Global()
5378 ->Get(context.local(), v8_str("ReturnThisSloppy"))
5379 .ToLocalChecked());
5380 Local<Function> ReturnThisStrict = Local<Function>::Cast(
5381 context->Global()
5382 ->Get(context.local(), v8_str("ReturnThisStrict"))
5383 .ToLocalChecked());
Steve Blocka7e24c12009-10-30 11:49:00 +00005384
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005385 v8::Local<Value>* args0 = NULL;
5386 Local<v8::Array> a0 = Local<v8::Array>::Cast(
5387 Foo->Call(context.local(), Foo, 0, args0).ToLocalChecked());
5388 CHECK_EQ(0u, a0->Length());
Steve Blocka7e24c12009-10-30 11:49:00 +00005389
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005390 v8::Local<Value> args1[] = {v8_num(1.1)};
5391 Local<v8::Array> a1 = Local<v8::Array>::Cast(
5392 Foo->Call(context.local(), Foo, 1, args1).ToLocalChecked());
5393 CHECK_EQ(1u, a1->Length());
5394 CHECK_EQ(1.1, a1->Get(context.local(), v8::Integer::New(isolate, 0))
5395 .ToLocalChecked()
5396 ->NumberValue(context.local())
5397 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005398
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005399 v8::Local<Value> args2[] = {v8_num(2.2), v8_num(3.3)};
5400 Local<v8::Array> a2 = Local<v8::Array>::Cast(
5401 Foo->Call(context.local(), Foo, 2, args2).ToLocalChecked());
5402 CHECK_EQ(2u, a2->Length());
5403 CHECK_EQ(2.2, a2->Get(context.local(), v8::Integer::New(isolate, 0))
5404 .ToLocalChecked()
5405 ->NumberValue(context.local())
5406 .FromJust());
5407 CHECK_EQ(3.3, a2->Get(context.local(), v8::Integer::New(isolate, 1))
5408 .ToLocalChecked()
5409 ->NumberValue(context.local())
5410 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005411
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005412 v8::Local<Value> args3[] = {v8_num(4.4), v8_num(5.5), v8_num(6.6)};
5413 Local<v8::Array> a3 = Local<v8::Array>::Cast(
5414 Foo->Call(context.local(), Foo, 3, args3).ToLocalChecked());
5415 CHECK_EQ(3u, a3->Length());
5416 CHECK_EQ(4.4, a3->Get(context.local(), v8::Integer::New(isolate, 0))
5417 .ToLocalChecked()
5418 ->NumberValue(context.local())
5419 .FromJust());
5420 CHECK_EQ(5.5, a3->Get(context.local(), v8::Integer::New(isolate, 1))
5421 .ToLocalChecked()
5422 ->NumberValue(context.local())
5423 .FromJust());
5424 CHECK_EQ(6.6, a3->Get(context.local(), v8::Integer::New(isolate, 2))
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> args4[] = {v8_num(7.7), v8_num(8.8), v8_num(9.9),
5430 v8_num(10.11)};
5431 Local<v8::Array> a4 = Local<v8::Array>::Cast(
5432 Foo->Call(context.local(), Foo, 4, args4).ToLocalChecked());
5433 CHECK_EQ(4u, a4->Length());
5434 CHECK_EQ(7.7, a4->Get(context.local(), v8::Integer::New(isolate, 0))
5435 .ToLocalChecked()
5436 ->NumberValue(context.local())
5437 .FromJust());
5438 CHECK_EQ(8.8, a4->Get(context.local(), v8::Integer::New(isolate, 1))
5439 .ToLocalChecked()
5440 ->NumberValue(context.local())
5441 .FromJust());
5442 CHECK_EQ(9.9, a4->Get(context.local(), v8::Integer::New(isolate, 2))
5443 .ToLocalChecked()
5444 ->NumberValue(context.local())
5445 .FromJust());
5446 CHECK_EQ(10.11, a4->Get(context.local(), v8::Integer::New(isolate, 3))
5447 .ToLocalChecked()
5448 ->NumberValue(context.local())
5449 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005450
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005451 Local<v8::Value> r1 =
5452 ReturnThisSloppy->Call(context.local(), v8::Undefined(isolate), 0, NULL)
5453 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005454 CHECK(r1->StrictEquals(context->Global()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005455 Local<v8::Value> r2 =
5456 ReturnThisSloppy->Call(context.local(), v8::Null(isolate), 0, NULL)
5457 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005458 CHECK(r2->StrictEquals(context->Global()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005459 Local<v8::Value> r3 =
5460 ReturnThisSloppy->Call(context.local(), v8_num(42), 0, NULL)
5461 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005462 CHECK(r3->IsNumberObject());
5463 CHECK_EQ(42.0, r3.As<v8::NumberObject>()->ValueOf());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005464 Local<v8::Value> r4 =
5465 ReturnThisSloppy->Call(context.local(), v8_str("hello"), 0, NULL)
5466 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005467 CHECK(r4->IsStringObject());
5468 CHECK(r4.As<v8::StringObject>()->ValueOf()->StrictEquals(v8_str("hello")));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005469 Local<v8::Value> r5 =
5470 ReturnThisSloppy->Call(context.local(), v8::True(isolate), 0, NULL)
5471 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005472 CHECK(r5->IsBooleanObject());
5473 CHECK(r5.As<v8::BooleanObject>()->ValueOf());
Steve Blocka7e24c12009-10-30 11:49:00 +00005474
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005475 Local<v8::Value> r6 =
5476 ReturnThisStrict->Call(context.local(), v8::Undefined(isolate), 0, NULL)
5477 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005478 CHECK(r6->IsUndefined());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005479 Local<v8::Value> r7 =
5480 ReturnThisStrict->Call(context.local(), v8::Null(isolate), 0, NULL)
5481 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005482 CHECK(r7->IsNull());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005483 Local<v8::Value> r8 =
5484 ReturnThisStrict->Call(context.local(), v8_num(42), 0, NULL)
5485 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005486 CHECK(r8->StrictEquals(v8_num(42)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005487 Local<v8::Value> r9 =
5488 ReturnThisStrict->Call(context.local(), v8_str("hello"), 0, NULL)
5489 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005490 CHECK(r9->StrictEquals(v8_str("hello")));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005491 Local<v8::Value> r10 =
5492 ReturnThisStrict->Call(context.local(), v8::True(isolate), 0, NULL)
5493 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005494 CHECK(r10->StrictEquals(v8::True(isolate)));
Steve Blocka7e24c12009-10-30 11:49:00 +00005495}
5496
5497
5498THREADED_TEST(ConstructCall) {
Steve Blocka7e24c12009-10-30 11:49:00 +00005499 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005500 v8::Isolate* isolate = context->GetIsolate();
5501 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00005502 CompileRun(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005503 "function Foo() {"
5504 " var result = [];"
5505 " for (var i = 0; i < arguments.length; i++) {"
5506 " result.push(arguments[i]);"
5507 " }"
5508 " return result;"
5509 "}");
5510 Local<Function> Foo = Local<Function>::Cast(
5511 context->Global()->Get(context.local(), v8_str("Foo")).ToLocalChecked());
Steve Blocka7e24c12009-10-30 11:49:00 +00005512
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005513 v8::Local<Value>* args0 = NULL;
5514 Local<v8::Array> a0 = Local<v8::Array>::Cast(
5515 Foo->NewInstance(context.local(), 0, args0).ToLocalChecked());
5516 CHECK_EQ(0u, a0->Length());
Steve Blocka7e24c12009-10-30 11:49:00 +00005517
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005518 v8::Local<Value> args1[] = {v8_num(1.1)};
5519 Local<v8::Array> a1 = Local<v8::Array>::Cast(
5520 Foo->NewInstance(context.local(), 1, args1).ToLocalChecked());
5521 CHECK_EQ(1u, a1->Length());
5522 CHECK_EQ(1.1, a1->Get(context.local(), v8::Integer::New(isolate, 0))
5523 .ToLocalChecked()
5524 ->NumberValue(context.local())
5525 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005526
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005527 v8::Local<Value> args2[] = {v8_num(2.2), v8_num(3.3)};
5528 Local<v8::Array> a2 = Local<v8::Array>::Cast(
5529 Foo->NewInstance(context.local(), 2, args2).ToLocalChecked());
5530 CHECK_EQ(2u, a2->Length());
5531 CHECK_EQ(2.2, a2->Get(context.local(), v8::Integer::New(isolate, 0))
5532 .ToLocalChecked()
5533 ->NumberValue(context.local())
5534 .FromJust());
5535 CHECK_EQ(3.3, a2->Get(context.local(), v8::Integer::New(isolate, 1))
5536 .ToLocalChecked()
5537 ->NumberValue(context.local())
5538 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005539
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005540 v8::Local<Value> args3[] = {v8_num(4.4), v8_num(5.5), v8_num(6.6)};
5541 Local<v8::Array> a3 = Local<v8::Array>::Cast(
5542 Foo->NewInstance(context.local(), 3, args3).ToLocalChecked());
5543 CHECK_EQ(3u, a3->Length());
5544 CHECK_EQ(4.4, a3->Get(context.local(), v8::Integer::New(isolate, 0))
5545 .ToLocalChecked()
5546 ->NumberValue(context.local())
5547 .FromJust());
5548 CHECK_EQ(5.5, a3->Get(context.local(), v8::Integer::New(isolate, 1))
5549 .ToLocalChecked()
5550 ->NumberValue(context.local())
5551 .FromJust());
5552 CHECK_EQ(6.6, a3->Get(context.local(), v8::Integer::New(isolate, 2))
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> args4[] = {v8_num(7.7), v8_num(8.8), v8_num(9.9),
5558 v8_num(10.11)};
5559 Local<v8::Array> a4 = Local<v8::Array>::Cast(
5560 Foo->NewInstance(context.local(), 4, args4).ToLocalChecked());
5561 CHECK_EQ(4u, a4->Length());
5562 CHECK_EQ(7.7, a4->Get(context.local(), v8::Integer::New(isolate, 0))
5563 .ToLocalChecked()
5564 ->NumberValue(context.local())
5565 .FromJust());
5566 CHECK_EQ(8.8, a4->Get(context.local(), v8::Integer::New(isolate, 1))
5567 .ToLocalChecked()
5568 ->NumberValue(context.local())
5569 .FromJust());
5570 CHECK_EQ(9.9, a4->Get(context.local(), v8::Integer::New(isolate, 2))
5571 .ToLocalChecked()
5572 ->NumberValue(context.local())
5573 .FromJust());
5574 CHECK_EQ(10.11, a4->Get(context.local(), v8::Integer::New(isolate, 3))
5575 .ToLocalChecked()
5576 ->NumberValue(context.local())
5577 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005578}
5579
5580
Steve Block6ded16b2010-05-10 14:33:55 +01005581THREADED_TEST(ConversionNumber) {
Steve Block6ded16b2010-05-10 14:33:55 +01005582 LocalContext env;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005583 v8::Isolate* isolate = env->GetIsolate();
5584 v8::HandleScope scope(isolate);
Steve Block6ded16b2010-05-10 14:33:55 +01005585 // Very large number.
5586 CompileRun("var obj = Math.pow(2,32) * 1237;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005587 Local<Value> obj =
5588 env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
5589 CHECK_EQ(5312874545152.0,
5590 obj->ToNumber(env.local()).ToLocalChecked()->Value());
5591 CHECK_EQ(0, obj->ToInt32(env.local()).ToLocalChecked()->Value());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005592 CHECK(0u ==
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005593 obj->ToUint32(env.local())
5594 .ToLocalChecked()
5595 ->Value()); // NOLINT - no CHECK_EQ for unsigned.
Steve Block6ded16b2010-05-10 14:33:55 +01005596 // Large number.
5597 CompileRun("var obj = -1234567890123;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005598 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
5599 CHECK_EQ(-1234567890123.0,
5600 obj->ToNumber(env.local()).ToLocalChecked()->Value());
5601 CHECK_EQ(-1912276171, obj->ToInt32(env.local()).ToLocalChecked()->Value());
5602 CHECK(2382691125u ==
5603 obj->ToUint32(env.local()).ToLocalChecked()->Value()); // NOLINT
Steve Block6ded16b2010-05-10 14:33:55 +01005604 // Small positive integer.
5605 CompileRun("var obj = 42;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005606 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
5607 CHECK_EQ(42.0, obj->ToNumber(env.local()).ToLocalChecked()->Value());
5608 CHECK_EQ(42, obj->ToInt32(env.local()).ToLocalChecked()->Value());
5609 CHECK(42u == obj->ToUint32(env.local()).ToLocalChecked()->Value()); // NOLINT
Steve Block6ded16b2010-05-10 14:33:55 +01005610 // Negative integer.
5611 CompileRun("var obj = -37;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005612 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
5613 CHECK_EQ(-37.0, obj->ToNumber(env.local()).ToLocalChecked()->Value());
5614 CHECK_EQ(-37, obj->ToInt32(env.local()).ToLocalChecked()->Value());
5615 CHECK(4294967259u ==
5616 obj->ToUint32(env.local()).ToLocalChecked()->Value()); // NOLINT
Steve Block6ded16b2010-05-10 14:33:55 +01005617 // Positive non-int32 integer.
5618 CompileRun("var obj = 0x81234567;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005619 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
5620 CHECK_EQ(2166572391.0, obj->ToNumber(env.local()).ToLocalChecked()->Value());
5621 CHECK_EQ(-2128394905, obj->ToInt32(env.local()).ToLocalChecked()->Value());
5622 CHECK(2166572391u ==
5623 obj->ToUint32(env.local()).ToLocalChecked()->Value()); // NOLINT
Steve Block6ded16b2010-05-10 14:33:55 +01005624 // Fraction.
5625 CompileRun("var obj = 42.3;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005626 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
5627 CHECK_EQ(42.3, obj->ToNumber(env.local()).ToLocalChecked()->Value());
5628 CHECK_EQ(42, obj->ToInt32(env.local()).ToLocalChecked()->Value());
5629 CHECK(42u == obj->ToUint32(env.local()).ToLocalChecked()->Value()); // NOLINT
Steve Block6ded16b2010-05-10 14:33:55 +01005630 // Large negative fraction.
5631 CompileRun("var obj = -5726623061.75;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005632 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
5633 CHECK_EQ(-5726623061.75,
5634 obj->ToNumber(env.local()).ToLocalChecked()->Value());
5635 CHECK_EQ(-1431655765, obj->ToInt32(env.local()).ToLocalChecked()->Value());
5636 CHECK(2863311531u ==
5637 obj->ToUint32(env.local()).ToLocalChecked()->Value()); // NOLINT
Steve Block6ded16b2010-05-10 14:33:55 +01005638}
5639
5640
5641THREADED_TEST(isNumberType) {
Steve Block6ded16b2010-05-10 14:33:55 +01005642 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005643 v8::HandleScope scope(env->GetIsolate());
Steve Block6ded16b2010-05-10 14:33:55 +01005644 // Very large number.
5645 CompileRun("var obj = Math.pow(2,32) * 1237;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005646 Local<Value> obj =
5647 env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
Steve Block6ded16b2010-05-10 14:33:55 +01005648 CHECK(!obj->IsInt32());
5649 CHECK(!obj->IsUint32());
5650 // Large negative number.
5651 CompileRun("var obj = -1234567890123;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005652 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
Steve Block6ded16b2010-05-10 14:33:55 +01005653 CHECK(!obj->IsInt32());
5654 CHECK(!obj->IsUint32());
5655 // Small positive integer.
5656 CompileRun("var obj = 42;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005657 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
Steve Block6ded16b2010-05-10 14:33:55 +01005658 CHECK(obj->IsInt32());
5659 CHECK(obj->IsUint32());
5660 // Negative integer.
5661 CompileRun("var obj = -37;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005662 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
Steve Block6ded16b2010-05-10 14:33:55 +01005663 CHECK(obj->IsInt32());
5664 CHECK(!obj->IsUint32());
5665 // Positive non-int32 integer.
5666 CompileRun("var obj = 0x81234567;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005667 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
Steve Block6ded16b2010-05-10 14:33:55 +01005668 CHECK(!obj->IsInt32());
5669 CHECK(obj->IsUint32());
5670 // Fraction.
5671 CompileRun("var obj = 42.3;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005672 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
Steve Block6ded16b2010-05-10 14:33:55 +01005673 CHECK(!obj->IsInt32());
5674 CHECK(!obj->IsUint32());
5675 // Large negative fraction.
5676 CompileRun("var obj = -5726623061.75;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005677 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
Steve Block6ded16b2010-05-10 14:33:55 +01005678 CHECK(!obj->IsInt32());
5679 CHECK(!obj->IsUint32());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005680 // Positive zero
5681 CompileRun("var obj = 0.0;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005682 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005683 CHECK(obj->IsInt32());
5684 CHECK(obj->IsUint32());
5685 // Positive zero
5686 CompileRun("var obj = -0.0;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005687 obj = env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01005688 CHECK(!obj->IsInt32());
5689 CHECK(!obj->IsUint32());
Steve Block6ded16b2010-05-10 14:33:55 +01005690}
5691
5692
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005693static void CheckUncle(v8::TryCatch* try_catch) {
5694 CHECK(try_catch->HasCaught());
5695 String::Utf8Value str_value(try_catch->Exception());
5696 CHECK_EQ(0, strcmp(*str_value, "uncle?"));
5697 try_catch->Reset();
5698}
5699
5700
Steve Blocka7e24c12009-10-30 11:49:00 +00005701THREADED_TEST(ConversionException) {
Steve Blocka7e24c12009-10-30 11:49:00 +00005702 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005703 v8::Isolate* isolate = env->GetIsolate();
5704 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00005705 CompileRun(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005706 "function TestClass() { };"
5707 "TestClass.prototype.toString = function () { throw 'uncle?'; };"
5708 "var obj = new TestClass();");
5709 Local<Value> obj =
5710 env->Global()->Get(env.local(), v8_str("obj")).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00005711
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005712 v8::TryCatch try_catch(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00005713
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005714 CHECK(obj->ToString(env.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00005715 CheckUncle(&try_catch);
5716
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005717 CHECK(obj->ToNumber(env.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00005718 CheckUncle(&try_catch);
5719
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005720 CHECK(obj->ToInteger(env.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00005721 CheckUncle(&try_catch);
5722
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005723 CHECK(obj->ToUint32(env.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00005724 CheckUncle(&try_catch);
5725
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005726 CHECK(obj->ToInt32(env.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00005727 CheckUncle(&try_catch);
5728
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005729 CHECK(v8::Undefined(isolate)->ToObject(env.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00005730 CHECK(try_catch.HasCaught());
5731 try_catch.Reset();
5732
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005733 CHECK(obj->Int32Value(env.local()).IsNothing());
Steve Blocka7e24c12009-10-30 11:49:00 +00005734 CheckUncle(&try_catch);
5735
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005736 CHECK(obj->Uint32Value(env.local()).IsNothing());
Steve Blocka7e24c12009-10-30 11:49:00 +00005737 CheckUncle(&try_catch);
5738
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005739 CHECK(obj->NumberValue(env.local()).IsNothing());
Steve Blocka7e24c12009-10-30 11:49:00 +00005740 CheckUncle(&try_catch);
5741
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005742 CHECK(obj->IntegerValue(env.local()).IsNothing());
Steve Blocka7e24c12009-10-30 11:49:00 +00005743 CheckUncle(&try_catch);
5744}
5745
5746
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005747void ThrowFromC(const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +00005748 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005749 args.GetIsolate()->ThrowException(v8_str("konto"));
Steve Blocka7e24c12009-10-30 11:49:00 +00005750}
5751
5752
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005753void CCatcher(const v8::FunctionCallbackInfo<v8::Value>& args) {
5754 if (args.Length() < 1) {
5755 args.GetReturnValue().Set(false);
5756 return;
5757 }
5758 v8::HandleScope scope(args.GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005759 v8::TryCatch try_catch(args.GetIsolate());
5760 Local<Value> result =
5761 CompileRun(args[0]
5762 ->ToString(args.GetIsolate()->GetCurrentContext())
5763 .ToLocalChecked());
Steve Blocka7e24c12009-10-30 11:49:00 +00005764 CHECK(!try_catch.HasCaught() || result.IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005765 args.GetReturnValue().Set(try_catch.HasCaught());
Steve Blocka7e24c12009-10-30 11:49:00 +00005766}
5767
5768
5769THREADED_TEST(APICatch) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005770 v8::Isolate* isolate = CcTest::isolate();
5771 v8::HandleScope scope(isolate);
5772 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00005773 templ->Set(v8_str("ThrowFromC"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005774 v8::FunctionTemplate::New(isolate, ThrowFromC));
Steve Blocka7e24c12009-10-30 11:49:00 +00005775 LocalContext context(0, templ);
5776 CompileRun(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005777 "var thrown = false;"
5778 "try {"
5779 " ThrowFromC();"
5780 "} catch (e) {"
5781 " thrown = true;"
5782 "}");
5783 Local<Value> thrown = context->Global()
5784 ->Get(context.local(), v8_str("thrown"))
5785 .ToLocalChecked();
5786 CHECK(thrown->BooleanValue(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00005787}
5788
5789
5790THREADED_TEST(APIThrowTryCatch) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005791 v8::Isolate* isolate = CcTest::isolate();
5792 v8::HandleScope scope(isolate);
5793 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00005794 templ->Set(v8_str("ThrowFromC"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005795 v8::FunctionTemplate::New(isolate, ThrowFromC));
Steve Blocka7e24c12009-10-30 11:49:00 +00005796 LocalContext context(0, templ);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005797 v8::TryCatch try_catch(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00005798 CompileRun("ThrowFromC();");
5799 CHECK(try_catch.HasCaught());
5800}
5801
5802
5803// Test that a try-finally block doesn't shadow a try-catch block
5804// when setting up an external handler.
5805//
5806// BUG(271): Some of the exception propagation does not work on the
5807// ARM simulator because the simulator separates the C++ stack and the
5808// JS stack. This test therefore fails on the simulator. The test is
5809// not threaded to allow the threading tests to run on the simulator.
5810TEST(TryCatchInTryFinally) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005811 v8::Isolate* isolate = CcTest::isolate();
5812 v8::HandleScope scope(isolate);
5813 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005814 templ->Set(v8_str("CCatcher"), v8::FunctionTemplate::New(isolate, CCatcher));
Steve Blocka7e24c12009-10-30 11:49:00 +00005815 LocalContext context(0, templ);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005816 Local<Value> result = CompileRun(
5817 "try {"
5818 " try {"
5819 " CCatcher('throw 7;');"
5820 " } finally {"
5821 " }"
5822 "} catch (e) {"
5823 "}");
Steve Blocka7e24c12009-10-30 11:49:00 +00005824 CHECK(result->IsTrue());
5825}
5826
5827
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005828static void check_custom_error_tostring(v8::Local<v8::Message> message,
5829 v8::Local<v8::Value> data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005830 const char* uncaught_error = "Uncaught MyError toString";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005831 CHECK(message->Get()
5832 ->Equals(CcTest::isolate()->GetCurrentContext(),
5833 v8_str(uncaught_error))
5834 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005835}
5836
5837
5838TEST(CustomErrorToString) {
5839 LocalContext context;
5840 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005841 context->GetIsolate()->AddMessageListener(check_custom_error_tostring);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005842 CompileRun(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005843 "function MyError(name, message) { "
5844 " this.name = name; "
5845 " this.message = message; "
5846 "} "
5847 "MyError.prototype = Object.create(Error.prototype); "
5848 "MyError.prototype.toString = function() { "
5849 " return 'MyError toString'; "
5850 "}; "
5851 "throw new MyError('my name', 'my message'); ");
5852 context->GetIsolate()->RemoveMessageListeners(check_custom_error_tostring);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005853}
5854
5855
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005856static void check_custom_error_message(v8::Local<v8::Message> message,
5857 v8::Local<v8::Value> data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005858 const char* uncaught_error = "Uncaught MyError: my message";
5859 printf("%s\n", *v8::String::Utf8Value(message->Get()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005860 CHECK(message->Get()
5861 ->Equals(CcTest::isolate()->GetCurrentContext(),
5862 v8_str(uncaught_error))
5863 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005864}
5865
5866
5867TEST(CustomErrorMessage) {
5868 LocalContext context;
5869 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005870 context->GetIsolate()->AddMessageListener(check_custom_error_message);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005871
5872 // Handlebars.
5873 CompileRun(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005874 "function MyError(msg) { "
5875 " this.name = 'MyError'; "
5876 " this.message = msg; "
5877 "} "
5878 "MyError.prototype = new Error(); "
5879 "throw new MyError('my message'); ");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005880
5881 // Closure.
5882 CompileRun(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005883 "function MyError(msg) { "
5884 " this.name = 'MyError'; "
5885 " this.message = msg; "
5886 "} "
5887 "inherits = function(childCtor, parentCtor) { "
5888 " function tempCtor() {}; "
5889 " tempCtor.prototype = parentCtor.prototype; "
5890 " childCtor.superClass_ = parentCtor.prototype; "
5891 " childCtor.prototype = new tempCtor(); "
5892 " childCtor.prototype.constructor = childCtor; "
5893 "}; "
5894 "inherits(MyError, Error); "
5895 "throw new MyError('my message'); ");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005896
5897 // Object.create.
5898 CompileRun(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005899 "function MyError(msg) { "
5900 " this.name = 'MyError'; "
5901 " this.message = msg; "
5902 "} "
5903 "MyError.prototype = Object.create(Error.prototype); "
5904 "throw new MyError('my message'); ");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005905
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005906 context->GetIsolate()->RemoveMessageListeners(check_custom_error_message);
Ben Murdochb8e0da22011-05-16 14:20:40 +01005907}
5908
5909
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005910static void check_custom_rethrowing_message(v8::Local<v8::Message> message,
5911 v8::Local<v8::Value> data) {
5912 const char* uncaught_error = "Uncaught exception";
5913 CHECK(message->Get()
5914 ->Equals(CcTest::isolate()->GetCurrentContext(),
5915 v8_str(uncaught_error))
5916 .FromJust());
5917}
5918
5919
5920TEST(CustomErrorRethrowsOnToString) {
5921 LocalContext context;
5922 v8::HandleScope scope(context->GetIsolate());
5923 context->GetIsolate()->AddMessageListener(check_custom_rethrowing_message);
5924
5925 CompileRun(
5926 "var e = { toString: function() { throw e; } };"
5927 "try { throw e; } finally {}");
5928
5929 context->GetIsolate()->RemoveMessageListeners(
5930 check_custom_rethrowing_message);
5931}
5932
5933
5934static void receive_message(v8::Local<v8::Message> message,
5935 v8::Local<v8::Value> data) {
Steve Blocka7e24c12009-10-30 11:49:00 +00005936 message->Get();
5937 message_received = true;
5938}
5939
5940
5941TEST(APIThrowMessage) {
5942 message_received = false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005943 v8::Isolate* isolate = CcTest::isolate();
5944 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005945 isolate->AddMessageListener(receive_message);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005946 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00005947 templ->Set(v8_str("ThrowFromC"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005948 v8::FunctionTemplate::New(isolate, ThrowFromC));
Steve Blocka7e24c12009-10-30 11:49:00 +00005949 LocalContext context(0, templ);
5950 CompileRun("ThrowFromC();");
5951 CHECK(message_received);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005952 isolate->RemoveMessageListeners(receive_message);
Steve Blocka7e24c12009-10-30 11:49:00 +00005953}
5954
5955
5956TEST(APIThrowMessageAndVerboseTryCatch) {
5957 message_received = false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005958 v8::Isolate* isolate = CcTest::isolate();
5959 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005960 isolate->AddMessageListener(receive_message);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005961 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00005962 templ->Set(v8_str("ThrowFromC"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005963 v8::FunctionTemplate::New(isolate, ThrowFromC));
Steve Blocka7e24c12009-10-30 11:49:00 +00005964 LocalContext context(0, templ);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005965 v8::TryCatch try_catch(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00005966 try_catch.SetVerbose(true);
5967 Local<Value> result = CompileRun("ThrowFromC();");
5968 CHECK(try_catch.HasCaught());
5969 CHECK(result.IsEmpty());
5970 CHECK(message_received);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005971 isolate->RemoveMessageListeners(receive_message);
Steve Blocka7e24c12009-10-30 11:49:00 +00005972}
5973
5974
Ben Murdoch8b112d22011-06-08 16:22:53 +01005975TEST(APIStackOverflowAndVerboseTryCatch) {
5976 message_received = false;
Ben Murdoch8b112d22011-06-08 16:22:53 +01005977 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005978 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005979 context->GetIsolate()->AddMessageListener(receive_message);
5980 v8::TryCatch try_catch(context->GetIsolate());
Ben Murdoch8b112d22011-06-08 16:22:53 +01005981 try_catch.SetVerbose(true);
5982 Local<Value> result = CompileRun("function foo() { foo(); } foo();");
5983 CHECK(try_catch.HasCaught());
5984 CHECK(result.IsEmpty());
5985 CHECK(message_received);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005986 context->GetIsolate()->RemoveMessageListeners(receive_message);
Ben Murdoch8b112d22011-06-08 16:22:53 +01005987}
5988
5989
Steve Blocka7e24c12009-10-30 11:49:00 +00005990THREADED_TEST(ExternalScriptException) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005991 v8::Isolate* isolate = CcTest::isolate();
5992 v8::HandleScope scope(isolate);
5993 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00005994 templ->Set(v8_str("ThrowFromC"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005995 v8::FunctionTemplate::New(isolate, ThrowFromC));
Steve Blocka7e24c12009-10-30 11:49:00 +00005996 LocalContext context(0, templ);
5997
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005998 v8::TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005999 Local<Value> result = CompileRun("ThrowFromC(); throw 'panama';");
Steve Blocka7e24c12009-10-30 11:49:00 +00006000 CHECK(result.IsEmpty());
6001 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006002 String::Utf8Value exception_value(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006003 CHECK_EQ(0, strcmp("konto", *exception_value));
Steve Blocka7e24c12009-10-30 11:49:00 +00006004}
6005
6006
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006007void CThrowCountDown(const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +00006008 ApiTestFuzzer::Fuzz();
6009 CHECK_EQ(4, args.Length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006010 v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
6011 int count = args[0]->Int32Value(context).FromJust();
6012 int cInterval = args[2]->Int32Value(context).FromJust();
Steve Blocka7e24c12009-10-30 11:49:00 +00006013 if (count == 0) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006014 args.GetIsolate()->ThrowException(v8_str("FromC"));
6015 return;
Steve Blocka7e24c12009-10-30 11:49:00 +00006016 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006017 Local<v8::Object> global = context->Global();
6018 Local<Value> fun =
6019 global->Get(context, v8_str("JSThrowCountDown")).ToLocalChecked();
6020 v8::Local<Value> argv[] = {v8_num(count - 1), args[1], args[2], args[3]};
Steve Blocka7e24c12009-10-30 11:49:00 +00006021 if (count % cInterval == 0) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006022 v8::TryCatch try_catch(args.GetIsolate());
6023 Local<Value> result = fun.As<Function>()
6024 ->Call(context, global, 4, argv)
6025 .FromMaybe(Local<Value>());
6026 int expected = args[3]->Int32Value(context).FromJust();
Steve Blocka7e24c12009-10-30 11:49:00 +00006027 if (try_catch.HasCaught()) {
6028 CHECK_EQ(expected, count);
6029 CHECK(result.IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006030 CHECK(!CcTest::i_isolate()->has_scheduled_exception());
Steve Blocka7e24c12009-10-30 11:49:00 +00006031 } else {
6032 CHECK_NE(expected, count);
6033 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006034 args.GetReturnValue().Set(result);
6035 return;
Steve Blocka7e24c12009-10-30 11:49:00 +00006036 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006037 args.GetReturnValue().Set(fun.As<Function>()
6038 ->Call(context, global, 4, argv)
6039 .FromMaybe(v8::Local<v8::Value>()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006040 return;
Steve Blocka7e24c12009-10-30 11:49:00 +00006041 }
6042 }
6043}
6044
6045
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006046void JSCheck(const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +00006047 ApiTestFuzzer::Fuzz();
6048 CHECK_EQ(3, args.Length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006049 v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
6050 bool equality = args[0]->BooleanValue(context).FromJust();
6051 int count = args[1]->Int32Value(context).FromJust();
6052 int expected = args[2]->Int32Value(context).FromJust();
Steve Blocka7e24c12009-10-30 11:49:00 +00006053 if (equality) {
6054 CHECK_EQ(count, expected);
6055 } else {
6056 CHECK_NE(count, expected);
6057 }
Steve Blocka7e24c12009-10-30 11:49:00 +00006058}
6059
6060
6061THREADED_TEST(EvalInTryFinally) {
Steve Blocka7e24c12009-10-30 11:49:00 +00006062 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006063 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006064 v8::TryCatch try_catch(context->GetIsolate());
6065 CompileRun(
6066 "(function() {"
6067 " try {"
6068 " eval('asldkf (*&^&*^');"
6069 " } finally {"
6070 " return;"
6071 " }"
6072 "})()");
Steve Blocka7e24c12009-10-30 11:49:00 +00006073 CHECK(!try_catch.HasCaught());
6074}
6075
6076
6077// This test works by making a stack of alternating JavaScript and C
6078// activations. These activations set up exception handlers with regular
6079// intervals, one interval for C activations and another for JavaScript
6080// activations. When enough activations have been created an exception is
6081// thrown and we check that the right activation catches the exception and that
6082// no other activations do. The right activation is always the topmost one with
6083// a handler, regardless of whether it is in JavaScript or C.
6084//
6085// The notation used to describe a test case looks like this:
6086//
6087// *JS[4] *C[3] @JS[2] C[1] JS[0]
6088//
6089// Each entry is an activation, either JS or C. The index is the count at that
6090// level. Stars identify activations with exception handlers, the @ identifies
6091// the exception handler that should catch the exception.
6092//
6093// BUG(271): Some of the exception propagation does not work on the
6094// ARM simulator because the simulator separates the C++ stack and the
6095// JS stack. This test therefore fails on the simulator. The test is
6096// not threaded to allow the threading tests to run on the simulator.
6097TEST(ExceptionOrder) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006098 v8::Isolate* isolate = CcTest::isolate();
6099 v8::HandleScope scope(isolate);
6100 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6101 templ->Set(v8_str("check"), v8::FunctionTemplate::New(isolate, JSCheck));
Steve Blocka7e24c12009-10-30 11:49:00 +00006102 templ->Set(v8_str("CThrowCountDown"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006103 v8::FunctionTemplate::New(isolate, CThrowCountDown));
Steve Blocka7e24c12009-10-30 11:49:00 +00006104 LocalContext context(0, templ);
6105 CompileRun(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006106 "function JSThrowCountDown(count, jsInterval, cInterval, expected) {"
6107 " if (count == 0) throw 'FromJS';"
6108 " if (count % jsInterval == 0) {"
6109 " try {"
6110 " var value = CThrowCountDown(count - 1,"
6111 " jsInterval,"
6112 " cInterval,"
6113 " expected);"
6114 " check(false, count, expected);"
6115 " return value;"
6116 " } catch (e) {"
6117 " check(true, count, expected);"
6118 " }"
6119 " } else {"
6120 " return CThrowCountDown(count - 1, jsInterval, cInterval, expected);"
6121 " }"
6122 "}");
6123 Local<Function> fun = Local<Function>::Cast(
6124 context->Global()
6125 ->Get(context.local(), v8_str("JSThrowCountDown"))
6126 .ToLocalChecked());
Steve Blocka7e24c12009-10-30 11:49:00 +00006127
6128 const int argc = 4;
6129 // count jsInterval cInterval expected
6130
6131 // *JS[4] *C[3] @JS[2] C[1] JS[0]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006132 v8::Local<Value> a0[argc] = {v8_num(4), v8_num(2), v8_num(3), v8_num(2)};
6133 fun->Call(context.local(), fun, argc, a0).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00006134
6135 // JS[5] *C[4] JS[3] @C[2] JS[1] C[0]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006136 v8::Local<Value> a1[argc] = {v8_num(5), v8_num(6), v8_num(1), v8_num(2)};
6137 fun->Call(context.local(), fun, argc, a1).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00006138
6139 // JS[6] @C[5] JS[4] C[3] JS[2] C[1] JS[0]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006140 v8::Local<Value> a2[argc] = {v8_num(6), v8_num(7), v8_num(5), v8_num(5)};
6141 fun->Call(context.local(), fun, argc, a2).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00006142
6143 // @JS[6] C[5] JS[4] C[3] JS[2] C[1] JS[0]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006144 v8::Local<Value> a3[argc] = {v8_num(6), v8_num(6), v8_num(7), v8_num(6)};
6145 fun->Call(context.local(), fun, argc, a3).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00006146
6147 // JS[6] *C[5] @JS[4] C[3] JS[2] C[1] JS[0]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006148 v8::Local<Value> a4[argc] = {v8_num(6), v8_num(4), v8_num(5), v8_num(4)};
6149 fun->Call(context.local(), fun, argc, a4).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00006150
6151 // JS[6] C[5] *JS[4] @C[3] JS[2] C[1] JS[0]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006152 v8::Local<Value> a5[argc] = {v8_num(6), v8_num(4), v8_num(3), v8_num(3)};
6153 fun->Call(context.local(), fun, argc, a5).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00006154}
6155
6156
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006157void ThrowValue(const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +00006158 ApiTestFuzzer::Fuzz();
6159 CHECK_EQ(1, args.Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006160 args.GetIsolate()->ThrowException(args[0]);
Steve Blocka7e24c12009-10-30 11:49:00 +00006161}
6162
6163
6164THREADED_TEST(ThrowValues) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006165 v8::Isolate* isolate = CcTest::isolate();
6166 v8::HandleScope scope(isolate);
6167 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6168 templ->Set(v8_str("Throw"), v8::FunctionTemplate::New(isolate, ThrowValue));
Steve Blocka7e24c12009-10-30 11:49:00 +00006169 LocalContext context(0, templ);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006170 v8::Local<v8::Array> result = v8::Local<v8::Array>::Cast(
6171 CompileRun("function Run(obj) {"
6172 " try {"
6173 " Throw(obj);"
6174 " } catch (e) {"
6175 " return e;"
6176 " }"
6177 " return 'no exception';"
6178 "}"
6179 "[Run('str'), Run(1), Run(0), Run(null), Run(void 0)];"));
6180 CHECK_EQ(5u, result->Length());
6181 CHECK(result->Get(context.local(), v8::Integer::New(isolate, 0))
6182 .ToLocalChecked()
6183 ->IsString());
6184 CHECK(result->Get(context.local(), v8::Integer::New(isolate, 1))
6185 .ToLocalChecked()
6186 ->IsNumber());
6187 CHECK_EQ(1, result->Get(context.local(), v8::Integer::New(isolate, 1))
6188 .ToLocalChecked()
6189 ->Int32Value(context.local())
6190 .FromJust());
6191 CHECK(result->Get(context.local(), v8::Integer::New(isolate, 2))
6192 .ToLocalChecked()
6193 ->IsNumber());
6194 CHECK_EQ(0, result->Get(context.local(), v8::Integer::New(isolate, 2))
6195 .ToLocalChecked()
6196 ->Int32Value(context.local())
6197 .FromJust());
6198 CHECK(result->Get(context.local(), v8::Integer::New(isolate, 3))
6199 .ToLocalChecked()
6200 ->IsNull());
6201 CHECK(result->Get(context.local(), v8::Integer::New(isolate, 4))
6202 .ToLocalChecked()
6203 ->IsUndefined());
Steve Blocka7e24c12009-10-30 11:49:00 +00006204}
6205
6206
6207THREADED_TEST(CatchZero) {
Steve Blocka7e24c12009-10-30 11:49:00 +00006208 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006209 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006210 v8::TryCatch try_catch(context->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00006211 CHECK(!try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006212 CompileRun("throw 10");
Steve Blocka7e24c12009-10-30 11:49:00 +00006213 CHECK(try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006214 CHECK_EQ(10, try_catch.Exception()->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00006215 try_catch.Reset();
6216 CHECK(!try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006217 CompileRun("throw 0");
Steve Blocka7e24c12009-10-30 11:49:00 +00006218 CHECK(try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006219 CHECK_EQ(0, try_catch.Exception()->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00006220}
6221
6222
6223THREADED_TEST(CatchExceptionFromWith) {
Steve Blocka7e24c12009-10-30 11:49:00 +00006224 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006225 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006226 v8::TryCatch try_catch(context->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00006227 CHECK(!try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006228 CompileRun("var o = {}; with (o) { throw 42; }");
Steve Blocka7e24c12009-10-30 11:49:00 +00006229 CHECK(try_catch.HasCaught());
6230}
6231
6232
Ben Murdoche0cee9b2011-05-25 10:26:03 +01006233THREADED_TEST(TryCatchAndFinallyHidingException) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01006234 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006235 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006236 v8::TryCatch try_catch(context->GetIsolate());
Ben Murdoche0cee9b2011-05-25 10:26:03 +01006237 CHECK(!try_catch.HasCaught());
6238 CompileRun("function f(k) { try { this[k]; } finally { return 0; } };");
6239 CompileRun("f({toString: function() { throw 42; }});");
6240 CHECK(!try_catch.HasCaught());
6241}
6242
6243
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006244void WithTryCatch(const v8::FunctionCallbackInfo<v8::Value>& args) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006245 v8::TryCatch try_catch(args.GetIsolate());
Ben Murdoche0cee9b2011-05-25 10:26:03 +01006246}
6247
6248
6249THREADED_TEST(TryCatchAndFinally) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01006250 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006251 v8::Isolate* isolate = context->GetIsolate();
6252 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006253 CHECK(context->Global()
6254 ->Set(context.local(), v8_str("native_with_try_catch"),
6255 v8::FunctionTemplate::New(isolate, WithTryCatch)
6256 ->GetFunction(context.local())
6257 .ToLocalChecked())
6258 .FromJust());
6259 v8::TryCatch try_catch(isolate);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01006260 CHECK(!try_catch.HasCaught());
6261 CompileRun(
6262 "try {\n"
6263 " throw new Error('a');\n"
6264 "} finally {\n"
6265 " native_with_try_catch();\n"
6266 "}\n");
6267 CHECK(try_catch.HasCaught());
6268}
6269
6270
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006271static void TryCatchNested1Helper(int depth) {
6272 if (depth > 0) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006273 v8::TryCatch try_catch(CcTest::isolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006274 try_catch.SetVerbose(true);
6275 TryCatchNested1Helper(depth - 1);
6276 CHECK(try_catch.HasCaught());
6277 try_catch.ReThrow();
6278 } else {
6279 CcTest::isolate()->ThrowException(v8_str("E1"));
6280 }
6281}
6282
6283
6284static void TryCatchNested2Helper(int depth) {
6285 if (depth > 0) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006286 v8::TryCatch try_catch(CcTest::isolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006287 try_catch.SetVerbose(true);
6288 TryCatchNested2Helper(depth - 1);
6289 CHECK(try_catch.HasCaught());
6290 try_catch.ReThrow();
6291 } else {
6292 CompileRun("throw 'E2';");
6293 }
6294}
6295
6296
6297TEST(TryCatchNested) {
6298 v8::V8::Initialize();
Steve Blocka7e24c12009-10-30 11:49:00 +00006299 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006300 v8::HandleScope scope(context->GetIsolate());
6301
6302 {
6303 // Test nested try-catch with a native throw in the end.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006304 v8::TryCatch try_catch(context->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006305 TryCatchNested1Helper(5);
6306 CHECK(try_catch.HasCaught());
6307 CHECK_EQ(0, strcmp(*v8::String::Utf8Value(try_catch.Exception()), "E1"));
6308 }
6309
6310 {
6311 // Test nested try-catch with a JavaScript throw in the end.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006312 v8::TryCatch try_catch(context->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006313 TryCatchNested2Helper(5);
6314 CHECK(try_catch.HasCaught());
6315 CHECK_EQ(0, strcmp(*v8::String::Utf8Value(try_catch.Exception()), "E2"));
6316 }
6317}
6318
6319
6320void TryCatchMixedNestingCheck(v8::TryCatch* try_catch) {
6321 CHECK(try_catch->HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006322 Local<Message> message = try_catch->Message();
6323 Local<Value> resource = message->GetScriptOrigin().ResourceName();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006324 CHECK_EQ(0, strcmp(*v8::String::Utf8Value(resource), "inner"));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006325 CHECK_EQ(0,
6326 strcmp(*v8::String::Utf8Value(message->Get()), "Uncaught Error: a"));
6327 CHECK_EQ(1, message->GetLineNumber(CcTest::isolate()->GetCurrentContext())
6328 .FromJust());
6329 CHECK_EQ(0, message->GetStartColumn(CcTest::isolate()->GetCurrentContext())
6330 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006331}
6332
6333
6334void TryCatchMixedNestingHelper(
6335 const v8::FunctionCallbackInfo<v8::Value>& args) {
6336 ApiTestFuzzer::Fuzz();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006337 v8::TryCatch try_catch(args.GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006338 CompileRunWithOrigin("throw new Error('a');\n", "inner", 0, 0);
6339 CHECK(try_catch.HasCaught());
6340 TryCatchMixedNestingCheck(&try_catch);
6341 try_catch.ReThrow();
6342}
6343
6344
6345// This test ensures that an outer TryCatch in the following situation:
6346// C++/TryCatch -> JS -> C++/TryCatch -> JS w/ SyntaxError
6347// does not clobber the Message object generated for the inner TryCatch.
6348// This exercises the ability of TryCatch.ReThrow() to restore the
6349// inner pending Message before throwing the exception again.
6350TEST(TryCatchMixedNesting) {
6351 v8::Isolate* isolate = CcTest::isolate();
6352 v8::HandleScope scope(isolate);
6353 v8::V8::Initialize();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006354 v8::TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006355 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6356 templ->Set(v8_str("TryCatchMixedNestingHelper"),
6357 v8::FunctionTemplate::New(isolate, TryCatchMixedNestingHelper));
6358 LocalContext context(0, templ);
6359 CompileRunWithOrigin("TryCatchMixedNestingHelper();\n", "outer", 1, 1);
6360 TryCatchMixedNestingCheck(&try_catch);
6361}
6362
6363
6364void TryCatchNativeHelper(const v8::FunctionCallbackInfo<v8::Value>& args) {
6365 ApiTestFuzzer::Fuzz();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006366 v8::TryCatch try_catch(args.GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006367 args.GetIsolate()->ThrowException(v8_str("boom"));
6368 CHECK(try_catch.HasCaught());
6369}
6370
6371
6372TEST(TryCatchNative) {
6373 v8::Isolate* isolate = CcTest::isolate();
6374 v8::HandleScope scope(isolate);
6375 v8::V8::Initialize();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006376 v8::TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006377 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6378 templ->Set(v8_str("TryCatchNativeHelper"),
6379 v8::FunctionTemplate::New(isolate, TryCatchNativeHelper));
6380 LocalContext context(0, templ);
6381 CompileRun("TryCatchNativeHelper();");
6382 CHECK(!try_catch.HasCaught());
6383}
6384
6385
6386void TryCatchNativeResetHelper(
6387 const v8::FunctionCallbackInfo<v8::Value>& args) {
6388 ApiTestFuzzer::Fuzz();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006389 v8::TryCatch try_catch(args.GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006390 args.GetIsolate()->ThrowException(v8_str("boom"));
6391 CHECK(try_catch.HasCaught());
6392 try_catch.Reset();
6393 CHECK(!try_catch.HasCaught());
6394}
6395
6396
6397TEST(TryCatchNativeReset) {
6398 v8::Isolate* isolate = CcTest::isolate();
6399 v8::HandleScope scope(isolate);
6400 v8::V8::Initialize();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006401 v8::TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006402 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6403 templ->Set(v8_str("TryCatchNativeResetHelper"),
6404 v8::FunctionTemplate::New(isolate, TryCatchNativeResetHelper));
6405 LocalContext context(0, templ);
6406 CompileRun("TryCatchNativeResetHelper();");
6407 CHECK(!try_catch.HasCaught());
6408}
6409
6410
6411THREADED_TEST(Equality) {
6412 LocalContext context;
6413 v8::Isolate* isolate = context->GetIsolate();
6414 v8::HandleScope scope(context->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00006415 // Check that equality works at all before relying on CHECK_EQ
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006416 CHECK(v8_str("a")->Equals(context.local(), v8_str("a")).FromJust());
6417 CHECK(!v8_str("a")->Equals(context.local(), v8_str("b")).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00006418
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006419 CHECK(v8_str("a")->Equals(context.local(), v8_str("a")).FromJust());
6420 CHECK(!v8_str("a")->Equals(context.local(), v8_str("b")).FromJust());
6421 CHECK(v8_num(1)->Equals(context.local(), v8_num(1)).FromJust());
6422 CHECK(v8_num(1.00)->Equals(context.local(), v8_num(1)).FromJust());
6423 CHECK(!v8_num(1)->Equals(context.local(), v8_num(2)).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00006424
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006425 // Assume String is not internalized.
Steve Blocka7e24c12009-10-30 11:49:00 +00006426 CHECK(v8_str("a")->StrictEquals(v8_str("a")));
6427 CHECK(!v8_str("a")->StrictEquals(v8_str("b")));
6428 CHECK(!v8_str("5")->StrictEquals(v8_num(5)));
6429 CHECK(v8_num(1)->StrictEquals(v8_num(1)));
6430 CHECK(!v8_num(1)->StrictEquals(v8_num(2)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006431 CHECK(v8_num(0.0)->StrictEquals(v8_num(-0.0)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006432 Local<Value> not_a_number = v8_num(std::numeric_limits<double>::quiet_NaN());
Steve Blocka7e24c12009-10-30 11:49:00 +00006433 CHECK(!not_a_number->StrictEquals(not_a_number));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006434 CHECK(v8::False(isolate)->StrictEquals(v8::False(isolate)));
6435 CHECK(!v8::False(isolate)->StrictEquals(v8::Undefined(isolate)));
Steve Blocka7e24c12009-10-30 11:49:00 +00006436
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006437 v8::Local<v8::Object> obj = v8::Object::New(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006438 v8::Persistent<v8::Object> alias(isolate, obj);
6439 CHECK(v8::Local<v8::Object>::New(isolate, alias)->StrictEquals(obj));
6440 alias.Reset();
6441
6442 CHECK(v8_str("a")->SameValue(v8_str("a")));
6443 CHECK(!v8_str("a")->SameValue(v8_str("b")));
6444 CHECK(!v8_str("5")->SameValue(v8_num(5)));
6445 CHECK(v8_num(1)->SameValue(v8_num(1)));
6446 CHECK(!v8_num(1)->SameValue(v8_num(2)));
6447 CHECK(!v8_num(0.0)->SameValue(v8_num(-0.0)));
6448 CHECK(not_a_number->SameValue(not_a_number));
6449 CHECK(v8::False(isolate)->SameValue(v8::False(isolate)));
6450 CHECK(!v8::False(isolate)->SameValue(v8::Undefined(isolate)));
Steve Blocka7e24c12009-10-30 11:49:00 +00006451}
6452
Ben Murdochc5610432016-08-08 18:44:38 +01006453THREADED_TEST(TypeOf) {
6454 LocalContext context;
6455 v8::Isolate* isolate = context->GetIsolate();
6456 v8::HandleScope scope(context->GetIsolate());
6457
6458 Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
6459 Local<v8::Function> fun = t1->GetFunction(context.local()).ToLocalChecked();
6460
6461 CHECK(v8::Undefined(isolate)
6462 ->TypeOf(isolate)
6463 ->Equals(context.local(), v8_str("undefined"))
6464 .FromJust());
6465 CHECK(v8::Null(isolate)
6466 ->TypeOf(isolate)
6467 ->Equals(context.local(), v8_str("object"))
6468 .FromJust());
6469 CHECK(v8_str("str")
6470 ->TypeOf(isolate)
6471 ->Equals(context.local(), v8_str("string"))
6472 .FromJust());
6473 CHECK(v8_num(0.0)
6474 ->TypeOf(isolate)
6475 ->Equals(context.local(), v8_str("number"))
6476 .FromJust());
6477 CHECK(v8_num(1)
6478 ->TypeOf(isolate)
6479 ->Equals(context.local(), v8_str("number"))
6480 .FromJust());
6481 CHECK(v8::Object::New(isolate)
6482 ->TypeOf(isolate)
6483 ->Equals(context.local(), v8_str("object"))
6484 .FromJust());
6485 CHECK(v8::Boolean::New(isolate, true)
6486 ->TypeOf(isolate)
6487 ->Equals(context.local(), v8_str("boolean"))
6488 .FromJust());
6489 CHECK(fun->TypeOf(isolate)
6490 ->Equals(context.local(), v8_str("function"))
6491 .FromJust());
6492}
Steve Blocka7e24c12009-10-30 11:49:00 +00006493
6494THREADED_TEST(MultiRun) {
Steve Blocka7e24c12009-10-30 11:49:00 +00006495 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006496 v8::HandleScope scope(context->GetIsolate());
6497 Local<Script> script = v8_compile("x");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006498 for (int i = 0; i < 10; i++) {
6499 script->Run(context.local()).IsEmpty();
6500 }
Steve Blocka7e24c12009-10-30 11:49:00 +00006501}
6502
6503
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006504static void GetXValue(Local<Name> name,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006505 const v8::PropertyCallbackInfo<v8::Value>& info) {
Steve Blocka7e24c12009-10-30 11:49:00 +00006506 ApiTestFuzzer::Fuzz();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006507 CHECK(info.Data()
6508 ->Equals(CcTest::isolate()->GetCurrentContext(), v8_str("donut"))
6509 .FromJust());
6510 CHECK(name->Equals(CcTest::isolate()->GetCurrentContext(), v8_str("x"))
6511 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006512 info.GetReturnValue().Set(name);
Steve Blocka7e24c12009-10-30 11:49:00 +00006513}
6514
6515
6516THREADED_TEST(SimplePropertyRead) {
Steve Blocka7e24c12009-10-30 11:49:00 +00006517 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006518 v8::Isolate* isolate = context->GetIsolate();
6519 v8::HandleScope scope(isolate);
6520 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6521 templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006522 CHECK(context->Global()
6523 ->Set(context.local(), v8_str("obj"),
6524 templ->NewInstance(context.local()).ToLocalChecked())
6525 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006526 Local<Script> script = v8_compile("obj.x");
Steve Blocka7e24c12009-10-30 11:49:00 +00006527 for (int i = 0; i < 10; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006528 Local<Value> result = script->Run(context.local()).ToLocalChecked();
6529 CHECK(result->Equals(context.local(), v8_str("x")).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00006530 }
6531}
6532
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006533
Andrei Popescu31002712010-02-23 13:46:05 +00006534THREADED_TEST(DefinePropertyOnAPIAccessor) {
Andrei Popescu31002712010-02-23 13:46:05 +00006535 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006536 v8::Isolate* isolate = context->GetIsolate();
6537 v8::HandleScope scope(isolate);
6538 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6539 templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006540 CHECK(context->Global()
6541 ->Set(context.local(), v8_str("obj"),
6542 templ->NewInstance(context.local()).ToLocalChecked())
6543 .FromJust());
Andrei Popescu31002712010-02-23 13:46:05 +00006544
6545 // Uses getOwnPropertyDescriptor to check the configurable status
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006546 Local<Script> script_desc = v8_compile(
6547 "var prop = Object.getOwnPropertyDescriptor( "
6548 "obj, 'x');"
6549 "prop.configurable;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006550 Local<Value> result = script_desc->Run(context.local()).ToLocalChecked();
6551 CHECK_EQ(result->BooleanValue(context.local()).FromJust(), true);
Andrei Popescu31002712010-02-23 13:46:05 +00006552
6553 // Redefine get - but still configurable
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006554 Local<Script> script_define = v8_compile(
6555 "var desc = { get: function(){return 42; },"
6556 " configurable: true };"
6557 "Object.defineProperty(obj, 'x', desc);"
6558 "obj.x");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006559 result = script_define->Run(context.local()).ToLocalChecked();
6560 CHECK(result->Equals(context.local(), v8_num(42)).FromJust());
Andrei Popescu31002712010-02-23 13:46:05 +00006561
6562 // Check that the accessor is still configurable
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006563 result = script_desc->Run(context.local()).ToLocalChecked();
6564 CHECK_EQ(result->BooleanValue(context.local()).FromJust(), true);
Andrei Popescu31002712010-02-23 13:46:05 +00006565
6566 // Redefine to a non-configurable
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006567 script_define = v8_compile(
6568 "var desc = { get: function(){return 43; },"
6569 " configurable: false };"
6570 "Object.defineProperty(obj, 'x', desc);"
6571 "obj.x");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006572 result = script_define->Run(context.local()).ToLocalChecked();
6573 CHECK(result->Equals(context.local(), v8_num(43)).FromJust());
6574 result = script_desc->Run(context.local()).ToLocalChecked();
6575 CHECK_EQ(result->BooleanValue(context.local()).FromJust(), false);
Andrei Popescu31002712010-02-23 13:46:05 +00006576
6577 // Make sure that it is not possible to redefine again
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006578 v8::TryCatch try_catch(isolate);
6579 CHECK(script_define->Run(context.local()).IsEmpty());
Andrei Popescu31002712010-02-23 13:46:05 +00006580 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006581 String::Utf8Value exception_value(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006582 CHECK_EQ(0,
6583 strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
Andrei Popescu31002712010-02-23 13:46:05 +00006584}
6585
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006586
Andrei Popescu31002712010-02-23 13:46:05 +00006587THREADED_TEST(DefinePropertyOnDefineGetterSetter) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006588 v8::Isolate* isolate = CcTest::isolate();
6589 v8::HandleScope scope(isolate);
6590 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Andrei Popescu31002712010-02-23 13:46:05 +00006591 templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
6592 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006593 CHECK(context->Global()
6594 ->Set(context.local(), v8_str("obj"),
6595 templ->NewInstance(context.local()).ToLocalChecked())
6596 .FromJust());
Andrei Popescu31002712010-02-23 13:46:05 +00006597
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006598 Local<Script> script_desc = v8_compile(
6599 "var prop ="
6600 "Object.getOwnPropertyDescriptor( "
6601 "obj, 'x');"
6602 "prop.configurable;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006603 Local<Value> result = script_desc->Run(context.local()).ToLocalChecked();
6604 CHECK_EQ(result->BooleanValue(context.local()).FromJust(), true);
Andrei Popescu31002712010-02-23 13:46:05 +00006605
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006606 Local<Script> script_define = v8_compile(
6607 "var desc = {get: function(){return 42; },"
6608 " configurable: true };"
6609 "Object.defineProperty(obj, 'x', desc);"
6610 "obj.x");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006611 result = script_define->Run(context.local()).ToLocalChecked();
6612 CHECK(result->Equals(context.local(), v8_num(42)).FromJust());
Andrei Popescu31002712010-02-23 13:46:05 +00006613
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006614 result = script_desc->Run(context.local()).ToLocalChecked();
6615 CHECK_EQ(result->BooleanValue(context.local()).FromJust(), true);
Andrei Popescu31002712010-02-23 13:46:05 +00006616
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006617 script_define = v8_compile(
6618 "var desc = {get: function(){return 43; },"
6619 " configurable: false };"
6620 "Object.defineProperty(obj, 'x', desc);"
6621 "obj.x");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006622 result = script_define->Run(context.local()).ToLocalChecked();
6623 CHECK(result->Equals(context.local(), v8_num(43)).FromJust());
Andrei Popescu31002712010-02-23 13:46:05 +00006624
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006625 result = script_desc->Run(context.local()).ToLocalChecked();
6626 CHECK_EQ(result->BooleanValue(context.local()).FromJust(), false);
Andrei Popescu31002712010-02-23 13:46:05 +00006627
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006628 v8::TryCatch try_catch(isolate);
6629 CHECK(script_define->Run(context.local()).IsEmpty());
Andrei Popescu31002712010-02-23 13:46:05 +00006630 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006631 String::Utf8Value exception_value(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006632 CHECK_EQ(0,
6633 strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
Andrei Popescu31002712010-02-23 13:46:05 +00006634}
6635
6636
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006637static v8::Local<v8::Object> GetGlobalProperty(LocalContext* context,
6638 char const* name) {
6639 return v8::Local<v8::Object>::Cast(
6640 (*context)
6641 ->Global()
6642 ->Get(CcTest::isolate()->GetCurrentContext(), v8_str(name))
6643 .ToLocalChecked());
Leon Clarkef7060e22010-06-03 12:02:55 +01006644}
Andrei Popescu31002712010-02-23 13:46:05 +00006645
6646
Leon Clarkef7060e22010-06-03 12:02:55 +01006647THREADED_TEST(DefineAPIAccessorOnObject) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006648 v8::Isolate* isolate = CcTest::isolate();
6649 v8::HandleScope scope(isolate);
6650 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Leon Clarkef7060e22010-06-03 12:02:55 +01006651 LocalContext context;
6652
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006653 CHECK(context->Global()
6654 ->Set(context.local(), v8_str("obj1"),
6655 templ->NewInstance(context.local()).ToLocalChecked())
6656 .FromJust());
Leon Clarkef7060e22010-06-03 12:02:55 +01006657 CompileRun("var obj2 = {};");
6658
6659 CHECK(CompileRun("obj1.x")->IsUndefined());
6660 CHECK(CompileRun("obj2.x")->IsUndefined());
6661
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006662 CHECK(GetGlobalProperty(&context, "obj1")
6663 ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
6664 v8_str("donut"))
6665 .FromJust());
Leon Clarkef7060e22010-06-03 12:02:55 +01006666
6667 ExpectString("obj1.x", "x");
6668 CHECK(CompileRun("obj2.x")->IsUndefined());
6669
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006670 CHECK(GetGlobalProperty(&context, "obj2")
6671 ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
6672 v8_str("donut"))
6673 .FromJust());
Leon Clarkef7060e22010-06-03 12:02:55 +01006674
6675 ExpectString("obj1.x", "x");
6676 ExpectString("obj2.x", "x");
6677
6678 ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
6679 ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
6680
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006681 CompileRun(
6682 "Object.defineProperty(obj1, 'x',"
6683 "{ get: function() { return 'y'; }, configurable: true })");
Leon Clarkef7060e22010-06-03 12:02:55 +01006684
6685 ExpectString("obj1.x", "y");
6686 ExpectString("obj2.x", "x");
6687
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006688 CompileRun(
6689 "Object.defineProperty(obj2, 'x',"
6690 "{ get: function() { return 'y'; }, configurable: true })");
Leon Clarkef7060e22010-06-03 12:02:55 +01006691
6692 ExpectString("obj1.x", "y");
6693 ExpectString("obj2.x", "y");
6694
6695 ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
6696 ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
6697
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006698 CHECK(GetGlobalProperty(&context, "obj1")
6699 ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
6700 v8_str("donut"))
6701 .FromJust());
6702 CHECK(GetGlobalProperty(&context, "obj2")
6703 ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
6704 v8_str("donut"))
6705 .FromJust());
Leon Clarkef7060e22010-06-03 12:02:55 +01006706
6707 ExpectString("obj1.x", "x");
6708 ExpectString("obj2.x", "x");
6709
6710 ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
6711 ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
6712
6713 // Define getters/setters, but now make them not configurable.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006714 CompileRun(
6715 "Object.defineProperty(obj1, 'x',"
6716 "{ get: function() { return 'z'; }, configurable: false })");
6717 CompileRun(
6718 "Object.defineProperty(obj2, 'x',"
6719 "{ get: function() { return 'z'; }, configurable: false })");
Leon Clarkef7060e22010-06-03 12:02:55 +01006720 ExpectTrue("!Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
6721 ExpectTrue("!Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
6722
6723 ExpectString("obj1.x", "z");
6724 ExpectString("obj2.x", "z");
6725
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006726 CHECK(GetGlobalProperty(&context, "obj1")
6727 ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
6728 v8_str("donut"))
6729 .IsNothing());
6730 CHECK(GetGlobalProperty(&context, "obj2")
6731 ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
6732 v8_str("donut"))
6733 .IsNothing());
Leon Clarkef7060e22010-06-03 12:02:55 +01006734
6735 ExpectString("obj1.x", "z");
6736 ExpectString("obj2.x", "z");
6737}
6738
6739
6740THREADED_TEST(DontDeleteAPIAccessorsCannotBeOverriden) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006741 v8::Isolate* isolate = CcTest::isolate();
6742 v8::HandleScope scope(isolate);
6743 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Leon Clarkef7060e22010-06-03 12:02:55 +01006744 LocalContext context;
6745
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006746 CHECK(context->Global()
6747 ->Set(context.local(), v8_str("obj1"),
6748 templ->NewInstance(context.local()).ToLocalChecked())
6749 .FromJust());
Leon Clarkef7060e22010-06-03 12:02:55 +01006750 CompileRun("var obj2 = {};");
6751
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006752 CHECK(GetGlobalProperty(&context, "obj1")
6753 ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
6754 v8_str("donut"), v8::DEFAULT, v8::DontDelete)
6755 .FromJust());
6756 CHECK(GetGlobalProperty(&context, "obj2")
6757 ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
6758 v8_str("donut"), v8::DEFAULT, v8::DontDelete)
6759 .FromJust());
Leon Clarkef7060e22010-06-03 12:02:55 +01006760
6761 ExpectString("obj1.x", "x");
6762 ExpectString("obj2.x", "x");
6763
6764 ExpectTrue("!Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
6765 ExpectTrue("!Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
6766
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006767 CHECK(GetGlobalProperty(&context, "obj1")
6768 ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
6769 v8_str("donut"))
6770 .IsNothing());
6771 CHECK(GetGlobalProperty(&context, "obj2")
6772 ->SetAccessor(context.local(), v8_str("x"), GetXValue, NULL,
6773 v8_str("donut"))
6774 .IsNothing());
Leon Clarkef7060e22010-06-03 12:02:55 +01006775
6776 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006777 v8::TryCatch try_catch(isolate);
6778 CompileRun(
6779 "Object.defineProperty(obj1, 'x',"
Leon Clarkef7060e22010-06-03 12:02:55 +01006780 "{get: function() { return 'func'; }})");
6781 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006782 String::Utf8Value exception_value(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006783 CHECK_EQ(
6784 0, strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
Leon Clarkef7060e22010-06-03 12:02:55 +01006785 }
6786 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006787 v8::TryCatch try_catch(isolate);
6788 CompileRun(
6789 "Object.defineProperty(obj2, 'x',"
Leon Clarkef7060e22010-06-03 12:02:55 +01006790 "{get: function() { return 'func'; }})");
6791 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006792 String::Utf8Value exception_value(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006793 CHECK_EQ(
6794 0, strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
Leon Clarkef7060e22010-06-03 12:02:55 +01006795 }
6796}
6797
6798
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006799static void Get239Value(Local<Name> name,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006800 const v8::PropertyCallbackInfo<v8::Value>& info) {
Leon Clarkef7060e22010-06-03 12:02:55 +01006801 ApiTestFuzzer::Fuzz();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006802 CHECK(info.Data()
6803 ->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("donut"))
6804 .FromJust());
6805 CHECK(name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("239"))
6806 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006807 info.GetReturnValue().Set(name);
Leon Clarkef7060e22010-06-03 12:02:55 +01006808}
6809
6810
6811THREADED_TEST(ElementAPIAccessor) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006812 v8::Isolate* isolate = CcTest::isolate();
6813 v8::HandleScope scope(isolate);
6814 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Leon Clarkef7060e22010-06-03 12:02:55 +01006815 LocalContext context;
6816
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006817 CHECK(context->Global()
6818 ->Set(context.local(), v8_str("obj1"),
6819 templ->NewInstance(context.local()).ToLocalChecked())
6820 .FromJust());
Leon Clarkef7060e22010-06-03 12:02:55 +01006821 CompileRun("var obj2 = {};");
6822
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006823 CHECK(GetGlobalProperty(&context, "obj1")
6824 ->SetAccessor(context.local(), v8_str("239"), Get239Value, NULL,
6825 v8_str("donut"))
6826 .FromJust());
6827 CHECK(GetGlobalProperty(&context, "obj2")
6828 ->SetAccessor(context.local(), v8_str("239"), Get239Value, NULL,
6829 v8_str("donut"))
6830 .FromJust());
Leon Clarkef7060e22010-06-03 12:02:55 +01006831
6832 ExpectString("obj1[239]", "239");
6833 ExpectString("obj2[239]", "239");
6834 ExpectString("obj1['239']", "239");
6835 ExpectString("obj2['239']", "239");
6836}
6837
Steve Blocka7e24c12009-10-30 11:49:00 +00006838
6839v8::Persistent<Value> xValue;
6840
6841
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006842static void SetXValue(Local<Name> name, Local<Value> value,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006843 const v8::PropertyCallbackInfo<void>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006844 Local<Context> context = info.GetIsolate()->GetCurrentContext();
6845 CHECK(value->Equals(context, v8_num(4)).FromJust());
6846 CHECK(info.Data()->Equals(context, v8_str("donut")).FromJust());
6847 CHECK(name->Equals(context, v8_str("x")).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00006848 CHECK(xValue.IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006849 xValue.Reset(info.GetIsolate(), value);
Steve Blocka7e24c12009-10-30 11:49:00 +00006850}
6851
6852
6853THREADED_TEST(SimplePropertyWrite) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006854 v8::Isolate* isolate = CcTest::isolate();
6855 v8::HandleScope scope(isolate);
6856 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00006857 templ->SetAccessor(v8_str("x"), GetXValue, SetXValue, v8_str("donut"));
6858 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006859 CHECK(context->Global()
6860 ->Set(context.local(), v8_str("obj"),
6861 templ->NewInstance(context.local()).ToLocalChecked())
6862 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006863 Local<Script> script = v8_compile("obj.x = 4");
Steve Blocka7e24c12009-10-30 11:49:00 +00006864 for (int i = 0; i < 10; i++) {
6865 CHECK(xValue.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006866 script->Run(context.local()).ToLocalChecked();
6867 CHECK(v8_num(4)
6868 ->Equals(context.local(),
6869 Local<Value>::New(CcTest::isolate(), xValue))
6870 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006871 xValue.Reset();
Steve Blocka7e24c12009-10-30 11:49:00 +00006872 }
6873}
6874
6875
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006876THREADED_TEST(SetterOnly) {
6877 v8::Isolate* isolate = CcTest::isolate();
6878 v8::HandleScope scope(isolate);
6879 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6880 templ->SetAccessor(v8_str("x"), NULL, SetXValue, v8_str("donut"));
6881 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006882 CHECK(context->Global()
6883 ->Set(context.local(), v8_str("obj"),
6884 templ->NewInstance(context.local()).ToLocalChecked())
6885 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006886 Local<Script> script = v8_compile("obj.x = 4; obj.x");
6887 for (int i = 0; i < 10; i++) {
6888 CHECK(xValue.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006889 script->Run(context.local()).ToLocalChecked();
6890 CHECK(v8_num(4)
6891 ->Equals(context.local(),
6892 Local<Value>::New(CcTest::isolate(), xValue))
6893 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006894 xValue.Reset();
6895 }
6896}
6897
6898
6899THREADED_TEST(NoAccessors) {
6900 v8::Isolate* isolate = CcTest::isolate();
6901 v8::HandleScope scope(isolate);
6902 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006903 templ->SetAccessor(v8_str("x"), static_cast<v8::AccessorGetterCallback>(NULL),
6904 NULL, v8_str("donut"));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006905 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006906 CHECK(context->Global()
6907 ->Set(context.local(), v8_str("obj"),
6908 templ->NewInstance(context.local()).ToLocalChecked())
6909 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006910 Local<Script> script = v8_compile("obj.x = 4; obj.x");
6911 for (int i = 0; i < 10; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006912 script->Run(context.local()).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006913 }
6914}
6915
6916
Steve Blocka7e24c12009-10-30 11:49:00 +00006917THREADED_TEST(MultiContexts) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006918 v8::Isolate* isolate = CcTest::isolate();
6919 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006920 v8::Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6921 templ->Set(v8_str("dummy"),
6922 v8::FunctionTemplate::New(isolate, DummyCallHandler));
Steve Blocka7e24c12009-10-30 11:49:00 +00006923
6924 Local<String> password = v8_str("Password");
6925
6926 // Create an environment
6927 LocalContext context0(0, templ);
6928 context0->SetSecurityToken(password);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006929 v8::Local<v8::Object> global0 = context0->Global();
6930 CHECK(global0->Set(context0.local(), v8_str("custom"), v8_num(1234))
6931 .FromJust());
6932 CHECK_EQ(1234, global0->Get(context0.local(), v8_str("custom"))
6933 .ToLocalChecked()
6934 ->Int32Value(context0.local())
6935 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00006936
6937 // Create an independent environment
6938 LocalContext context1(0, templ);
6939 context1->SetSecurityToken(password);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006940 v8::Local<v8::Object> global1 = context1->Global();
6941 CHECK(global1->Set(context1.local(), v8_str("custom"), v8_num(1234))
6942 .FromJust());
6943 CHECK(!global0->Equals(context1.local(), global1).FromJust());
6944 CHECK_EQ(1234, global0->Get(context1.local(), v8_str("custom"))
6945 .ToLocalChecked()
6946 ->Int32Value(context0.local())
6947 .FromJust());
6948 CHECK_EQ(1234, global1->Get(context1.local(), v8_str("custom"))
6949 .ToLocalChecked()
6950 ->Int32Value(context1.local())
6951 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00006952
6953 // Now create a new context with the old global
6954 LocalContext context2(0, templ, global1);
6955 context2->SetSecurityToken(password);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006956 v8::Local<v8::Object> global2 = context2->Global();
6957 CHECK(global1->Equals(context2.local(), global2).FromJust());
6958 CHECK_EQ(0, global1->Get(context2.local(), v8_str("custom"))
6959 .ToLocalChecked()
6960 ->Int32Value(context1.local())
6961 .FromJust());
6962 CHECK_EQ(0, global2->Get(context2.local(), v8_str("custom"))
6963 .ToLocalChecked()
6964 ->Int32Value(context2.local())
6965 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00006966}
6967
6968
6969THREADED_TEST(FunctionPrototypeAcrossContexts) {
6970 // Make sure that functions created by cloning boilerplates cannot
6971 // communicate through their __proto__ field.
6972
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006973 v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00006974
6975 LocalContext env0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006976 v8::Local<v8::Object> global0 = env0->Global();
6977 v8::Local<v8::Object> object0 = global0->Get(env0.local(), v8_str("Object"))
6978 .ToLocalChecked()
6979 .As<v8::Object>();
6980 v8::Local<v8::Object> tostring0 =
6981 object0->Get(env0.local(), v8_str("toString"))
6982 .ToLocalChecked()
6983 .As<v8::Object>();
6984 v8::Local<v8::Object> proto0 =
6985 tostring0->Get(env0.local(), v8_str("__proto__"))
6986 .ToLocalChecked()
6987 .As<v8::Object>();
6988 CHECK(proto0->Set(env0.local(), v8_str("custom"), v8_num(1234)).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00006989
6990 LocalContext env1;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006991 v8::Local<v8::Object> global1 = env1->Global();
6992 v8::Local<v8::Object> object1 = global1->Get(env1.local(), v8_str("Object"))
6993 .ToLocalChecked()
6994 .As<v8::Object>();
6995 v8::Local<v8::Object> tostring1 =
6996 object1->Get(env1.local(), v8_str("toString"))
6997 .ToLocalChecked()
6998 .As<v8::Object>();
6999 v8::Local<v8::Object> proto1 =
7000 tostring1->Get(env1.local(), v8_str("__proto__"))
7001 .ToLocalChecked()
7002 .As<v8::Object>();
7003 CHECK(!proto1->Has(env1.local(), v8_str("custom")).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00007004}
7005
7006
7007THREADED_TEST(Regress892105) {
7008 // Make sure that object and array literals created by cloning
7009 // boilerplates cannot communicate through their __proto__
7010 // field. This is rather difficult to check, but we try to add stuff
7011 // to Object.prototype and Array.prototype and create a new
7012 // environment. This should succeed.
7013
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007014 v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00007015
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007016 Local<String> source = v8_str(
7017 "Object.prototype.obj = 1234;"
7018 "Array.prototype.arr = 4567;"
7019 "8901");
Steve Blocka7e24c12009-10-30 11:49:00 +00007020
7021 LocalContext env0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007022 Local<Script> script0 = v8_compile(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007023 CHECK_EQ(8901.0, script0->Run(env0.local())
7024 .ToLocalChecked()
7025 ->NumberValue(env0.local())
7026 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00007027
7028 LocalContext env1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007029 Local<Script> script1 = v8_compile(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007030 CHECK_EQ(8901.0, script1->Run(env1.local())
7031 .ToLocalChecked()
7032 ->NumberValue(env1.local())
7033 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00007034}
7035
7036
Steve Blocka7e24c12009-10-30 11:49:00 +00007037THREADED_TEST(UndetectableObject) {
Steve Blocka7e24c12009-10-30 11:49:00 +00007038 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007039 v8::HandleScope scope(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00007040
7041 Local<v8::FunctionTemplate> desc =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007042 v8::FunctionTemplate::New(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00007043 desc->InstanceTemplate()->MarkAsUndetectable(); // undetectable
7044
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007045 Local<v8::Object> obj = desc->GetFunction(env.local())
7046 .ToLocalChecked()
7047 ->NewInstance(env.local())
7048 .ToLocalChecked();
7049 CHECK(
7050 env->Global()->Set(env.local(), v8_str("undetectable"), obj).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00007051
7052 ExpectString("undetectable.toString()", "[object Object]");
7053 ExpectString("typeof undetectable", "undefined");
7054 ExpectString("typeof(undetectable)", "undefined");
7055 ExpectBoolean("typeof undetectable == 'undefined'", true);
7056 ExpectBoolean("typeof undetectable == 'object'", false);
7057 ExpectBoolean("if (undetectable) { true; } else { false; }", false);
7058 ExpectBoolean("!undetectable", true);
7059
7060 ExpectObject("true&&undetectable", obj);
7061 ExpectBoolean("false&&undetectable", false);
7062 ExpectBoolean("true||undetectable", true);
7063 ExpectObject("false||undetectable", obj);
7064
7065 ExpectObject("undetectable&&true", obj);
7066 ExpectObject("undetectable&&false", obj);
7067 ExpectBoolean("undetectable||true", true);
7068 ExpectBoolean("undetectable||false", false);
7069
7070 ExpectBoolean("undetectable==null", true);
7071 ExpectBoolean("null==undetectable", true);
7072 ExpectBoolean("undetectable==undefined", true);
7073 ExpectBoolean("undefined==undetectable", true);
7074 ExpectBoolean("undetectable==undetectable", true);
7075
7076
7077 ExpectBoolean("undetectable===null", false);
7078 ExpectBoolean("null===undetectable", false);
7079 ExpectBoolean("undetectable===undefined", false);
7080 ExpectBoolean("undefined===undetectable", false);
7081 ExpectBoolean("undetectable===undetectable", true);
7082}
7083
7084
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007085THREADED_TEST(VoidLiteral) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007086 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007087 v8::Isolate* isolate = env->GetIsolate();
7088 v8::HandleScope scope(isolate);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007089
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007090 Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007091 desc->InstanceTemplate()->MarkAsUndetectable(); // undetectable
7092
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007093 Local<v8::Object> obj = desc->GetFunction(env.local())
7094 .ToLocalChecked()
7095 ->NewInstance(env.local())
7096 .ToLocalChecked();
7097 CHECK(
7098 env->Global()->Set(env.local(), v8_str("undetectable"), obj).FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007099
7100 ExpectBoolean("undefined == void 0", true);
7101 ExpectBoolean("undetectable == void 0", true);
7102 ExpectBoolean("null == void 0", true);
7103 ExpectBoolean("undefined === void 0", true);
7104 ExpectBoolean("undetectable === void 0", false);
7105 ExpectBoolean("null === void 0", false);
7106
7107 ExpectBoolean("void 0 == undefined", true);
7108 ExpectBoolean("void 0 == undetectable", true);
7109 ExpectBoolean("void 0 == null", true);
7110 ExpectBoolean("void 0 === undefined", true);
7111 ExpectBoolean("void 0 === undetectable", false);
7112 ExpectBoolean("void 0 === null", false);
7113
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007114 ExpectString(
7115 "(function() {"
7116 " try {"
7117 " return x === void 0;"
7118 " } catch(e) {"
7119 " return e.toString();"
7120 " }"
7121 "})()",
7122 "ReferenceError: x is not defined");
7123 ExpectString(
7124 "(function() {"
7125 " try {"
7126 " return void 0 === x;"
7127 " } catch(e) {"
7128 " return e.toString();"
7129 " }"
7130 "})()",
7131 "ReferenceError: x is not defined");
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007132}
7133
Steve Block8defd9f2010-07-08 12:39:36 +01007134
7135THREADED_TEST(ExtensibleOnUndetectable) {
Steve Block8defd9f2010-07-08 12:39:36 +01007136 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007137 v8::Isolate* isolate = env->GetIsolate();
7138 v8::HandleScope scope(isolate);
Steve Block8defd9f2010-07-08 12:39:36 +01007139
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007140 Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
Steve Block8defd9f2010-07-08 12:39:36 +01007141 desc->InstanceTemplate()->MarkAsUndetectable(); // undetectable
7142
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007143 Local<v8::Object> obj = desc->GetFunction(env.local())
7144 .ToLocalChecked()
7145 ->NewInstance(env.local())
7146 .ToLocalChecked();
7147 CHECK(
7148 env->Global()->Set(env.local(), v8_str("undetectable"), obj).FromJust());
Steve Block8defd9f2010-07-08 12:39:36 +01007149
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007150 Local<String> source = v8_str(
7151 "undetectable.x = 42;"
7152 "undetectable.x");
Steve Block8defd9f2010-07-08 12:39:36 +01007153
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007154 Local<Script> script = v8_compile(source);
Steve Block8defd9f2010-07-08 12:39:36 +01007155
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007156 CHECK(v8::Integer::New(isolate, 42)
7157 ->Equals(env.local(), script->Run(env.local()).ToLocalChecked())
7158 .FromJust());
Steve Block8defd9f2010-07-08 12:39:36 +01007159
7160 ExpectBoolean("Object.isExtensible(undetectable)", true);
7161
7162 source = v8_str("Object.preventExtensions(undetectable);");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007163 script = v8_compile(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007164 script->Run(env.local()).ToLocalChecked();
Steve Block8defd9f2010-07-08 12:39:36 +01007165 ExpectBoolean("Object.isExtensible(undetectable)", false);
7166
7167 source = v8_str("undetectable.y = 2000;");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007168 script = v8_compile(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007169 script->Run(env.local()).ToLocalChecked();
Steve Block44f0eee2011-05-26 01:26:41 +01007170 ExpectBoolean("undetectable.y == undefined", true);
Steve Block8defd9f2010-07-08 12:39:36 +01007171}
7172
7173
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007174// The point of this test is type checking. We run it only so compilers
7175// don't complain about an unused function.
7176TEST(PersistentHandles) {
7177 LocalContext env;
7178 v8::Isolate* isolate = CcTest::isolate();
7179 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00007180 Local<String> str = v8_str("foo");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007181 v8::Persistent<String> p_str(isolate, str);
7182 p_str.Reset();
7183 Local<Script> scr = v8_compile("");
7184 v8::Persistent<Script> p_scr(isolate, scr);
7185 p_scr.Reset();
7186 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
7187 v8::Persistent<ObjectTemplate> p_templ(isolate, templ);
7188 p_templ.Reset();
Steve Blocka7e24c12009-10-30 11:49:00 +00007189}
7190
7191
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007192static void HandleLogDelegator(
7193 const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +00007194 ApiTestFuzzer::Fuzz();
Steve Blocka7e24c12009-10-30 11:49:00 +00007195}
7196
7197
7198THREADED_TEST(GlobalObjectTemplate) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007199 v8::Isolate* isolate = CcTest::isolate();
7200 v8::HandleScope handle_scope(isolate);
7201 Local<ObjectTemplate> global_template = ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00007202 global_template->Set(v8_str("JSNI_Log"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007203 v8::FunctionTemplate::New(isolate, HandleLogDelegator));
7204 v8::Local<Context> context = Context::New(isolate, 0, global_template);
Steve Blocka7e24c12009-10-30 11:49:00 +00007205 Context::Scope context_scope(context);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007206 CompileRun("JSNI_Log('LOG')");
Steve Blocka7e24c12009-10-30 11:49:00 +00007207}
7208
7209
7210static const char* kSimpleExtensionSource =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007211 "function Foo() {"
7212 " return 4;"
7213 "}";
Steve Blocka7e24c12009-10-30 11:49:00 +00007214
7215
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007216TEST(SimpleExtensions) {
7217 v8::HandleScope handle_scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00007218 v8::RegisterExtension(new Extension("simpletest", kSimpleExtensionSource));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007219 const char* extension_names[] = {"simpletest"};
Steve Blocka7e24c12009-10-30 11:49:00 +00007220 v8::ExtensionConfiguration extensions(1, extension_names);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007221 v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
Steve Blocka7e24c12009-10-30 11:49:00 +00007222 Context::Scope lock(context);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007223 v8::Local<Value> result = CompileRun("Foo()");
7224 CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 4))
7225 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007226}
7227
7228
7229static const char* kStackTraceFromExtensionSource =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007230 "function foo() {"
7231 " throw new Error();"
7232 "}"
7233 "function bar() {"
7234 " foo();"
7235 "}";
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007236
7237
7238TEST(StackTraceInExtension) {
7239 v8::HandleScope handle_scope(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007240 v8::RegisterExtension(
7241 new Extension("stacktracetest", kStackTraceFromExtensionSource));
7242 const char* extension_names[] = {"stacktracetest"};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007243 v8::ExtensionConfiguration extensions(1, extension_names);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007244 v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007245 Context::Scope lock(context);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007246 CompileRun(
7247 "function user() { bar(); }"
7248 "var error;"
7249 "try{ user(); } catch (e) { error = e; }");
7250 CHECK_EQ(-1, v8_run_int32value(v8_compile("error.stack.indexOf('foo')")));
7251 CHECK_EQ(-1, v8_run_int32value(v8_compile("error.stack.indexOf('bar')")));
7252 CHECK_NE(-1, v8_run_int32value(v8_compile("error.stack.indexOf('user')")));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007253}
7254
7255
7256TEST(NullExtensions) {
7257 v8::HandleScope handle_scope(CcTest::isolate());
7258 v8::RegisterExtension(new Extension("nulltest", NULL));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007259 const char* extension_names[] = {"nulltest"};
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007260 v8::ExtensionConfiguration extensions(1, extension_names);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007261 v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007262 Context::Scope lock(context);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007263 v8::Local<Value> result = CompileRun("1+3");
7264 CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 4))
7265 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00007266}
7267
7268
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007269static const char* kEmbeddedExtensionSource =
7270 "function Ret54321(){return 54321;}~~@@$"
7271 "$%% THIS IS A SERIES OF NON-NULL-TERMINATED STRINGS.";
7272static const int kEmbeddedExtensionSourceValidLen = 34;
7273
7274
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007275TEST(ExtensionMissingSourceLength) {
7276 v8::HandleScope handle_scope(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007277 v8::RegisterExtension(
7278 new Extension("srclentest_fail", kEmbeddedExtensionSource));
7279 const char* extension_names[] = {"srclentest_fail"};
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007280 v8::ExtensionConfiguration extensions(1, extension_names);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007281 v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
7282 CHECK(0 == *context);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007283}
7284
7285
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007286TEST(ExtensionWithSourceLength) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007287 for (int source_len = kEmbeddedExtensionSourceValidLen - 1;
7288 source_len <= kEmbeddedExtensionSourceValidLen + 1; ++source_len) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007289 v8::HandleScope handle_scope(CcTest::isolate());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007290 i::ScopedVector<char> extension_name(32);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007291 i::SNPrintF(extension_name, "ext #%d", source_len);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007292 v8::RegisterExtension(new Extension(
7293 extension_name.start(), kEmbeddedExtensionSource, 0, 0, source_len));
7294 const char* extension_names[1] = {extension_name.start()};
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007295 v8::ExtensionConfiguration extensions(1, extension_names);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007296 v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007297 if (source_len == kEmbeddedExtensionSourceValidLen) {
7298 Context::Scope lock(context);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007299 v8::Local<Value> result = CompileRun("Ret54321()");
7300 CHECK(v8::Integer::New(CcTest::isolate(), 54321)
7301 ->Equals(context, result)
7302 .FromJust());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007303 } else {
7304 // Anything but exactly the right length should fail to compile.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007305 CHECK(0 == *context);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007306 }
7307 }
7308}
7309
7310
Steve Blocka7e24c12009-10-30 11:49:00 +00007311static const char* kEvalExtensionSource1 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007312 "function UseEval1() {"
7313 " var x = 42;"
7314 " return eval('x');"
7315 "}";
Steve Blocka7e24c12009-10-30 11:49:00 +00007316
7317
7318static const char* kEvalExtensionSource2 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007319 "(function() {"
7320 " var x = 42;"
7321 " function e() {"
7322 " return eval('x');"
7323 " }"
7324 " this.UseEval2 = e;"
7325 "})()";
Steve Blocka7e24c12009-10-30 11:49:00 +00007326
7327
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007328TEST(UseEvalFromExtension) {
7329 v8::HandleScope handle_scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00007330 v8::RegisterExtension(new Extension("evaltest1", kEvalExtensionSource1));
7331 v8::RegisterExtension(new Extension("evaltest2", kEvalExtensionSource2));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007332 const char* extension_names[] = {"evaltest1", "evaltest2"};
Steve Blocka7e24c12009-10-30 11:49:00 +00007333 v8::ExtensionConfiguration extensions(2, extension_names);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007334 v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
Steve Blocka7e24c12009-10-30 11:49:00 +00007335 Context::Scope lock(context);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007336 v8::Local<Value> result = CompileRun("UseEval1()");
7337 CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 42))
7338 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007339 result = CompileRun("UseEval2()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007340 CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 42))
7341 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00007342}
7343
7344
7345static const char* kWithExtensionSource1 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007346 "function UseWith1() {"
7347 " var x = 42;"
7348 " with({x:87}) { return x; }"
7349 "}";
Steve Blocka7e24c12009-10-30 11:49:00 +00007350
7351
7352static const char* kWithExtensionSource2 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007353 "(function() {"
7354 " var x = 42;"
7355 " function e() {"
7356 " with ({x:87}) { return x; }"
7357 " }"
7358 " this.UseWith2 = e;"
7359 "})()";
Steve Blocka7e24c12009-10-30 11:49:00 +00007360
7361
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007362TEST(UseWithFromExtension) {
7363 v8::HandleScope handle_scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00007364 v8::RegisterExtension(new Extension("withtest1", kWithExtensionSource1));
7365 v8::RegisterExtension(new Extension("withtest2", kWithExtensionSource2));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007366 const char* extension_names[] = {"withtest1", "withtest2"};
Steve Blocka7e24c12009-10-30 11:49:00 +00007367 v8::ExtensionConfiguration extensions(2, extension_names);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007368 v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
Steve Blocka7e24c12009-10-30 11:49:00 +00007369 Context::Scope lock(context);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007370 v8::Local<Value> result = CompileRun("UseWith1()");
7371 CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 87))
7372 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007373 result = CompileRun("UseWith2()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007374 CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 87))
7375 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00007376}
7377
7378
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007379TEST(AutoExtensions) {
7380 v8::HandleScope handle_scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00007381 Extension* extension = new Extension("autotest", kSimpleExtensionSource);
7382 extension->set_auto_enable(true);
7383 v8::RegisterExtension(extension);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007384 v8::Local<Context> context = Context::New(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00007385 Context::Scope lock(context);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007386 v8::Local<Value> result = CompileRun("Foo()");
7387 CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 4))
7388 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00007389}
7390
7391
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007392static const char* kSyntaxErrorInExtensionSource = "[";
Steve Blockd0582a62009-12-15 09:54:21 +00007393
7394
7395// Test that a syntax error in an extension does not cause a fatal
7396// error but results in an empty context.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007397TEST(SyntaxErrorExtensions) {
7398 v8::HandleScope handle_scope(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007399 v8::RegisterExtension(
7400 new Extension("syntaxerror", kSyntaxErrorInExtensionSource));
7401 const char* extension_names[] = {"syntaxerror"};
Steve Blockd0582a62009-12-15 09:54:21 +00007402 v8::ExtensionConfiguration extensions(1, extension_names);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007403 v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
Steve Blockd0582a62009-12-15 09:54:21 +00007404 CHECK(context.IsEmpty());
7405}
7406
7407
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007408static const char* kExceptionInExtensionSource = "throw 42";
Steve Blockd0582a62009-12-15 09:54:21 +00007409
7410
7411// Test that an exception when installing an extension does not cause
7412// a fatal error but results in an empty context.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007413TEST(ExceptionExtensions) {
7414 v8::HandleScope handle_scope(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007415 v8::RegisterExtension(
7416 new Extension("exception", kExceptionInExtensionSource));
7417 const char* extension_names[] = {"exception"};
Steve Blockd0582a62009-12-15 09:54:21 +00007418 v8::ExtensionConfiguration extensions(1, extension_names);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007419 v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
Steve Blockd0582a62009-12-15 09:54:21 +00007420 CHECK(context.IsEmpty());
7421}
7422
7423
Iain Merrick9ac36c92010-09-13 15:29:50 +01007424static const char* kNativeCallInExtensionSource =
7425 "function call_runtime_last_index_of(x) {"
7426 " return %StringLastIndexOf(x, 'bob', 10);"
7427 "}";
7428
7429
7430static const char* kNativeCallTest =
7431 "call_runtime_last_index_of('bobbobboellebobboellebobbob');";
7432
7433// Test that a native runtime calls are supported in extensions.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007434TEST(NativeCallInExtensions) {
7435 v8::HandleScope handle_scope(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007436 v8::RegisterExtension(
7437 new Extension("nativecall", kNativeCallInExtensionSource));
7438 const char* extension_names[] = {"nativecall"};
Iain Merrick9ac36c92010-09-13 15:29:50 +01007439 v8::ExtensionConfiguration extensions(1, extension_names);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007440 v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
Iain Merrick9ac36c92010-09-13 15:29:50 +01007441 Context::Scope lock(context);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007442 v8::Local<Value> result = CompileRun(kNativeCallTest);
7443 CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 3))
7444 .FromJust());
Iain Merrick9ac36c92010-09-13 15:29:50 +01007445}
7446
7447
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007448class NativeFunctionExtension : public Extension {
7449 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007450 NativeFunctionExtension(const char* name, const char* source,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007451 v8::FunctionCallback fun = &Echo)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007452 : Extension(name, source), function_(fun) {}
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007453
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007454 virtual v8::Local<v8::FunctionTemplate> GetNativeFunctionTemplate(
7455 v8::Isolate* isolate, v8::Local<v8::String> name) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007456 return v8::FunctionTemplate::New(isolate, function_);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007457 }
7458
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007459 static void Echo(const v8::FunctionCallbackInfo<v8::Value>& args) {
7460 if (args.Length() >= 1) args.GetReturnValue().Set(args[0]);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007461 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007462
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007463 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007464 v8::FunctionCallback function_;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007465};
7466
7467
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007468TEST(NativeFunctionDeclaration) {
7469 v8::HandleScope handle_scope(CcTest::isolate());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007470 const char* name = "nativedecl";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007471 v8::RegisterExtension(
7472 new NativeFunctionExtension(name, "native function foo();"));
7473 const char* extension_names[] = {name};
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007474 v8::ExtensionConfiguration extensions(1, extension_names);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007475 v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007476 Context::Scope lock(context);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007477 v8::Local<Value> result = CompileRun("foo(42);");
7478 CHECK(result->Equals(context, v8::Integer::New(CcTest::isolate(), 42))
7479 .FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007480}
7481
7482
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007483TEST(NativeFunctionDeclarationError) {
7484 v8::HandleScope handle_scope(CcTest::isolate());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007485 const char* name = "nativedeclerr";
7486 // Syntax error in extension code.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007487 v8::RegisterExtension(
7488 new NativeFunctionExtension(name, "native\nfunction foo();"));
7489 const char* extension_names[] = {name};
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007490 v8::ExtensionConfiguration extensions(1, extension_names);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007491 v8::Local<Context> context = Context::New(CcTest::isolate(), &extensions);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007492 CHECK(context.IsEmpty());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007493}
7494
Ben Murdoch3ef787d2012-04-12 10:51:47 +01007495
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007496TEST(NativeFunctionDeclarationErrorEscape) {
7497 v8::HandleScope handle_scope(CcTest::isolate());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007498 const char* name = "nativedeclerresc";
7499 // Syntax error in extension code - escape code in "native" means that
7500 // it's not treated as a keyword.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007501 v8::RegisterExtension(
7502 new NativeFunctionExtension(name, "nativ\\u0065 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 Murdoch3ef787d2012-04-12 10:51:47 +01007506 CHECK(context.IsEmpty());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00007507}
7508
7509
Steve Blocka7e24c12009-10-30 11:49:00 +00007510static void CheckDependencies(const char* name, const char* expected) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007511 v8::HandleScope handle_scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00007512 v8::ExtensionConfiguration config(1, &name);
7513 LocalContext context(&config);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007514 CHECK(
7515 v8_str(expected)
7516 ->Equals(context.local(), context->Global()
7517 ->Get(context.local(), v8_str("loaded"))
7518 .ToLocalChecked())
7519 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00007520}
7521
7522
7523/*
7524 * Configuration:
7525 *
7526 * /-- B <--\
7527 * A <- -- D <-- E
7528 * \-- C <--/
7529 */
7530THREADED_TEST(ExtensionDependency) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007531 static const char* kEDeps[] = {"D"};
Steve Blocka7e24c12009-10-30 11:49:00 +00007532 v8::RegisterExtension(new Extension("E", "this.loaded += 'E';", 1, kEDeps));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007533 static const char* kDDeps[] = {"B", "C"};
Steve Blocka7e24c12009-10-30 11:49:00 +00007534 v8::RegisterExtension(new Extension("D", "this.loaded += 'D';", 2, kDDeps));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007535 static const char* kBCDeps[] = {"A"};
Steve Blocka7e24c12009-10-30 11:49:00 +00007536 v8::RegisterExtension(new Extension("B", "this.loaded += 'B';", 1, kBCDeps));
7537 v8::RegisterExtension(new Extension("C", "this.loaded += 'C';", 1, kBCDeps));
7538 v8::RegisterExtension(new Extension("A", "this.loaded += 'A';"));
7539 CheckDependencies("A", "undefinedA");
7540 CheckDependencies("B", "undefinedAB");
7541 CheckDependencies("C", "undefinedAC");
7542 CheckDependencies("D", "undefinedABCD");
7543 CheckDependencies("E", "undefinedABCDE");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007544 v8::HandleScope handle_scope(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007545 static const char* exts[2] = {"C", "E"};
Steve Blocka7e24c12009-10-30 11:49:00 +00007546 v8::ExtensionConfiguration config(2, exts);
7547 LocalContext context(&config);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007548 CHECK(
7549 v8_str("undefinedACBDE")
7550 ->Equals(context.local(), context->Global()
7551 ->Get(context.local(), v8_str("loaded"))
7552 .ToLocalChecked())
7553 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00007554}
7555
7556
7557static const char* kExtensionTestScript =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007558 "native function A();"
7559 "native function B();"
7560 "native function C();"
7561 "function Foo(i) {"
7562 " if (i == 0) return A();"
7563 " if (i == 1) return B();"
7564 " if (i == 2) return C();"
7565 "}";
Steve Blocka7e24c12009-10-30 11:49:00 +00007566
7567
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007568static void CallFun(const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +00007569 ApiTestFuzzer::Fuzz();
Leon Clarkee46be812010-01-19 14:06:41 +00007570 if (args.IsConstructCall()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007571 CHECK(args.This()
7572 ->Set(args.GetIsolate()->GetCurrentContext(), v8_str("data"),
7573 args.Data())
7574 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007575 args.GetReturnValue().SetNull();
7576 return;
Leon Clarkee46be812010-01-19 14:06:41 +00007577 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007578 args.GetReturnValue().Set(args.Data());
Steve Blocka7e24c12009-10-30 11:49:00 +00007579}
7580
7581
7582class FunctionExtension : public Extension {
7583 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007584 FunctionExtension() : Extension("functiontest", kExtensionTestScript) {}
7585 virtual v8::Local<v8::FunctionTemplate> GetNativeFunctionTemplate(
7586 v8::Isolate* isolate, v8::Local<String> name);
Steve Blocka7e24c12009-10-30 11:49:00 +00007587};
7588
7589
7590static int lookup_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007591v8::Local<v8::FunctionTemplate> FunctionExtension::GetNativeFunctionTemplate(
7592 v8::Isolate* isolate, v8::Local<String> name) {
Steve Blocka7e24c12009-10-30 11:49:00 +00007593 lookup_count++;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007594 if (name->Equals(isolate->GetCurrentContext(), v8_str("A")).FromJust()) {
7595 return v8::FunctionTemplate::New(isolate, CallFun,
7596 v8::Integer::New(isolate, 8));
7597 } else if (name->Equals(isolate->GetCurrentContext(), v8_str("B"))
7598 .FromJust()) {
7599 return v8::FunctionTemplate::New(isolate, CallFun,
7600 v8::Integer::New(isolate, 7));
7601 } else if (name->Equals(isolate->GetCurrentContext(), v8_str("C"))
7602 .FromJust()) {
7603 return v8::FunctionTemplate::New(isolate, CallFun,
7604 v8::Integer::New(isolate, 6));
Steve Blocka7e24c12009-10-30 11:49:00 +00007605 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007606 return v8::Local<v8::FunctionTemplate>();
Steve Blocka7e24c12009-10-30 11:49:00 +00007607 }
7608}
7609
7610
7611THREADED_TEST(FunctionLookup) {
7612 v8::RegisterExtension(new FunctionExtension());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007613 v8::HandleScope handle_scope(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007614 static const char* exts[1] = {"functiontest"};
Steve Blocka7e24c12009-10-30 11:49:00 +00007615 v8::ExtensionConfiguration config(1, exts);
7616 LocalContext context(&config);
7617 CHECK_EQ(3, lookup_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007618 CHECK(v8::Integer::New(CcTest::isolate(), 8)
7619 ->Equals(context.local(), CompileRun("Foo(0)"))
7620 .FromJust());
7621 CHECK(v8::Integer::New(CcTest::isolate(), 7)
7622 ->Equals(context.local(), CompileRun("Foo(1)"))
7623 .FromJust());
7624 CHECK(v8::Integer::New(CcTest::isolate(), 6)
7625 ->Equals(context.local(), CompileRun("Foo(2)"))
7626 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00007627}
7628
7629
Leon Clarkee46be812010-01-19 14:06:41 +00007630THREADED_TEST(NativeFunctionConstructCall) {
7631 v8::RegisterExtension(new FunctionExtension());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007632 v8::HandleScope handle_scope(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007633 static const char* exts[1] = {"functiontest"};
Leon Clarkee46be812010-01-19 14:06:41 +00007634 v8::ExtensionConfiguration config(1, exts);
7635 LocalContext context(&config);
Leon Clarked91b9f72010-01-27 17:25:45 +00007636 for (int i = 0; i < 10; i++) {
7637 // Run a few times to ensure that allocation of objects doesn't
7638 // change behavior of a constructor function.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007639 CHECK(v8::Integer::New(CcTest::isolate(), 8)
7640 ->Equals(context.local(), CompileRun("(new A()).data"))
7641 .FromJust());
7642 CHECK(v8::Integer::New(CcTest::isolate(), 7)
7643 ->Equals(context.local(), CompileRun("(new B()).data"))
7644 .FromJust());
7645 CHECK(v8::Integer::New(CcTest::isolate(), 6)
7646 ->Equals(context.local(), CompileRun("(new C()).data"))
7647 .FromJust());
Leon Clarked91b9f72010-01-27 17:25:45 +00007648 }
Leon Clarkee46be812010-01-19 14:06:41 +00007649}
7650
7651
Steve Blocka7e24c12009-10-30 11:49:00 +00007652static const char* last_location;
7653static const char* last_message;
7654void StoringErrorCallback(const char* location, const char* message) {
7655 if (last_location == NULL) {
7656 last_location = location;
7657 last_message = message;
7658 }
7659}
7660
7661
7662// ErrorReporting creates a circular extensions configuration and
7663// tests that the fatal error handler gets called. This renders V8
7664// unusable and therefore this test cannot be run in parallel.
7665TEST(ErrorReporting) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007666 CcTest::isolate()->SetFatalErrorHandler(StoringErrorCallback);
7667 static const char* aDeps[] = {"B"};
Steve Blocka7e24c12009-10-30 11:49:00 +00007668 v8::RegisterExtension(new Extension("A", "", 1, aDeps));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007669 static const char* bDeps[] = {"A"};
Steve Blocka7e24c12009-10-30 11:49:00 +00007670 v8::RegisterExtension(new Extension("B", "", 1, bDeps));
7671 last_location = NULL;
7672 v8::ExtensionConfiguration config(1, bDeps);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007673 v8::Local<Context> context = Context::New(CcTest::isolate(), &config);
Steve Blocka7e24c12009-10-30 11:49:00 +00007674 CHECK(context.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007675 CHECK(last_location);
Steve Blocka7e24c12009-10-30 11:49:00 +00007676}
7677
7678
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007679static void MissingScriptInfoMessageListener(v8::Local<v8::Message> message,
7680 v8::Local<Value> data) {
7681 v8::Isolate* isolate = CcTest::isolate();
7682 Local<Context> context = isolate->GetCurrentContext();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007683 CHECK(message->GetScriptOrigin().ResourceName()->IsUndefined());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007684 CHECK(v8::Undefined(isolate)
7685 ->Equals(context, message->GetScriptOrigin().ResourceName())
7686 .FromJust());
7687 message->GetLineNumber(context).FromJust();
7688 message->GetSourceLine(context).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00007689}
7690
7691
7692THREADED_TEST(ErrorWithMissingScriptInfo) {
Steve Blocka7e24c12009-10-30 11:49:00 +00007693 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007694 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007695 context->GetIsolate()->AddMessageListener(MissingScriptInfoMessageListener);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007696 CompileRun("throw Error()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007697 context->GetIsolate()->RemoveMessageListeners(
7698 MissingScriptInfoMessageListener);
Steve Blocka7e24c12009-10-30 11:49:00 +00007699}
7700
7701
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007702struct FlagAndPersistent {
7703 bool flag;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007704 v8::Global<v8::Object> handle;
Steve Blocka7e24c12009-10-30 11:49:00 +00007705};
7706
Steve Blocka7e24c12009-10-30 11:49:00 +00007707
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007708static void SetFlag(const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007709 data.GetParameter()->flag = true;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007710 data.GetParameter()->handle.Reset();
Steve Blockd0582a62009-12-15 09:54:21 +00007711}
7712
Steve Blockd0582a62009-12-15 09:54:21 +00007713
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007714static void IndependentWeakHandle(bool global_gc, bool interlinked) {
7715 v8::Isolate* iso = CcTest::isolate();
7716 v8::HandleScope scope(iso);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007717 v8::Local<Context> context = Context::New(iso);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007718 Context::Scope context_scope(context);
7719
7720 FlagAndPersistent object_a, object_b;
7721
7722 intptr_t big_heap_size;
7723
7724 {
7725 v8::HandleScope handle_scope(iso);
7726 Local<Object> a(v8::Object::New(iso));
7727 Local<Object> b(v8::Object::New(iso));
7728 object_a.handle.Reset(iso, a);
7729 object_b.handle.Reset(iso, b);
7730 if (interlinked) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007731 a->Set(context, v8_str("x"), b).FromJust();
7732 b->Set(context, v8_str("x"), a).FromJust();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007733 }
7734 if (global_gc) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007735 CcTest::heap()->CollectAllGarbage();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007736 } else {
7737 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
7738 }
7739 // We are relying on this creating a big flag array and reserving the space
7740 // up front.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007741 v8::Local<Value> big_array = CompileRun("new Array(5000)");
7742 a->Set(context, v8_str("y"), big_array).FromJust();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007743 big_heap_size = CcTest::heap()->SizeOfObjects();
7744 }
7745
7746 object_a.flag = false;
7747 object_b.flag = false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007748 object_a.handle.SetWeak(&object_a, &SetFlag,
7749 v8::WeakCallbackType::kParameter);
7750 object_b.handle.SetWeak(&object_b, &SetFlag,
7751 v8::WeakCallbackType::kParameter);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007752 CHECK(!object_b.handle.IsIndependent());
7753 object_a.handle.MarkIndependent();
7754 object_b.handle.MarkIndependent();
7755 CHECK(object_b.handle.IsIndependent());
7756 if (global_gc) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007757 CcTest::heap()->CollectAllGarbage();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007758 } else {
7759 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
7760 }
7761 // A single GC should be enough to reclaim the memory, since we are using
7762 // phantom handles.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007763 CHECK_LT(CcTest::heap()->SizeOfObjects(), big_heap_size - 20000);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007764 CHECK(object_a.flag);
7765 CHECK(object_b.flag);
7766}
7767
7768
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007769TEST(IndependentWeakHandle) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007770 IndependentWeakHandle(false, false);
7771 IndependentWeakHandle(false, true);
7772 IndependentWeakHandle(true, false);
7773 IndependentWeakHandle(true, true);
7774}
7775
7776
7777class Trivial {
7778 public:
7779 explicit Trivial(int x) : x_(x) {}
7780
7781 int x() { return x_; }
7782 void set_x(int x) { x_ = x; }
7783
7784 private:
7785 int x_;
7786};
7787
7788
7789class Trivial2 {
7790 public:
7791 Trivial2(int x, int y) : y_(y), x_(x) {}
7792
7793 int x() { return x_; }
7794 void set_x(int x) { x_ = x; }
7795
7796 int y() { return y_; }
7797 void set_y(int y) { y_ = y; }
7798
7799 private:
7800 int y_;
7801 int x_;
7802};
7803
7804
7805void CheckInternalFields(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007806 const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
7807 v8::Persistent<v8::Object>* handle = data.GetParameter();
7808 handle->Reset();
7809 Trivial* t1 = reinterpret_cast<Trivial*>(data.GetInternalField(0));
7810 Trivial2* t2 = reinterpret_cast<Trivial2*>(data.GetInternalField(1));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007811 CHECK_EQ(42, t1->x());
7812 CHECK_EQ(103, t2->x());
7813 t1->set_x(1729);
7814 t2->set_x(33550336);
7815}
7816
7817
7818void InternalFieldCallback(bool global_gc) {
7819 LocalContext env;
7820 v8::Isolate* isolate = env->GetIsolate();
7821 v8::HandleScope scope(isolate);
7822
7823 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
7824 Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
7825 Trivial* t1;
7826 Trivial2* t2;
7827 instance_templ->SetInternalFieldCount(2);
7828 {
7829 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007830 Local<v8::Object> obj = templ->GetFunction(env.local())
7831 .ToLocalChecked()
7832 ->NewInstance(env.local())
7833 .ToLocalChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007834 v8::Persistent<v8::Object> handle(isolate, obj);
7835 CHECK_EQ(2, obj->InternalFieldCount());
7836 CHECK(obj->GetInternalField(0)->IsUndefined());
7837 t1 = new Trivial(42);
7838 t2 = new Trivial2(103, 9);
7839
7840 obj->SetAlignedPointerInInternalField(0, t1);
7841 t1 = reinterpret_cast<Trivial*>(obj->GetAlignedPointerFromInternalField(0));
7842 CHECK_EQ(42, t1->x());
7843
7844 obj->SetAlignedPointerInInternalField(1, t2);
7845 t2 =
7846 reinterpret_cast<Trivial2*>(obj->GetAlignedPointerFromInternalField(1));
7847 CHECK_EQ(103, t2->x());
7848
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007849 handle.SetWeak<v8::Persistent<v8::Object>>(
7850 &handle, CheckInternalFields, v8::WeakCallbackType::kInternalFields);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007851 if (!global_gc) {
7852 handle.MarkIndependent();
7853 }
7854 }
7855 if (global_gc) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007856 CcTest::heap()->CollectAllGarbage();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007857 } else {
7858 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
7859 }
7860
7861 CHECK_EQ(1729, t1->x());
7862 CHECK_EQ(33550336, t2->x());
7863
7864 delete t1;
7865 delete t2;
7866}
7867
7868
7869THREADED_TEST(InternalFieldCallback) {
7870 InternalFieldCallback(false);
7871 InternalFieldCallback(true);
7872}
7873
7874
7875static void ResetUseValueAndSetFlag(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007876 const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007877 // Blink will reset the handle, and then use the other handle, so they
7878 // can't use the same backing slot.
7879 data.GetParameter()->handle.Reset();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007880 data.GetParameter()->flag = true;
7881}
7882
7883
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007884void v8::internal::HeapTester::ResetWeakHandle(bool global_gc) {
7885 using v8::Context;
7886 using v8::Local;
7887 using v8::Object;
7888
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007889 v8::Isolate* iso = CcTest::isolate();
7890 v8::HandleScope scope(iso);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007891 v8::Local<Context> context = Context::New(iso);
Steve Blockd0582a62009-12-15 09:54:21 +00007892 Context::Scope context_scope(context);
7893
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007894 FlagAndPersistent object_a, object_b;
Steve Blockd0582a62009-12-15 09:54:21 +00007895
7896 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007897 v8::HandleScope handle_scope(iso);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007898 Local<Object> a(v8::Object::New(iso));
7899 Local<Object> b(v8::Object::New(iso));
7900 object_a.handle.Reset(iso, a);
7901 object_b.handle.Reset(iso, b);
7902 if (global_gc) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007903 CcTest::heap()->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007904 } else {
7905 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
7906 }
Steve Blockd0582a62009-12-15 09:54:21 +00007907 }
7908
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007909 object_a.flag = false;
7910 object_b.flag = false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007911 object_a.handle.SetWeak(&object_a, &ResetUseValueAndSetFlag,
7912 v8::WeakCallbackType::kParameter);
7913 object_b.handle.SetWeak(&object_b, &ResetUseValueAndSetFlag,
7914 v8::WeakCallbackType::kParameter);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007915 if (!global_gc) {
7916 object_a.handle.MarkIndependent();
7917 object_b.handle.MarkIndependent();
7918 CHECK(object_b.handle.IsIndependent());
7919 }
7920 if (global_gc) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007921 CcTest::heap()->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007922 } else {
7923 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
7924 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007925 CHECK(object_a.flag);
7926 CHECK(object_b.flag);
Ben Murdoch257744e2011-11-30 15:57:28 +00007927}
Steve Blockd0582a62009-12-15 09:54:21 +00007928
Ben Murdoch257744e2011-11-30 15:57:28 +00007929
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007930THREADED_HEAP_TEST(ResetWeakHandle) {
7931 v8::internal::HeapTester::ResetWeakHandle(false);
7932 v8::internal::HeapTester::ResetWeakHandle(true);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007933}
7934
7935
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007936static void InvokeScavenge() { CcTest::heap()->CollectGarbage(i::NEW_SPACE); }
Ben Murdoch257744e2011-11-30 15:57:28 +00007937
7938
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007939static void InvokeMarkSweep() { CcTest::heap()->CollectAllGarbage(); }
Ben Murdoch257744e2011-11-30 15:57:28 +00007940
7941
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007942static void ForceScavenge2(
7943 const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007944 data.GetParameter()->flag = true;
Ben Murdoch257744e2011-11-30 15:57:28 +00007945 InvokeScavenge();
7946}
7947
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007948static void ForceScavenge1(
7949 const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007950 data.GetParameter()->handle.Reset();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007951 data.SetSecondPassCallback(ForceScavenge2);
7952}
7953
7954
7955static void ForceMarkSweep2(
7956 const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007957 data.GetParameter()->flag = true;
Ben Murdoch257744e2011-11-30 15:57:28 +00007958 InvokeMarkSweep();
7959}
7960
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007961static void ForceMarkSweep1(
7962 const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
7963 data.GetParameter()->handle.Reset();
7964 data.SetSecondPassCallback(ForceMarkSweep2);
7965}
7966
Ben Murdoch257744e2011-11-30 15:57:28 +00007967
7968THREADED_TEST(GCFromWeakCallbacks) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007969 v8::Isolate* isolate = CcTest::isolate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007970 v8::Locker locker(CcTest::isolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007971 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007972 v8::Local<Context> context = Context::New(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +00007973 Context::Scope context_scope(context);
7974
7975 static const int kNumberOfGCTypes = 2;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007976 typedef v8::WeakCallbackInfo<FlagAndPersistent>::Callback Callback;
7977 Callback gc_forcing_callback[kNumberOfGCTypes] = {&ForceScavenge1,
7978 &ForceMarkSweep1};
Ben Murdoch257744e2011-11-30 15:57:28 +00007979
7980 typedef void (*GCInvoker)();
7981 GCInvoker invoke_gc[kNumberOfGCTypes] = {&InvokeScavenge, &InvokeMarkSweep};
7982
7983 for (int outer_gc = 0; outer_gc < kNumberOfGCTypes; outer_gc++) {
7984 for (int inner_gc = 0; inner_gc < kNumberOfGCTypes; inner_gc++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007985 FlagAndPersistent object;
Ben Murdoch257744e2011-11-30 15:57:28 +00007986 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007987 v8::HandleScope handle_scope(isolate);
7988 object.handle.Reset(isolate, v8::Object::New(isolate));
Ben Murdoch257744e2011-11-30 15:57:28 +00007989 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007990 object.flag = false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007991 object.handle.SetWeak(&object, gc_forcing_callback[inner_gc],
7992 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007993 object.handle.MarkIndependent();
Ben Murdoch257744e2011-11-30 15:57:28 +00007994 invoke_gc[outer_gc]();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007995 EmptyMessageQueues(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007996 CHECK(object.flag);
Ben Murdoch257744e2011-11-30 15:57:28 +00007997 }
Steve Blockd0582a62009-12-15 09:54:21 +00007998 }
Ben Murdoch257744e2011-11-30 15:57:28 +00007999}
8000
8001
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008002v8::Local<Function> args_fun;
Steve Blocka7e24c12009-10-30 11:49:00 +00008003
8004
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008005static void ArgumentsTestCallback(
8006 const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +00008007 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008008 v8::Isolate* isolate = args.GetIsolate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008009 Local<Context> context = isolate->GetCurrentContext();
Steve Blocka7e24c12009-10-30 11:49:00 +00008010 CHECK_EQ(3, args.Length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008011 CHECK(v8::Integer::New(isolate, 1)->Equals(context, args[0]).FromJust());
8012 CHECK(v8::Integer::New(isolate, 2)->Equals(context, args[1]).FromJust());
8013 CHECK(v8::Integer::New(isolate, 3)->Equals(context, args[2]).FromJust());
8014 CHECK(v8::Undefined(isolate)->Equals(context, args[3]).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008015 v8::HandleScope scope(args.GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008016 CcTest::heap()->CollectAllGarbage();
Steve Blocka7e24c12009-10-30 11:49:00 +00008017}
8018
8019
8020THREADED_TEST(Arguments) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008021 v8::Isolate* isolate = CcTest::isolate();
8022 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008023 v8::Local<v8::ObjectTemplate> global = ObjectTemplate::New(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008024 global->Set(v8_str("f"),
8025 v8::FunctionTemplate::New(isolate, ArgumentsTestCallback));
Steve Blocka7e24c12009-10-30 11:49:00 +00008026 LocalContext context(NULL, global);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008027 args_fun = context->Global()
8028 ->Get(context.local(), v8_str("f"))
8029 .ToLocalChecked()
8030 .As<Function>();
8031 v8_compile("f(1, 2, 3)")->Run(context.local()).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00008032}
8033
8034
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008035static int p_getter_count;
8036static int p_getter_count2;
Steve Blocka7e24c12009-10-30 11:49:00 +00008037
8038
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008039static void PGetter(Local<Name> name,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008040 const v8::PropertyCallbackInfo<v8::Value>& info) {
Steve Blocka7e24c12009-10-30 11:49:00 +00008041 ApiTestFuzzer::Fuzz();
8042 p_getter_count++;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008043 v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
8044 v8::Local<v8::Object> global = context->Global();
8045 CHECK(
8046 info.Holder()
8047 ->Equals(context, global->Get(context, v8_str("o1")).ToLocalChecked())
8048 .FromJust());
8049 if (name->Equals(context, v8_str("p1")).FromJust()) {
8050 CHECK(info.This()
8051 ->Equals(context,
8052 global->Get(context, v8_str("o1")).ToLocalChecked())
8053 .FromJust());
8054 } else if (name->Equals(context, v8_str("p2")).FromJust()) {
8055 CHECK(info.This()
8056 ->Equals(context,
8057 global->Get(context, v8_str("o2")).ToLocalChecked())
8058 .FromJust());
8059 } else if (name->Equals(context, v8_str("p3")).FromJust()) {
8060 CHECK(info.This()
8061 ->Equals(context,
8062 global->Get(context, v8_str("o3")).ToLocalChecked())
8063 .FromJust());
8064 } else if (name->Equals(context, v8_str("p4")).FromJust()) {
8065 CHECK(info.This()
8066 ->Equals(context,
8067 global->Get(context, v8_str("o4")).ToLocalChecked())
8068 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00008069 }
Steve Blocka7e24c12009-10-30 11:49:00 +00008070}
8071
8072
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008073static void RunHolderTest(v8::Local<v8::ObjectTemplate> obj) {
Steve Blocka7e24c12009-10-30 11:49:00 +00008074 ApiTestFuzzer::Fuzz();
8075 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008076 CHECK(context->Global()
8077 ->Set(context.local(), v8_str("o1"),
8078 obj->NewInstance(context.local()).ToLocalChecked())
8079 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00008080 CompileRun(
8081 "o1.__proto__ = { };"
8082 "var o2 = { __proto__: o1 };"
8083 "var o3 = { __proto__: o2 };"
8084 "var o4 = { __proto__: o3 };"
8085 "for (var i = 0; i < 10; i++) o4.p4;"
8086 "for (var i = 0; i < 10; i++) o3.p3;"
8087 "for (var i = 0; i < 10; i++) o2.p2;"
8088 "for (var i = 0; i < 10; i++) o1.p1;");
8089}
8090
8091
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008092static void PGetter2(Local<Name> name,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008093 const v8::PropertyCallbackInfo<v8::Value>& info) {
Steve Blocka7e24c12009-10-30 11:49:00 +00008094 ApiTestFuzzer::Fuzz();
8095 p_getter_count2++;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008096 v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
8097 v8::Local<v8::Object> global = context->Global();
8098 CHECK(
8099 info.Holder()
8100 ->Equals(context, global->Get(context, v8_str("o1")).ToLocalChecked())
8101 .FromJust());
8102 if (name->Equals(context, v8_str("p1")).FromJust()) {
8103 CHECK(info.This()
8104 ->Equals(context,
8105 global->Get(context, v8_str("o1")).ToLocalChecked())
8106 .FromJust());
8107 } else if (name->Equals(context, v8_str("p2")).FromJust()) {
8108 CHECK(info.This()
8109 ->Equals(context,
8110 global->Get(context, v8_str("o2")).ToLocalChecked())
8111 .FromJust());
8112 } else if (name->Equals(context, v8_str("p3")).FromJust()) {
8113 CHECK(info.This()
8114 ->Equals(context,
8115 global->Get(context, v8_str("o3")).ToLocalChecked())
8116 .FromJust());
8117 } else if (name->Equals(context, v8_str("p4")).FromJust()) {
8118 CHECK(info.This()
8119 ->Equals(context,
8120 global->Get(context, v8_str("o4")).ToLocalChecked())
8121 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00008122 }
Steve Blocka7e24c12009-10-30 11:49:00 +00008123}
8124
8125
8126THREADED_TEST(GetterHolders) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008127 v8::Isolate* isolate = CcTest::isolate();
8128 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008129 v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00008130 obj->SetAccessor(v8_str("p1"), PGetter);
8131 obj->SetAccessor(v8_str("p2"), PGetter);
8132 obj->SetAccessor(v8_str("p3"), PGetter);
8133 obj->SetAccessor(v8_str("p4"), PGetter);
8134 p_getter_count = 0;
8135 RunHolderTest(obj);
8136 CHECK_EQ(40, p_getter_count);
8137}
8138
8139
8140THREADED_TEST(PreInterceptorHolders) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008141 v8::Isolate* isolate = CcTest::isolate();
8142 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008143 v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008144 obj->SetHandler(v8::NamedPropertyHandlerConfiguration(PGetter2));
Steve Blocka7e24c12009-10-30 11:49:00 +00008145 p_getter_count2 = 0;
8146 RunHolderTest(obj);
8147 CHECK_EQ(40, p_getter_count2);
8148}
8149
8150
8151THREADED_TEST(ObjectInstantiation) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008152 v8::Isolate* isolate = CcTest::isolate();
8153 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008154 v8::Local<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00008155 templ->SetAccessor(v8_str("t"), PGetter2);
8156 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008157 CHECK(context->Global()
8158 ->Set(context.local(), v8_str("o"),
8159 templ->NewInstance(context.local()).ToLocalChecked())
8160 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00008161 for (int i = 0; i < 100; i++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008162 v8::HandleScope inner_scope(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008163 v8::Local<v8::Object> obj =
8164 templ->NewInstance(context.local()).ToLocalChecked();
8165 CHECK(!obj->Equals(context.local(), context->Global()
8166 ->Get(context.local(), v8_str("o"))
8167 .ToLocalChecked())
8168 .FromJust());
8169 CHECK(
8170 context->Global()->Set(context.local(), v8_str("o2"), obj).FromJust());
8171 v8::Local<Value> value = CompileRun("o.__proto__ === o2.__proto__");
8172 CHECK(v8::True(isolate)->Equals(context.local(), value).FromJust());
8173 CHECK(context->Global()->Set(context.local(), v8_str("o"), obj).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00008174 }
8175}
8176
8177
Ben Murdochb0fe1622011-05-05 13:52:32 +01008178static int StrCmp16(uint16_t* a, uint16_t* b) {
8179 while (true) {
8180 if (*a == 0 && *b == 0) return 0;
8181 if (*a != *b) return 0 + *a - *b;
8182 a++;
8183 b++;
8184 }
8185}
8186
8187
8188static int StrNCmp16(uint16_t* a, uint16_t* b, int n) {
8189 while (true) {
8190 if (n-- == 0) return 0;
8191 if (*a == 0 && *b == 0) return 0;
8192 if (*a != *b) return 0 + *a - *b;
8193 a++;
8194 b++;
8195 }
8196}
8197
8198
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008199int GetUtf8Length(Local<String> str) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008200 int len = str->Utf8Length();
8201 if (len < 0) {
8202 i::Handle<i::String> istr(v8::Utils::OpenHandle(*str));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008203 i::String::Flatten(istr);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008204 len = str->Utf8Length();
8205 }
8206 return len;
8207}
8208
8209
Steve Blocka7e24c12009-10-30 11:49:00 +00008210THREADED_TEST(StringWrite) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008211 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008212 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008213 v8::Local<String> str = v8_str("abcde");
Ben Murdochb0fe1622011-05-05 13:52:32 +01008214 // abc<Icelandic eth><Unicode snowman>.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008215 v8::Local<String> str2 = v8_str("abc\303\260\342\230\203");
8216 v8::Local<String> str3 =
8217 v8::String::NewFromUtf8(context->GetIsolate(), "abc\0def",
8218 v8::NewStringType::kNormal, 7)
8219 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008220 // "ab" + lead surrogate + "cd" + trail surrogate + "ef"
8221 uint16_t orphans[8] = { 0x61, 0x62, 0xd800, 0x63, 0x64, 0xdc00, 0x65, 0x66 };
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008222 v8::Local<String> orphans_str =
8223 v8::String::NewFromTwoByte(context->GetIsolate(), orphans,
8224 v8::NewStringType::kNormal, 8)
8225 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008226 // single lead surrogate
8227 uint16_t lead[1] = { 0xd800 };
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008228 v8::Local<String> lead_str =
8229 v8::String::NewFromTwoByte(context->GetIsolate(), lead,
8230 v8::NewStringType::kNormal, 1)
8231 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008232 // single trail surrogate
8233 uint16_t trail[1] = { 0xdc00 };
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008234 v8::Local<String> trail_str =
8235 v8::String::NewFromTwoByte(context->GetIsolate(), trail,
8236 v8::NewStringType::kNormal, 1)
8237 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008238 // surrogate pair
8239 uint16_t pair[2] = { 0xd800, 0xdc00 };
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008240 v8::Local<String> pair_str =
8241 v8::String::NewFromTwoByte(context->GetIsolate(), pair,
8242 v8::NewStringType::kNormal, 2)
8243 .ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008244 const int kStride = 4; // Must match stride in for loops in JS below.
8245 CompileRun(
8246 "var left = '';"
8247 "for (var i = 0; i < 0xd800; i += 4) {"
8248 " left = left + String.fromCharCode(i);"
8249 "}");
8250 CompileRun(
8251 "var right = '';"
8252 "for (var i = 0; i < 0xd800; i += 4) {"
8253 " right = String.fromCharCode(i) + right;"
8254 "}");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008255 v8::Local<v8::Object> global = context->Global();
8256 Local<String> left_tree = global->Get(context.local(), v8_str("left"))
8257 .ToLocalChecked()
8258 .As<String>();
8259 Local<String> right_tree = global->Get(context.local(), v8_str("right"))
8260 .ToLocalChecked()
8261 .As<String>();
Ben Murdochb0fe1622011-05-05 13:52:32 +01008262
8263 CHECK_EQ(5, str2->Length());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008264 CHECK_EQ(0xd800 / kStride, left_tree->Length());
8265 CHECK_EQ(0xd800 / kStride, right_tree->Length());
Steve Blocka7e24c12009-10-30 11:49:00 +00008266
8267 char buf[100];
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008268 char utf8buf[0xd800 * 3];
Ben Murdochb0fe1622011-05-05 13:52:32 +01008269 uint16_t wbuf[100];
Steve Blocka7e24c12009-10-30 11:49:00 +00008270 int len;
Ben Murdochb0fe1622011-05-05 13:52:32 +01008271 int charlen;
8272
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008273 memset(utf8buf, 0x1, 1000);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008274 len = str2->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen);
Steve Block44f0eee2011-05-26 01:26:41 +01008275 CHECK_EQ(9, len);
8276 CHECK_EQ(5, charlen);
8277 CHECK_EQ(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008278
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008279 memset(utf8buf, 0x1, 1000);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008280 len = str2->WriteUtf8(utf8buf, 8, &charlen);
Steve Block44f0eee2011-05-26 01:26:41 +01008281 CHECK_EQ(8, len);
8282 CHECK_EQ(5, charlen);
8283 CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\342\230\203\1", 9));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008284
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008285 memset(utf8buf, 0x1, 1000);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008286 len = str2->WriteUtf8(utf8buf, 7, &charlen);
Steve Block44f0eee2011-05-26 01:26:41 +01008287 CHECK_EQ(5, len);
8288 CHECK_EQ(4, charlen);
8289 CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008290
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008291 memset(utf8buf, 0x1, 1000);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008292 len = str2->WriteUtf8(utf8buf, 6, &charlen);
Steve Block44f0eee2011-05-26 01:26:41 +01008293 CHECK_EQ(5, len);
8294 CHECK_EQ(4, charlen);
8295 CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008296
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008297 memset(utf8buf, 0x1, 1000);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008298 len = str2->WriteUtf8(utf8buf, 5, &charlen);
Steve Block44f0eee2011-05-26 01:26:41 +01008299 CHECK_EQ(5, len);
8300 CHECK_EQ(4, charlen);
8301 CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008302
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008303 memset(utf8buf, 0x1, 1000);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008304 len = str2->WriteUtf8(utf8buf, 4, &charlen);
Steve Block44f0eee2011-05-26 01:26:41 +01008305 CHECK_EQ(3, len);
8306 CHECK_EQ(3, charlen);
8307 CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4));
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, 3, &charlen);
Steve Block44f0eee2011-05-26 01:26:41 +01008311 CHECK_EQ(3, len);
8312 CHECK_EQ(3, charlen);
8313 CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4));
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, 2, &charlen);
Steve Block44f0eee2011-05-26 01:26:41 +01008317 CHECK_EQ(2, len);
8318 CHECK_EQ(2, charlen);
8319 CHECK_EQ(0, strncmp(utf8buf, "ab\1", 3));
Steve Blocka7e24c12009-10-30 11:49:00 +00008320
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008321 // allow orphan surrogates by default
8322 memset(utf8buf, 0x1, 1000);
8323 len = orphans_str->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen);
8324 CHECK_EQ(13, len);
8325 CHECK_EQ(8, charlen);
8326 CHECK_EQ(0, strcmp(utf8buf, "ab\355\240\200cd\355\260\200ef"));
8327
8328 // replace orphan surrogates with unicode replacement character
8329 memset(utf8buf, 0x1, 1000);
8330 len = orphans_str->WriteUtf8(utf8buf,
8331 sizeof(utf8buf),
8332 &charlen,
8333 String::REPLACE_INVALID_UTF8);
8334 CHECK_EQ(13, len);
8335 CHECK_EQ(8, charlen);
8336 CHECK_EQ(0, strcmp(utf8buf, "ab\357\277\275cd\357\277\275ef"));
8337
8338 // replace single lead surrogate with unicode replacement character
8339 memset(utf8buf, 0x1, 1000);
8340 len = lead_str->WriteUtf8(utf8buf,
8341 sizeof(utf8buf),
8342 &charlen,
8343 String::REPLACE_INVALID_UTF8);
8344 CHECK_EQ(4, len);
8345 CHECK_EQ(1, charlen);
8346 CHECK_EQ(0, strcmp(utf8buf, "\357\277\275"));
8347
8348 // replace single trail surrogate with unicode replacement character
8349 memset(utf8buf, 0x1, 1000);
8350 len = trail_str->WriteUtf8(utf8buf,
8351 sizeof(utf8buf),
8352 &charlen,
8353 String::REPLACE_INVALID_UTF8);
8354 CHECK_EQ(4, len);
8355 CHECK_EQ(1, charlen);
8356 CHECK_EQ(0, strcmp(utf8buf, "\357\277\275"));
8357
8358 // do not replace / write anything if surrogate pair does not fit the buffer
8359 // space
8360 memset(utf8buf, 0x1, 1000);
8361 len = pair_str->WriteUtf8(utf8buf,
8362 3,
8363 &charlen,
8364 String::REPLACE_INVALID_UTF8);
8365 CHECK_EQ(0, len);
8366 CHECK_EQ(0, charlen);
8367
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008368 memset(utf8buf, 0x1, sizeof(utf8buf));
8369 len = GetUtf8Length(left_tree);
8370 int utf8_expected =
8371 (0x80 + (0x800 - 0x80) * 2 + (0xd800 - 0x800) * 3) / kStride;
8372 CHECK_EQ(utf8_expected, len);
8373 len = left_tree->WriteUtf8(utf8buf, utf8_expected, &charlen);
8374 CHECK_EQ(utf8_expected, len);
8375 CHECK_EQ(0xd800 / kStride, charlen);
8376 CHECK_EQ(0xed, static_cast<unsigned char>(utf8buf[utf8_expected - 3]));
8377 CHECK_EQ(0x9f, static_cast<unsigned char>(utf8buf[utf8_expected - 2]));
8378 CHECK_EQ(0xc0 - kStride,
8379 static_cast<unsigned char>(utf8buf[utf8_expected - 1]));
8380 CHECK_EQ(1, utf8buf[utf8_expected]);
8381
8382 memset(utf8buf, 0x1, sizeof(utf8buf));
8383 len = GetUtf8Length(right_tree);
8384 CHECK_EQ(utf8_expected, len);
8385 len = right_tree->WriteUtf8(utf8buf, utf8_expected, &charlen);
8386 CHECK_EQ(utf8_expected, len);
8387 CHECK_EQ(0xd800 / kStride, charlen);
8388 CHECK_EQ(0xed, static_cast<unsigned char>(utf8buf[0]));
8389 CHECK_EQ(0x9f, static_cast<unsigned char>(utf8buf[1]));
8390 CHECK_EQ(0xc0 - kStride, static_cast<unsigned char>(utf8buf[2]));
8391 CHECK_EQ(1, utf8buf[utf8_expected]);
8392
Steve Blocka7e24c12009-10-30 11:49:00 +00008393 memset(buf, 0x1, sizeof(buf));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008394 memset(wbuf, 0x1, sizeof(wbuf));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008395 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf));
Steve Block44f0eee2011-05-26 01:26:41 +01008396 CHECK_EQ(5, len);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008397 len = str->Write(wbuf);
Steve Block44f0eee2011-05-26 01:26:41 +01008398 CHECK_EQ(5, len);
8399 CHECK_EQ(0, strcmp("abcde", buf));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008400 uint16_t answer1[] = {'a', 'b', 'c', 'd', 'e', '\0'};
Steve Block44f0eee2011-05-26 01:26:41 +01008401 CHECK_EQ(0, StrCmp16(answer1, wbuf));
Steve Blocka7e24c12009-10-30 11:49:00 +00008402
8403 memset(buf, 0x1, sizeof(buf));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008404 memset(wbuf, 0x1, sizeof(wbuf));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008405 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 4);
Steve Block44f0eee2011-05-26 01:26:41 +01008406 CHECK_EQ(4, len);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008407 len = str->Write(wbuf, 0, 4);
Steve Block44f0eee2011-05-26 01:26:41 +01008408 CHECK_EQ(4, len);
8409 CHECK_EQ(0, strncmp("abcd\1", buf, 5));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008410 uint16_t answer2[] = {'a', 'b', 'c', 'd', 0x101};
Steve Block44f0eee2011-05-26 01:26:41 +01008411 CHECK_EQ(0, StrNCmp16(answer2, wbuf, 5));
Steve Blocka7e24c12009-10-30 11:49:00 +00008412
8413 memset(buf, 0x1, sizeof(buf));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008414 memset(wbuf, 0x1, sizeof(wbuf));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008415 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 5);
Steve Block44f0eee2011-05-26 01:26:41 +01008416 CHECK_EQ(5, len);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008417 len = str->Write(wbuf, 0, 5);
Steve Block44f0eee2011-05-26 01:26:41 +01008418 CHECK_EQ(5, len);
8419 CHECK_EQ(0, strncmp("abcde\1", buf, 6));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008420 uint16_t answer3[] = {'a', 'b', 'c', 'd', 'e', 0x101};
Steve Block44f0eee2011-05-26 01:26:41 +01008421 CHECK_EQ(0, StrNCmp16(answer3, wbuf, 6));
Steve Blocka7e24c12009-10-30 11:49:00 +00008422
8423 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), 0, 6);
Steve Block44f0eee2011-05-26 01:26:41 +01008426 CHECK_EQ(5, len);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008427 len = str->Write(wbuf, 0, 6);
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 answer4[] = {'a', 'b', 'c', 'd', 'e', '\0'};
Steve Block44f0eee2011-05-26 01:26:41 +01008431 CHECK_EQ(0, StrCmp16(answer4, 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), 4, -1);
Steve Block44f0eee2011-05-26 01:26:41 +01008436 CHECK_EQ(1, len);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008437 len = str->Write(wbuf, 4, -1);
Steve Block44f0eee2011-05-26 01:26:41 +01008438 CHECK_EQ(1, len);
8439 CHECK_EQ(0, strcmp("e", buf));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008440 uint16_t answer5[] = {'e', '\0'};
Steve Block44f0eee2011-05-26 01:26:41 +01008441 CHECK_EQ(0, StrCmp16(answer5, wbuf));
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), 4, 6);
Steve Block44f0eee2011-05-26 01:26:41 +01008446 CHECK_EQ(1, len);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008447 len = str->Write(wbuf, 4, 6);
Steve Block44f0eee2011-05-26 01:26:41 +01008448 CHECK_EQ(1, len);
8449 CHECK_EQ(0, strcmp("e", buf));
8450 CHECK_EQ(0, StrCmp16(answer5, wbuf));
Steve Blocka7e24c12009-10-30 11:49:00 +00008451
8452 memset(buf, 0x1, sizeof(buf));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008453 memset(wbuf, 0x1, sizeof(wbuf));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008454 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, 1);
Steve Block44f0eee2011-05-26 01:26:41 +01008455 CHECK_EQ(1, len);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008456 len = str->Write(wbuf, 4, 1);
Steve Block44f0eee2011-05-26 01:26:41 +01008457 CHECK_EQ(1, len);
8458 CHECK_EQ(0, strncmp("e\1", buf, 2));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008459 uint16_t answer6[] = {'e', 0x101};
Steve Block44f0eee2011-05-26 01:26:41 +01008460 CHECK_EQ(0, StrNCmp16(answer6, wbuf, 2));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008461
8462 memset(buf, 0x1, sizeof(buf));
8463 memset(wbuf, 0x1, sizeof(wbuf));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008464 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 3, 1);
Steve Block44f0eee2011-05-26 01:26:41 +01008465 CHECK_EQ(1, len);
Ben Murdochb0fe1622011-05-05 13:52:32 +01008466 len = str->Write(wbuf, 3, 1);
Steve Block44f0eee2011-05-26 01:26:41 +01008467 CHECK_EQ(1, len);
8468 CHECK_EQ(0, strncmp("d\1", buf, 2));
Ben Murdochb0fe1622011-05-05 13:52:32 +01008469 uint16_t answer7[] = {'d', 0x101};
Steve Block44f0eee2011-05-26 01:26:41 +01008470 CHECK_EQ(0, StrNCmp16(answer7, wbuf, 2));
Ben Murdoch69a99ed2011-11-30 16:03:39 +00008471
8472 memset(wbuf, 0x1, sizeof(wbuf));
8473 wbuf[5] = 'X';
8474 len = str->Write(wbuf, 0, 6, String::NO_NULL_TERMINATION);
8475 CHECK_EQ(5, len);
8476 CHECK_EQ('X', wbuf[5]);
8477 uint16_t answer8a[] = {'a', 'b', 'c', 'd', 'e'};
8478 uint16_t answer8b[] = {'a', 'b', 'c', 'd', 'e', '\0'};
8479 CHECK_EQ(0, StrNCmp16(answer8a, wbuf, 5));
8480 CHECK_NE(0, StrCmp16(answer8b, wbuf));
8481 wbuf[5] = '\0';
8482 CHECK_EQ(0, StrCmp16(answer8b, wbuf));
8483
8484 memset(buf, 0x1, sizeof(buf));
8485 buf[5] = 'X';
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008486 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf),
8487 0,
8488 6,
8489 String::NO_NULL_TERMINATION);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00008490 CHECK_EQ(5, len);
8491 CHECK_EQ('X', buf[5]);
8492 CHECK_EQ(0, strncmp("abcde", buf, 5));
8493 CHECK_NE(0, strcmp("abcde", buf));
8494 buf[5] = '\0';
8495 CHECK_EQ(0, strcmp("abcde", buf));
8496
8497 memset(utf8buf, 0x1, sizeof(utf8buf));
8498 utf8buf[8] = 'X';
8499 len = str2->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen,
8500 String::NO_NULL_TERMINATION);
8501 CHECK_EQ(8, len);
8502 CHECK_EQ('X', utf8buf[8]);
8503 CHECK_EQ(5, charlen);
8504 CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\342\230\203", 8));
8505 CHECK_NE(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
8506 utf8buf[8] = '\0';
8507 CHECK_EQ(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008508
8509 memset(utf8buf, 0x1, sizeof(utf8buf));
8510 utf8buf[5] = 'X';
8511 len = str->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen,
8512 String::NO_NULL_TERMINATION);
8513 CHECK_EQ(5, len);
8514 CHECK_EQ('X', utf8buf[5]); // Test that the sixth character is untouched.
8515 CHECK_EQ(5, charlen);
8516 utf8buf[5] = '\0';
8517 CHECK_EQ(0, strcmp(utf8buf, "abcde"));
8518
8519 memset(buf, 0x1, sizeof(buf));
8520 len = str3->WriteOneByte(reinterpret_cast<uint8_t*>(buf));
8521 CHECK_EQ(7, len);
8522 CHECK_EQ(0, strcmp("abc", buf));
8523 CHECK_EQ(0, buf[3]);
8524 CHECK_EQ(0, strcmp("def", buf + 4));
8525
8526 CHECK_EQ(0, str->WriteOneByte(NULL, 0, 0, String::NO_NULL_TERMINATION));
8527 CHECK_EQ(0, str->WriteUtf8(NULL, 0, 0, String::NO_NULL_TERMINATION));
8528 CHECK_EQ(0, str->Write(NULL, 0, 0, String::NO_NULL_TERMINATION));
Steve Blocka7e24c12009-10-30 11:49:00 +00008529}
8530
8531
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008532static void Utf16Helper(
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008533 LocalContext& context, // NOLINT
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008534 const char* name,
8535 const char* lengths_name,
8536 int len) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008537 Local<v8::Array> a = Local<v8::Array>::Cast(
8538 context->Global()->Get(context.local(), v8_str(name)).ToLocalChecked());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008539 Local<v8::Array> alens =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008540 Local<v8::Array>::Cast(context->Global()
8541 ->Get(context.local(), v8_str(lengths_name))
8542 .ToLocalChecked());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008543 for (int i = 0; i < len; i++) {
8544 Local<v8::String> string =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008545 Local<v8::String>::Cast(a->Get(context.local(), i).ToLocalChecked());
8546 Local<v8::Number> expected_len = Local<v8::Number>::Cast(
8547 alens->Get(context.local(), i).ToLocalChecked());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008548 int length = GetUtf8Length(string);
8549 CHECK_EQ(static_cast<int>(expected_len->Value()), length);
8550 }
8551}
8552
8553
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008554THREADED_TEST(Utf16) {
8555 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008556 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008557 CompileRun(
8558 "var pad = '01234567890123456789';"
8559 "var p = [];"
8560 "var plens = [20, 3, 3];"
8561 "p.push('01234567890123456789');"
8562 "var lead = 0xd800;"
8563 "var trail = 0xdc00;"
8564 "p.push(String.fromCharCode(0xd800));"
8565 "p.push(String.fromCharCode(0xdc00));"
8566 "var a = [];"
8567 "var b = [];"
8568 "var c = [];"
8569 "var alens = [];"
8570 "for (var i = 0; i < 3; i++) {"
8571 " p[1] = String.fromCharCode(lead++);"
8572 " for (var j = 0; j < 3; j++) {"
8573 " p[2] = String.fromCharCode(trail++);"
8574 " a.push(p[i] + p[j]);"
8575 " b.push(p[i] + p[j]);"
8576 " c.push(p[i] + p[j]);"
8577 " alens.push(plens[i] + plens[j]);"
8578 " }"
8579 "}"
8580 "alens[5] -= 2;" // Here the surrogate pairs match up.
8581 "var a2 = [];"
8582 "var b2 = [];"
8583 "var c2 = [];"
8584 "var a2lens = [];"
8585 "for (var m = 0; m < 9; m++) {"
8586 " for (var n = 0; n < 9; n++) {"
8587 " a2.push(a[m] + a[n]);"
8588 " b2.push(b[m] + b[n]);"
8589 " var newc = 'x' + c[m] + c[n] + 'y';"
8590 " c2.push(newc.substring(1, newc.length - 1));"
8591 " var utf = alens[m] + alens[n];" // And here.
8592 // The 'n's that start with 0xdc.. are 6-8
8593 // The 'm's that end with 0xd8.. are 1, 4 and 7
8594 " if ((m % 3) == 1 && n >= 6) utf -= 2;"
8595 " a2lens.push(utf);"
8596 " }"
8597 "}");
8598 Utf16Helper(context, "a", "alens", 9);
8599 Utf16Helper(context, "a2", "a2lens", 81);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008600}
8601
8602
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008603static bool SameSymbol(Local<String> s1, Local<String> s2) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008604 i::Handle<i::String> is1(v8::Utils::OpenHandle(*s1));
8605 i::Handle<i::String> is2(v8::Utils::OpenHandle(*s2));
8606 return *is1 == *is2;
8607}
8608
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008609
8610THREADED_TEST(Utf16Symbol) {
8611 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008612 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008613
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008614 Local<String> symbol1 =
8615 v8::String::NewFromUtf8(context->GetIsolate(), "abc",
8616 v8::NewStringType::kInternalized)
8617 .ToLocalChecked();
8618 Local<String> symbol2 =
8619 v8::String::NewFromUtf8(context->GetIsolate(), "abc",
8620 v8::NewStringType::kInternalized)
8621 .ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008622 CHECK(SameSymbol(symbol1, symbol2));
8623
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008624 CompileRun(
8625 "var sym0 = 'benedictus';"
8626 "var sym0b = 'S\303\270ren';"
8627 "var sym1 = '\355\240\201\355\260\207';"
8628 "var sym2 = '\360\220\220\210';"
8629 "var sym3 = 'x\355\240\201\355\260\207';"
8630 "var sym4 = 'x\360\220\220\210';"
8631 "if (sym1.length != 2) throw sym1;"
8632 "if (sym1.charCodeAt(1) != 0xdc07) throw sym1.charCodeAt(1);"
8633 "if (sym2.length != 2) throw sym2;"
8634 "if (sym2.charCodeAt(1) != 0xdc08) throw sym2.charCodeAt(2);"
8635 "if (sym3.length != 3) throw sym3;"
8636 "if (sym3.charCodeAt(2) != 0xdc07) throw sym1.charCodeAt(2);"
8637 "if (sym4.length != 3) throw sym4;"
8638 "if (sym4.charCodeAt(2) != 0xdc08) throw sym2.charCodeAt(2);");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008639 Local<String> sym0 =
8640 v8::String::NewFromUtf8(context->GetIsolate(), "benedictus",
8641 v8::NewStringType::kInternalized)
8642 .ToLocalChecked();
8643 Local<String> sym0b =
8644 v8::String::NewFromUtf8(context->GetIsolate(), "S\303\270ren",
8645 v8::NewStringType::kInternalized)
8646 .ToLocalChecked();
8647 Local<String> sym1 =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008648 v8::String::NewFromUtf8(context->GetIsolate(), "\355\240\201\355\260\207",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008649 v8::NewStringType::kInternalized)
8650 .ToLocalChecked();
8651 Local<String> sym2 =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008652 v8::String::NewFromUtf8(context->GetIsolate(), "\360\220\220\210",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008653 v8::NewStringType::kInternalized)
8654 .ToLocalChecked();
8655 Local<String> sym3 = v8::String::NewFromUtf8(context->GetIsolate(),
8656 "x\355\240\201\355\260\207",
8657 v8::NewStringType::kInternalized)
8658 .ToLocalChecked();
8659 Local<String> sym4 =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008660 v8::String::NewFromUtf8(context->GetIsolate(), "x\360\220\220\210",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008661 v8::NewStringType::kInternalized)
8662 .ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008663 v8::Local<v8::Object> global = context->Global();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008664 Local<Value> s0 =
8665 global->Get(context.local(), v8_str("sym0")).ToLocalChecked();
8666 Local<Value> s0b =
8667 global->Get(context.local(), v8_str("sym0b")).ToLocalChecked();
8668 Local<Value> s1 =
8669 global->Get(context.local(), v8_str("sym1")).ToLocalChecked();
8670 Local<Value> s2 =
8671 global->Get(context.local(), v8_str("sym2")).ToLocalChecked();
8672 Local<Value> s3 =
8673 global->Get(context.local(), v8_str("sym3")).ToLocalChecked();
8674 Local<Value> s4 =
8675 global->Get(context.local(), v8_str("sym4")).ToLocalChecked();
8676 CHECK(SameSymbol(sym0, Local<String>::Cast(s0)));
8677 CHECK(SameSymbol(sym0b, Local<String>::Cast(s0b)));
8678 CHECK(SameSymbol(sym1, Local<String>::Cast(s1)));
8679 CHECK(SameSymbol(sym2, Local<String>::Cast(s2)));
8680 CHECK(SameSymbol(sym3, Local<String>::Cast(s3)));
8681 CHECK(SameSymbol(sym4, Local<String>::Cast(s4)));
8682}
8683
8684
8685THREADED_TEST(Utf16MissingTrailing) {
8686 LocalContext context;
8687 v8::HandleScope scope(context->GetIsolate());
8688
8689 // Make sure it will go past the buffer, so it will call `WriteUtf16Slow`
8690 int size = 1024 * 64;
8691 uint8_t* buffer = new uint8_t[size];
8692 for (int i = 0; i < size; i += 4) {
8693 buffer[i] = 0xf0;
8694 buffer[i + 1] = 0x9d;
8695 buffer[i + 2] = 0x80;
8696 buffer[i + 3] = 0x9e;
8697 }
8698
8699 // Now invoke the decoder without last 3 bytes
8700 v8::Local<v8::String> str =
8701 v8::String::NewFromUtf8(
8702 context->GetIsolate(), reinterpret_cast<char*>(buffer),
8703 v8::NewStringType::kNormal, size - 3).ToLocalChecked();
8704 USE(str);
8705 delete[] buffer;
8706}
8707
8708
8709THREADED_TEST(Utf16Trailing3Byte) {
8710 LocalContext context;
8711 v8::HandleScope scope(context->GetIsolate());
8712
8713 // Make sure it will go past the buffer, so it will call `WriteUtf16Slow`
8714 int size = 1024 * 63;
8715 uint8_t* buffer = new uint8_t[size];
8716 for (int i = 0; i < size; i += 3) {
8717 buffer[i] = 0xe2;
8718 buffer[i + 1] = 0x80;
8719 buffer[i + 2] = 0xa6;
8720 }
8721
8722 // Now invoke the decoder without last 3 bytes
8723 v8::Local<v8::String> str =
8724 v8::String::NewFromUtf8(
8725 context->GetIsolate(), reinterpret_cast<char*>(buffer),
8726 v8::NewStringType::kNormal, size).ToLocalChecked();
8727
8728 v8::String::Value value(str);
8729 CHECK_EQ(value.length(), size / 3);
8730 CHECK_EQ((*value)[value.length() - 1], 0x2026);
8731
8732 delete[] buffer;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01008733}
8734
8735
Steve Blocka7e24c12009-10-30 11:49:00 +00008736THREADED_TEST(ToArrayIndex) {
Steve Blocka7e24c12009-10-30 11:49:00 +00008737 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008738 v8::Isolate* isolate = context->GetIsolate();
8739 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00008740
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008741 v8::Local<String> str = v8_str("42");
8742 v8::MaybeLocal<v8::Uint32> index = str->ToArrayIndex(context.local());
Steve Blocka7e24c12009-10-30 11:49:00 +00008743 CHECK(!index.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008744 CHECK_EQ(42.0,
8745 index.ToLocalChecked()->Uint32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00008746 str = v8_str("42asdf");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008747 index = str->ToArrayIndex(context.local());
Steve Blocka7e24c12009-10-30 11:49:00 +00008748 CHECK(index.IsEmpty());
8749 str = v8_str("-42");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008750 index = str->ToArrayIndex(context.local());
Steve Blocka7e24c12009-10-30 11:49:00 +00008751 CHECK(index.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008752 str = v8_str("4294967294");
8753 index = str->ToArrayIndex(context.local());
Steve Blocka7e24c12009-10-30 11:49:00 +00008754 CHECK(!index.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008755 CHECK_EQ(4294967294.0,
8756 index.ToLocalChecked()->Uint32Value(context.local()).FromJust());
8757 v8::Local<v8::Number> num = v8::Number::New(isolate, 1);
8758 index = num->ToArrayIndex(context.local());
Steve Blocka7e24c12009-10-30 11:49:00 +00008759 CHECK(!index.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008760 CHECK_EQ(1.0,
8761 index.ToLocalChecked()->Uint32Value(context.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008762 num = v8::Number::New(isolate, -1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008763 index = num->ToArrayIndex(context.local());
Steve Blocka7e24c12009-10-30 11:49:00 +00008764 CHECK(index.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008765 v8::Local<v8::Object> obj = v8::Object::New(isolate);
8766 index = obj->ToArrayIndex(context.local());
Steve Blocka7e24c12009-10-30 11:49:00 +00008767 CHECK(index.IsEmpty());
8768}
8769
8770
8771THREADED_TEST(ErrorConstruction) {
Steve Blocka7e24c12009-10-30 11:49:00 +00008772 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008773 v8::HandleScope scope(context->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00008774
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008775 v8::Local<String> foo = v8_str("foo");
8776 v8::Local<String> message = v8_str("message");
8777 v8::Local<Value> range_error = v8::Exception::RangeError(foo);
Steve Blocka7e24c12009-10-30 11:49:00 +00008778 CHECK(range_error->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008779 CHECK(range_error.As<v8::Object>()
8780 ->Get(context.local(), message)
8781 .ToLocalChecked()
8782 ->Equals(context.local(), foo)
8783 .FromJust());
8784 v8::Local<Value> reference_error = v8::Exception::ReferenceError(foo);
Steve Blocka7e24c12009-10-30 11:49:00 +00008785 CHECK(reference_error->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008786 CHECK(reference_error.As<v8::Object>()
8787 ->Get(context.local(), message)
8788 .ToLocalChecked()
8789 ->Equals(context.local(), foo)
8790 .FromJust());
8791 v8::Local<Value> syntax_error = v8::Exception::SyntaxError(foo);
Steve Blocka7e24c12009-10-30 11:49:00 +00008792 CHECK(syntax_error->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008793 CHECK(syntax_error.As<v8::Object>()
8794 ->Get(context.local(), message)
8795 .ToLocalChecked()
8796 ->Equals(context.local(), foo)
8797 .FromJust());
8798 v8::Local<Value> type_error = v8::Exception::TypeError(foo);
Steve Blocka7e24c12009-10-30 11:49:00 +00008799 CHECK(type_error->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008800 CHECK(type_error.As<v8::Object>()
8801 ->Get(context.local(), message)
8802 .ToLocalChecked()
8803 ->Equals(context.local(), foo)
8804 .FromJust());
8805 v8::Local<Value> error = v8::Exception::Error(foo);
Steve Blocka7e24c12009-10-30 11:49:00 +00008806 CHECK(error->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008807 CHECK(error.As<v8::Object>()
8808 ->Get(context.local(), message)
8809 .ToLocalChecked()
8810 ->Equals(context.local(), foo)
8811 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00008812}
8813
8814
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008815static void ThrowV8Exception(const v8::FunctionCallbackInfo<v8::Value>& info) {
8816 ApiTestFuzzer::Fuzz();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008817 v8::Local<String> foo = v8_str("foo");
8818 v8::Local<String> message = v8_str("message");
8819 v8::Local<Value> error = v8::Exception::Error(foo);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008820 CHECK(error->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008821 v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
8822 CHECK(error.As<v8::Object>()
8823 ->Get(context, message)
8824 .ToLocalChecked()
8825 ->Equals(context, foo)
8826 .FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008827 info.GetIsolate()->ThrowException(error);
8828 info.GetReturnValue().SetUndefined();
8829}
8830
8831
8832THREADED_TEST(ExceptionCreateMessage) {
8833 LocalContext context;
8834 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008835 v8::Local<String> foo_str = v8_str("foo");
8836 v8::Local<String> message_str = v8_str("message");
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008837
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008838 context->GetIsolate()->SetCaptureStackTraceForUncaughtExceptions(true);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008839
8840 Local<v8::FunctionTemplate> fun =
8841 v8::FunctionTemplate::New(context->GetIsolate(), ThrowV8Exception);
8842 v8::Local<v8::Object> global = context->Global();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008843 CHECK(global->Set(context.local(), v8_str("throwV8Exception"),
8844 fun->GetFunction(context.local()).ToLocalChecked())
8845 .FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008846
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008847 TryCatch try_catch(context->GetIsolate());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008848 CompileRun(
8849 "function f1() {\n"
8850 " throwV8Exception();\n"
8851 "};\n"
8852 "f1();");
8853 CHECK(try_catch.HasCaught());
8854
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008855 v8::Local<v8::Value> error = try_catch.Exception();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008856 CHECK(error->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008857 CHECK(error.As<v8::Object>()
8858 ->Get(context.local(), message_str)
8859 .ToLocalChecked()
8860 ->Equals(context.local(), foo_str)
8861 .FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008862
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008863 v8::Local<v8::Message> message =
8864 v8::Exception::CreateMessage(context->GetIsolate(), error);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008865 CHECK(!message.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008866 CHECK_EQ(2, message->GetLineNumber(context.local()).FromJust());
8867 CHECK_EQ(2, message->GetStartColumn(context.local()).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008868
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008869 v8::Local<v8::StackTrace> stackTrace = message->GetStackTrace();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008870 CHECK(!stackTrace.IsEmpty());
8871 CHECK_EQ(2, stackTrace->GetFrameCount());
8872
8873 stackTrace = v8::Exception::GetStackTrace(error);
8874 CHECK(!stackTrace.IsEmpty());
8875 CHECK_EQ(2, stackTrace->GetFrameCount());
8876
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008877 context->GetIsolate()->SetCaptureStackTraceForUncaughtExceptions(false);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008878
8879 // Now check message location when SetCaptureStackTraceForUncaughtExceptions
8880 // is false.
8881 try_catch.Reset();
8882
8883 CompileRun(
8884 "function f2() {\n"
8885 " return throwV8Exception();\n"
8886 "};\n"
8887 "f2();");
8888 CHECK(try_catch.HasCaught());
8889
8890 error = try_catch.Exception();
8891 CHECK(error->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008892 CHECK(error.As<v8::Object>()
8893 ->Get(context.local(), message_str)
8894 .ToLocalChecked()
8895 ->Equals(context.local(), foo_str)
8896 .FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008897
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008898 message = v8::Exception::CreateMessage(context->GetIsolate(), error);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008899 CHECK(!message.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008900 CHECK_EQ(2, message->GetLineNumber(context.local()).FromJust());
8901 CHECK_EQ(9, message->GetStartColumn(context.local()).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04008902
8903 // Should be empty stack trace.
8904 stackTrace = message->GetStackTrace();
8905 CHECK(stackTrace.IsEmpty());
8906 CHECK(v8::Exception::GetStackTrace(error).IsEmpty());
8907}
8908
8909
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008910THREADED_TEST(ExceptionCreateMessageLength) {
8911 LocalContext context;
8912 v8::HandleScope scope(context->GetIsolate());
8913
8914 // Test that the message is not truncated.
8915 TryCatch try_catch(context->GetIsolate());
8916 CompileRun(
8917 "var message = 'm';"
8918 "while (message.length < 1000) message += message;"
8919 "throw message;");
8920 CHECK(try_catch.HasCaught());
8921
8922 CHECK_LT(1000, try_catch.Message()->Get()->Length());
8923}
8924
8925
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008926static void YGetter(Local<String> name,
8927 const v8::PropertyCallbackInfo<v8::Value>& info) {
Steve Blocka7e24c12009-10-30 11:49:00 +00008928 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008929 info.GetReturnValue().Set(v8_num(10));
Steve Blocka7e24c12009-10-30 11:49:00 +00008930}
8931
8932
8933static void YSetter(Local<String> name,
8934 Local<Value> value,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008935 const v8::PropertyCallbackInfo<void>& info) {
8936 Local<Object> this_obj = Local<Object>::Cast(info.This());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008937 v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
8938 if (this_obj->Has(context, name).FromJust())
8939 this_obj->Delete(context, name).FromJust();
8940 CHECK(this_obj->Set(context, name, value).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00008941}
8942
8943
8944THREADED_TEST(DeleteAccessor) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008945 v8::Isolate* isolate = CcTest::isolate();
8946 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008947 v8::Local<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00008948 obj->SetAccessor(v8_str("y"), YGetter, YSetter);
8949 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008950 v8::Local<v8::Object> holder =
8951 obj->NewInstance(context.local()).ToLocalChecked();
8952 CHECK(context->Global()
8953 ->Set(context.local(), v8_str("holder"), holder)
8954 .FromJust());
8955 v8::Local<Value> result =
8956 CompileRun("holder.y = 11; holder.y = 12; holder.y");
8957 CHECK_EQ(12u, result->Uint32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00008958}
8959
8960
Steve Blocka7e24c12009-10-30 11:49:00 +00008961static int trouble_nesting = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008962static void TroubleCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +00008963 ApiTestFuzzer::Fuzz();
8964 trouble_nesting++;
8965
8966 // Call a JS function that throws an uncaught exception.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008967 Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
8968 Local<v8::Object> arg_this = context->Global();
8969 Local<Value> trouble_callee =
8970 (trouble_nesting == 3)
8971 ? arg_this->Get(context, v8_str("trouble_callee")).ToLocalChecked()
8972 : arg_this->Get(context, v8_str("trouble_caller")).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00008973 CHECK(trouble_callee->IsFunction());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008974 args.GetReturnValue().Set(Function::Cast(*trouble_callee)
8975 ->Call(context, arg_this, 0, NULL)
8976 .FromMaybe(v8::Local<v8::Value>()));
Steve Blocka7e24c12009-10-30 11:49:00 +00008977}
8978
8979
8980static int report_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008981static void ApiUncaughtExceptionTestListener(v8::Local<v8::Message>,
8982 v8::Local<Value>) {
Steve Blocka7e24c12009-10-30 11:49:00 +00008983 report_count++;
8984}
8985
8986
8987// Counts uncaught exceptions, but other tests running in parallel
8988// also have uncaught exceptions.
8989TEST(ApiUncaughtException) {
8990 report_count = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +00008991 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008992 v8::Isolate* isolate = env->GetIsolate();
8993 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008994 isolate->AddMessageListener(ApiUncaughtExceptionTestListener);
Steve Blocka7e24c12009-10-30 11:49:00 +00008995
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008996 Local<v8::FunctionTemplate> fun =
8997 v8::FunctionTemplate::New(isolate, TroubleCallback);
Steve Blocka7e24c12009-10-30 11:49:00 +00008998 v8::Local<v8::Object> global = env->Global();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008999 CHECK(global->Set(env.local(), v8_str("trouble"),
9000 fun->GetFunction(env.local()).ToLocalChecked())
9001 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009002
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009003 CompileRun(
9004 "function trouble_callee() {"
9005 " var x = null;"
9006 " return x.foo;"
9007 "};"
9008 "function trouble_caller() {"
9009 " trouble();"
9010 "};");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009011 Local<Value> trouble =
9012 global->Get(env.local(), v8_str("trouble")).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00009013 CHECK(trouble->IsFunction());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009014 Local<Value> trouble_callee =
9015 global->Get(env.local(), v8_str("trouble_callee")).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00009016 CHECK(trouble_callee->IsFunction());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009017 Local<Value> trouble_caller =
9018 global->Get(env.local(), v8_str("trouble_caller")).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00009019 CHECK(trouble_caller->IsFunction());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009020 Function::Cast(*trouble_caller)
9021 ->Call(env.local(), global, 0, NULL)
9022 .FromMaybe(v8::Local<v8::Value>());
Steve Blocka7e24c12009-10-30 11:49:00 +00009023 CHECK_EQ(1, report_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009024 isolate->RemoveMessageListeners(ApiUncaughtExceptionTestListener);
Steve Blocka7e24c12009-10-30 11:49:00 +00009025}
9026
Emily Bernierd0a1eb72015-03-24 16:35:39 -04009027
Leon Clarke4515c472010-02-03 11:58:03 +00009028static const char* script_resource_name = "ExceptionInNativeScript.js";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009029static void ExceptionInNativeScriptTestListener(v8::Local<v8::Message> message,
9030 v8::Local<Value>) {
9031 v8::Local<v8::Value> name_val = message->GetScriptOrigin().ResourceName();
Leon Clarke4515c472010-02-03 11:58:03 +00009032 CHECK(!name_val.IsEmpty() && name_val->IsString());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009033 v8::String::Utf8Value name(message->GetScriptOrigin().ResourceName());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009034 CHECK_EQ(0, strcmp(script_resource_name, *name));
9035 v8::Local<v8::Context> context =
9036 v8::Isolate::GetCurrent()->GetCurrentContext();
9037 CHECK_EQ(3, message->GetLineNumber(context).FromJust());
9038 v8::String::Utf8Value source_line(
9039 message->GetSourceLine(context).ToLocalChecked());
9040 CHECK_EQ(0, strcmp(" new o.foo();", *source_line));
Leon Clarke4515c472010-02-03 11:58:03 +00009041}
9042
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009043
Leon Clarke4515c472010-02-03 11:58:03 +00009044TEST(ExceptionInNativeScript) {
Leon Clarke4515c472010-02-03 11:58:03 +00009045 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009046 v8::Isolate* isolate = env->GetIsolate();
9047 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009048 isolate->AddMessageListener(ExceptionInNativeScriptTestListener);
Leon Clarke4515c472010-02-03 11:58:03 +00009049
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009050 Local<v8::FunctionTemplate> fun =
9051 v8::FunctionTemplate::New(isolate, TroubleCallback);
Leon Clarke4515c472010-02-03 11:58:03 +00009052 v8::Local<v8::Object> global = env->Global();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009053 CHECK(global->Set(env.local(), v8_str("trouble"),
9054 fun->GetFunction(env.local()).ToLocalChecked())
9055 .FromJust());
Leon Clarke4515c472010-02-03 11:58:03 +00009056
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009057 CompileRunWithOrigin(
9058 "function trouble() {\n"
9059 " var o = {};\n"
9060 " new o.foo();\n"
9061 "};",
9062 script_resource_name);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009063 Local<Value> trouble =
9064 global->Get(env.local(), v8_str("trouble")).ToLocalChecked();
Leon Clarke4515c472010-02-03 11:58:03 +00009065 CHECK(trouble->IsFunction());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009066 CHECK(Function::Cast(*trouble)->Call(env.local(), global, 0, NULL).IsEmpty());
9067 isolate->RemoveMessageListeners(ExceptionInNativeScriptTestListener);
Leon Clarke4515c472010-02-03 11:58:03 +00009068}
9069
Steve Blocka7e24c12009-10-30 11:49:00 +00009070
9071TEST(CompilationErrorUsingTryCatchHandler) {
Steve Blocka7e24c12009-10-30 11:49:00 +00009072 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009073 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009074 v8::TryCatch try_catch(env->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009075 v8_compile("This doesn't &*&@#$&*^ compile.");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009076 CHECK(*try_catch.Exception());
Steve Blocka7e24c12009-10-30 11:49:00 +00009077 CHECK(try_catch.HasCaught());
9078}
9079
9080
9081TEST(TryCatchFinallyUsingTryCatchHandler) {
Steve Blocka7e24c12009-10-30 11:49:00 +00009082 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009083 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009084 v8::TryCatch try_catch(env->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009085 CompileRun("try { throw ''; } catch (e) {}");
Steve Blocka7e24c12009-10-30 11:49:00 +00009086 CHECK(!try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009087 CompileRun("try { throw ''; } finally {}");
Steve Blocka7e24c12009-10-30 11:49:00 +00009088 CHECK(try_catch.HasCaught());
9089 try_catch.Reset();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009090 CompileRun(
9091 "(function() {"
9092 "try { throw ''; } finally { return; }"
9093 "})()");
Steve Blocka7e24c12009-10-30 11:49:00 +00009094 CHECK(!try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009095 CompileRun(
9096 "(function()"
9097 " { try { throw ''; } finally { throw 0; }"
9098 "})()");
Steve Blocka7e24c12009-10-30 11:49:00 +00009099 CHECK(try_catch.HasCaught());
9100}
9101
9102
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009103void CEvaluate(const v8::FunctionCallbackInfo<v8::Value>& args) {
9104 v8::HandleScope scope(args.GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009105 CompileRun(args[0]
9106 ->ToString(args.GetIsolate()->GetCurrentContext())
9107 .ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009108}
9109
9110
9111TEST(TryCatchFinallyStoresMessageUsingTryCatchHandler) {
9112 v8::Isolate* isolate = CcTest::isolate();
9113 v8::HandleScope scope(isolate);
9114 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
9115 templ->Set(v8_str("CEvaluate"),
9116 v8::FunctionTemplate::New(isolate, CEvaluate));
9117 LocalContext context(0, templ);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009118 v8::TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009119 CompileRun("try {"
9120 " CEvaluate('throw 1;');"
9121 "} finally {"
9122 "}");
9123 CHECK(try_catch.HasCaught());
9124 CHECK(!try_catch.Message().IsEmpty());
9125 String::Utf8Value exception_value(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009126 CHECK_EQ(0, strcmp(*exception_value, "1"));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009127 try_catch.Reset();
9128 CompileRun("try {"
9129 " CEvaluate('throw 1;');"
9130 "} finally {"
9131 " throw 2;"
9132 "}");
9133 CHECK(try_catch.HasCaught());
9134 CHECK(!try_catch.Message().IsEmpty());
9135 String::Utf8Value finally_exception_value(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009136 CHECK_EQ(0, strcmp(*finally_exception_value, "2"));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009137}
9138
9139
9140// For use within the TestSecurityHandler() test.
9141static bool g_security_callback_result = false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009142static bool SecurityTestCallback(Local<v8::Context> accessing_context,
Ben Murdoch097c5b22016-05-18 11:27:45 +01009143 Local<v8::Object> accessed_object,
9144 Local<v8::Value> data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009145 printf("a\n");
Ben Murdoch097c5b22016-05-18 11:27:45 +01009146 CHECK(!data.IsEmpty() && data->IsInt32());
9147 CHECK_EQ(42, data->Int32Value(accessing_context).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009148 return g_security_callback_result;
9149}
9150
9151
Steve Blocka7e24c12009-10-30 11:49:00 +00009152// SecurityHandler can't be run twice
9153TEST(SecurityHandler) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009154 v8::Isolate* isolate = CcTest::isolate();
9155 v8::HandleScope scope0(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009156 v8::Local<v8::ObjectTemplate> global_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009157 v8::ObjectTemplate::New(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +01009158 global_template->SetAccessCheckCallback(SecurityTestCallback, v8_num(42));
Steve Blocka7e24c12009-10-30 11:49:00 +00009159 // Create an environment
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009160 v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
Steve Blocka7e24c12009-10-30 11:49:00 +00009161 context0->Enter();
9162
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009163 v8::Local<v8::Object> global0 = context0->Global();
9164 v8::Local<Script> script0 = v8_compile("foo = 111");
9165 script0->Run(context0).ToLocalChecked();
9166 CHECK(global0->Set(context0, v8_str("0"), v8_num(999)).FromJust());
9167 v8::Local<Value> foo0 =
9168 global0->Get(context0, v8_str("foo")).ToLocalChecked();
9169 CHECK_EQ(111, foo0->Int32Value(context0).FromJust());
9170 v8::Local<Value> z0 = global0->Get(context0, v8_str("0")).ToLocalChecked();
9171 CHECK_EQ(999, z0->Int32Value(context0).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009172
9173 // Create another environment, should fail security checks.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009174 v8::HandleScope scope1(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00009175
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009176 v8::Local<Context> context1 = Context::New(isolate, NULL, global_template);
Steve Blocka7e24c12009-10-30 11:49:00 +00009177 context1->Enter();
9178
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009179 v8::Local<v8::Object> global1 = context1->Global();
9180 global1->Set(context1, v8_str("othercontext"), global0).FromJust();
Steve Blocka7e24c12009-10-30 11:49:00 +00009181 // This set will fail the security check.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009182 v8::Local<Script> script1 =
9183 v8_compile("othercontext.foo = 222; othercontext[0] = 888;");
9184 CHECK(script1->Run(context1).IsEmpty());
9185 g_security_callback_result = true;
Steve Blocka7e24c12009-10-30 11:49:00 +00009186 // This read will pass the security check.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009187 v8::Local<Value> foo1 =
9188 global0->Get(context1, v8_str("foo")).ToLocalChecked();
9189 CHECK_EQ(111, foo1->Int32Value(context0).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009190 // This read will pass the security check.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009191 v8::Local<Value> z1 = global0->Get(context1, v8_str("0")).ToLocalChecked();
9192 CHECK_EQ(999, z1->Int32Value(context1).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009193
9194 // Create another environment, should pass security checks.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009195 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009196 v8::HandleScope scope2(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00009197 LocalContext context2;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009198 v8::Local<v8::Object> global2 = context2->Global();
9199 CHECK(global2->Set(context2.local(), v8_str("othercontext"), global0)
9200 .FromJust());
9201 v8::Local<Script> script2 =
Steve Blocka7e24c12009-10-30 11:49:00 +00009202 v8_compile("othercontext.foo = 333; othercontext[0] = 888;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009203 script2->Run(context2.local()).ToLocalChecked();
9204 v8::Local<Value> foo2 =
9205 global0->Get(context2.local(), v8_str("foo")).ToLocalChecked();
9206 CHECK_EQ(333, foo2->Int32Value(context2.local()).FromJust());
9207 v8::Local<Value> z2 =
9208 global0->Get(context2.local(), v8_str("0")).ToLocalChecked();
9209 CHECK_EQ(888, z2->Int32Value(context2.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009210 }
9211
9212 context1->Exit();
Steve Blocka7e24c12009-10-30 11:49:00 +00009213 context0->Exit();
Steve Blocka7e24c12009-10-30 11:49:00 +00009214}
9215
9216
9217THREADED_TEST(SecurityChecks) {
Steve Blocka7e24c12009-10-30 11:49:00 +00009218 LocalContext env1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009219 v8::HandleScope handle_scope(env1->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009220 v8::Local<Context> env2 = Context::New(env1->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00009221
9222 Local<Value> foo = v8_str("foo");
9223 Local<Value> bar = v8_str("bar");
9224
9225 // Set to the same domain.
9226 env1->SetSecurityToken(foo);
9227
9228 // Create a function in env1.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009229 CompileRun("spy=function(){return spy;}");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009230 Local<Value> spy =
9231 env1->Global()->Get(env1.local(), v8_str("spy")).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00009232 CHECK(spy->IsFunction());
9233
9234 // Create another function accessing global objects.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009235 CompileRun("spy2=function(){return new this.Array();}");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009236 Local<Value> spy2 =
9237 env1->Global()->Get(env1.local(), v8_str("spy2")).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00009238 CHECK(spy2->IsFunction());
9239
9240 // Switch to env2 in the same domain and invoke spy on env2.
9241 {
9242 env2->SetSecurityToken(foo);
9243 // Enter env2
9244 Context::Scope scope_env2(env2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009245 Local<Value> result = Function::Cast(*spy)
9246 ->Call(env2, env2->Global(), 0, NULL)
9247 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00009248 CHECK(result->IsFunction());
9249 }
9250
9251 {
9252 env2->SetSecurityToken(bar);
9253 Context::Scope scope_env2(env2);
9254
9255 // Call cross_domain_call, it should throw an exception
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009256 v8::TryCatch try_catch(env1->GetIsolate());
9257 CHECK(Function::Cast(*spy2)->Call(env2, env2->Global(), 0, NULL).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00009258 CHECK(try_catch.HasCaught());
9259 }
Steve Blocka7e24c12009-10-30 11:49:00 +00009260}
9261
9262
9263// Regression test case for issue 1183439.
9264THREADED_TEST(SecurityChecksForPrototypeChain) {
Steve Blocka7e24c12009-10-30 11:49:00 +00009265 LocalContext current;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009266 v8::HandleScope scope(current->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009267 v8::Local<Context> other = Context::New(current->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00009268
9269 // Change context to be able to get to the Object function in the
9270 // other context without hitting the security checks.
9271 v8::Local<Value> other_object;
9272 { Context::Scope scope(other);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009273 other_object =
9274 other->Global()->Get(other, v8_str("Object")).ToLocalChecked();
9275 CHECK(other->Global()->Set(other, v8_num(42), v8_num(87)).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009276 }
9277
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009278 CHECK(current->Global()
9279 ->Set(current.local(), v8_str("other"), other->Global())
9280 .FromJust());
9281 CHECK(v8_compile("other")
9282 ->Run(current.local())
9283 .ToLocalChecked()
9284 ->Equals(current.local(), other->Global())
9285 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009286
9287 // Make sure the security check fails here and we get an undefined
9288 // result instead of getting the Object function. Repeat in a loop
9289 // to make sure to exercise the IC code.
9290 v8::Local<Script> access_other0 = v8_compile("other.Object");
9291 v8::Local<Script> access_other1 = v8_compile("other[42]");
9292 for (int i = 0; i < 5; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009293 CHECK(access_other0->Run(current.local()).IsEmpty());
9294 CHECK(access_other1->Run(current.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00009295 }
9296
9297 // Create an object that has 'other' in its prototype chain and make
9298 // sure we cannot access the Object function indirectly through
9299 // that. Repeat in a loop to make sure to exercise the IC code.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009300 v8_compile(
9301 "function F() { };"
9302 "F.prototype = other;"
9303 "var f = new F();")
9304 ->Run(current.local())
9305 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00009306 v8::Local<Script> access_f0 = v8_compile("f.Object");
9307 v8::Local<Script> access_f1 = v8_compile("f[42]");
9308 for (int j = 0; j < 5; j++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009309 CHECK(access_f0->Run(current.local()).IsEmpty());
9310 CHECK(access_f1->Run(current.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00009311 }
9312
9313 // Now it gets hairy: Set the prototype for the other global object
9314 // to be the current global object. The prototype chain for 'f' now
9315 // goes through 'other' but ends up in the current global object.
9316 { Context::Scope scope(other);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009317 CHECK(other->Global()
9318 ->Set(other, v8_str("__proto__"), current->Global())
9319 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009320 }
9321 // Set a named and an index property on the current global
9322 // object. To force the lookup to go through the other global object,
9323 // the properties must not exist in the other global object.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009324 CHECK(current->Global()
9325 ->Set(current.local(), v8_str("foo"), v8_num(100))
9326 .FromJust());
9327 CHECK(current->Global()
9328 ->Set(current.local(), v8_num(99), v8_num(101))
9329 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009330 // Try to read the properties from f and make sure that the access
9331 // gets stopped by the security checks on the other global object.
9332 Local<Script> access_f2 = v8_compile("f.foo");
9333 Local<Script> access_f3 = v8_compile("f[99]");
9334 for (int k = 0; k < 5; k++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009335 CHECK(access_f2->Run(current.local()).IsEmpty());
9336 CHECK(access_f3->Run(current.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00009337 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009338}
9339
9340
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009341static bool security_check_with_gc_called;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009342
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009343static bool SecurityTestCallbackWithGC(Local<v8::Context> accessing_context,
Ben Murdoch097c5b22016-05-18 11:27:45 +01009344 Local<v8::Object> accessed_object,
9345 Local<v8::Value> data) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009346 CcTest::heap()->CollectAllGarbage();
9347 security_check_with_gc_called = true;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009348 return true;
9349}
9350
9351
9352TEST(SecurityTestGCAllowed) {
9353 v8::Isolate* isolate = CcTest::isolate();
9354 v8::HandleScope handle_scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009355 v8::Local<v8::ObjectTemplate> object_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009356 v8::ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009357 object_template->SetAccessCheckCallback(SecurityTestCallbackWithGC);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009358
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009359 v8::Local<Context> context = Context::New(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009360 v8::Context::Scope context_scope(context);
9361
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009362 CHECK(context->Global()
9363 ->Set(context, v8_str("obj"),
9364 object_template->NewInstance(context).ToLocalChecked())
9365 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009366
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009367 security_check_with_gc_called = false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009368 CompileRun("obj[0] = new String(1002);");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009369 CHECK(security_check_with_gc_called);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009370
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009371 security_check_with_gc_called = false;
9372 CHECK(CompileRun("obj[0]")
9373 ->ToString(context)
9374 .ToLocalChecked()
9375 ->Equals(context, v8_str("1002"))
9376 .FromJust());
9377 CHECK(security_check_with_gc_called);
Steve Blocka7e24c12009-10-30 11:49:00 +00009378}
9379
9380
9381THREADED_TEST(CrossDomainDelete) {
Steve Blocka7e24c12009-10-30 11:49:00 +00009382 LocalContext env1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009383 v8::HandleScope handle_scope(env1->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009384 v8::Local<Context> env2 = Context::New(env1->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00009385
9386 Local<Value> foo = v8_str("foo");
9387 Local<Value> bar = v8_str("bar");
9388
9389 // Set to the same domain.
9390 env1->SetSecurityToken(foo);
9391 env2->SetSecurityToken(foo);
9392
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009393 CHECK(
9394 env1->Global()->Set(env1.local(), v8_str("prop"), v8_num(3)).FromJust());
9395 CHECK(env2->Global()->Set(env2, v8_str("env1"), env1->Global()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009396
9397 // Change env2 to a different domain and delete env1.prop.
9398 env2->SetSecurityToken(bar);
9399 {
9400 Context::Scope scope_env2(env2);
9401 Local<Value> result =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009402 CompileRun("delete env1.prop");
9403 CHECK(result.IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00009404 }
9405
9406 // Check that env1.prop still exists.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009407 Local<Value> v =
9408 env1->Global()->Get(env1.local(), v8_str("prop")).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00009409 CHECK(v->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009410 CHECK_EQ(3, v->Int32Value(env1.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009411}
9412
9413
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009414THREADED_TEST(CrossDomainPropertyIsEnumerable) {
Steve Blocka7e24c12009-10-30 11:49:00 +00009415 LocalContext env1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009416 v8::HandleScope handle_scope(env1->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009417 v8::Local<Context> env2 = Context::New(env1->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00009418
9419 Local<Value> foo = v8_str("foo");
9420 Local<Value> bar = v8_str("bar");
9421
9422 // Set to the same domain.
9423 env1->SetSecurityToken(foo);
9424 env2->SetSecurityToken(foo);
9425
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009426 CHECK(
9427 env1->Global()->Set(env1.local(), v8_str("prop"), v8_num(3)).FromJust());
9428 CHECK(env2->Global()->Set(env2, v8_str("env1"), env1->Global()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009429
9430 // env1.prop is enumerable in env2.
9431 Local<String> test = v8_str("propertyIsEnumerable.call(env1, 'prop')");
9432 {
9433 Context::Scope scope_env2(env2);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009434 Local<Value> result = CompileRun(test);
Steve Blocka7e24c12009-10-30 11:49:00 +00009435 CHECK(result->IsTrue());
9436 }
9437
9438 // Change env2 to a different domain and test again.
9439 env2->SetSecurityToken(bar);
9440 {
9441 Context::Scope scope_env2(env2);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009442 Local<Value> result = CompileRun(test);
9443 CHECK(result.IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00009444 }
Steve Blocka7e24c12009-10-30 11:49:00 +00009445}
9446
9447
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009448THREADED_TEST(CrossDomainFor) {
Steve Blocka7e24c12009-10-30 11:49:00 +00009449 LocalContext env1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009450 v8::HandleScope handle_scope(env1->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009451 v8::Local<Context> env2 = Context::New(env1->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00009452
9453 Local<Value> foo = v8_str("foo");
9454 Local<Value> bar = v8_str("bar");
9455
9456 // Set to the same domain.
9457 env1->SetSecurityToken(foo);
9458 env2->SetSecurityToken(foo);
9459
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009460 CHECK(
9461 env1->Global()->Set(env1.local(), v8_str("prop"), v8_num(3)).FromJust());
9462 CHECK(env2->Global()->Set(env2, v8_str("env1"), env1->Global()).FromJust());
9463
9464 // Change env2 to a different domain and set env1's global object
9465 // as the __proto__ of an object in env2 and enumerate properties
9466 // in for-in. It shouldn't enumerate properties on env1's global
9467 // object. It shouldn't throw either, just silently ignore them.
9468 env2->SetSecurityToken(bar);
9469 {
9470 Context::Scope scope_env2(env2);
9471 Local<Value> result = CompileRun(
9472 "(function() {"
9473 " try {"
9474 " for (var p in env1) {"
9475 " if (p == 'prop') return false;"
9476 " }"
9477 " return true;"
9478 " } catch (e) {"
9479 " return false;"
9480 " }"
9481 "})()");
9482 CHECK(result->IsTrue());
9483 }
9484}
9485
9486
9487THREADED_TEST(CrossDomainForInOnPrototype) {
9488 LocalContext env1;
9489 v8::HandleScope handle_scope(env1->GetIsolate());
9490 v8::Local<Context> env2 = Context::New(env1->GetIsolate());
9491
9492 Local<Value> foo = v8_str("foo");
9493 Local<Value> bar = v8_str("bar");
9494
9495 // Set to the same domain.
9496 env1->SetSecurityToken(foo);
9497 env2->SetSecurityToken(foo);
9498
9499 CHECK(
9500 env1->Global()->Set(env1.local(), v8_str("prop"), v8_num(3)).FromJust());
9501 CHECK(env2->Global()->Set(env2, v8_str("env1"), env1->Global()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009502
9503 // Change env2 to a different domain and set env1's global object
9504 // as the __proto__ of an object in env2 and enumerate properties
9505 // in for-in. It shouldn't enumerate properties on env1's global
9506 // object.
9507 env2->SetSecurityToken(bar);
9508 {
9509 Context::Scope scope_env2(env2);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009510 Local<Value> result = CompileRun(
9511 "(function() {"
9512 " var obj = { '__proto__': env1 };"
9513 " try {"
9514 " for (var p in obj) {"
9515 " if (p == 'prop') return false;"
9516 " }"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009517 " return true;"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009518 " } catch (e) {"
9519 " return false;"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009520 " }"
9521 "})()");
Steve Blocka7e24c12009-10-30 11:49:00 +00009522 CHECK(result->IsTrue());
9523 }
Steve Blocka7e24c12009-10-30 11:49:00 +00009524}
9525
9526
9527TEST(ContextDetachGlobal) {
Steve Blocka7e24c12009-10-30 11:49:00 +00009528 LocalContext env1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009529 v8::HandleScope handle_scope(env1->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009530 v8::Local<Context> env2 = Context::New(env1->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +00009531
Steve Blocka7e24c12009-10-30 11:49:00 +00009532
9533 Local<Value> foo = v8_str("foo");
9534
9535 // Set to the same domain.
9536 env1->SetSecurityToken(foo);
9537 env2->SetSecurityToken(foo);
9538
9539 // Enter env2
9540 env2->Enter();
9541
Andrei Popescu74b3c142010-03-29 12:03:09 +01009542 // Create a function in env2 and add a reference to it in env1.
Steve Blocka7e24c12009-10-30 11:49:00 +00009543 Local<v8::Object> global2 = env2->Global();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009544 CHECK(global2->Set(env2, v8_str("prop"),
9545 v8::Integer::New(env2->GetIsolate(), 1))
9546 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009547 CompileRun("function getProp() {return prop;}");
9548
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009549 CHECK(env1->Global()
9550 ->Set(env1.local(), v8_str("getProp"),
9551 global2->Get(env2, v8_str("getProp")).ToLocalChecked())
9552 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009553
Andrei Popescu74b3c142010-03-29 12:03:09 +01009554 // Detach env2's global, and reuse the global object of env2
Steve Blocka7e24c12009-10-30 11:49:00 +00009555 env2->Exit();
9556 env2->DetachGlobal();
Steve Blocka7e24c12009-10-30 11:49:00 +00009557
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009558 v8::Local<Context> env3 = Context::New(
9559 env1->GetIsolate(), 0, v8::Local<v8::ObjectTemplate>(), global2);
Steve Blocka7e24c12009-10-30 11:49:00 +00009560 env3->SetSecurityToken(v8_str("bar"));
Steve Blocka7e24c12009-10-30 11:49:00 +00009561
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009562 env3->Enter();
Steve Blocka7e24c12009-10-30 11:49:00 +00009563 Local<v8::Object> global3 = env3->Global();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009564 CHECK(global2->Equals(env3, global3).FromJust());
9565 CHECK(global3->Get(env3, v8_str("prop")).ToLocalChecked()->IsUndefined());
9566 CHECK(global3->Get(env3, v8_str("getProp")).ToLocalChecked()->IsUndefined());
9567 CHECK(global3->Set(env3, v8_str("prop"),
9568 v8::Integer::New(env3->GetIsolate(), -1))
9569 .FromJust());
9570 CHECK(global3->Set(env3, v8_str("prop2"),
9571 v8::Integer::New(env3->GetIsolate(), 2))
9572 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009573 env3->Exit();
9574
9575 // Call getProp in env1, and it should return the value 1
9576 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009577 Local<v8::Object> global1 = env1->Global();
9578 Local<Value> get_prop =
9579 global1->Get(env1.local(), v8_str("getProp")).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00009580 CHECK(get_prop->IsFunction());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009581 v8::TryCatch try_catch(env1->GetIsolate());
9582 Local<Value> r = Function::Cast(*get_prop)
9583 ->Call(env1.local(), global1, 0, NULL)
9584 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00009585 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009586 CHECK_EQ(1, r->Int32Value(env1.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009587 }
9588
9589 // Check that env3 is not accessible from env1
9590 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009591 v8::MaybeLocal<Value> r = global3->Get(env1.local(), v8_str("prop2"));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009592 CHECK(r.IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00009593 }
Steve Blocka7e24c12009-10-30 11:49:00 +00009594}
9595
9596
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009597TEST(DetachGlobal) {
Andrei Popescu74b3c142010-03-29 12:03:09 +01009598 LocalContext env1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009599 v8::HandleScope scope(env1->GetIsolate());
Andrei Popescu74b3c142010-03-29 12:03:09 +01009600
9601 // Create second environment.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009602 v8::Local<Context> env2 = Context::New(env1->GetIsolate());
Andrei Popescu74b3c142010-03-29 12:03:09 +01009603
9604 Local<Value> foo = v8_str("foo");
9605
9606 // Set same security token for env1 and env2.
9607 env1->SetSecurityToken(foo);
9608 env2->SetSecurityToken(foo);
9609
9610 // Create a property on the global object in env2.
9611 {
9612 v8::Context::Scope scope(env2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009613 CHECK(env2->Global()
9614 ->Set(env2, v8_str("p"), v8::Integer::New(env2->GetIsolate(), 42))
9615 .FromJust());
Andrei Popescu74b3c142010-03-29 12:03:09 +01009616 }
9617
9618 // Create a reference to env2 global from env1 global.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009619 CHECK(env1->Global()
9620 ->Set(env1.local(), v8_str("other"), env2->Global())
9621 .FromJust());
Andrei Popescu74b3c142010-03-29 12:03:09 +01009622
9623 // Check that we have access to other.p in env2 from env1.
9624 Local<Value> result = CompileRun("other.p");
9625 CHECK(result->IsInt32());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009626 CHECK_EQ(42, result->Int32Value(env1.local()).FromJust());
Andrei Popescu74b3c142010-03-29 12:03:09 +01009627
9628 // Hold on to global from env2 and detach global from env2.
9629 Local<v8::Object> global2 = env2->Global();
9630 env2->DetachGlobal();
9631
9632 // Check that the global has been detached. No other.p property can
9633 // be found.
9634 result = CompileRun("other.p");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009635 CHECK(result.IsEmpty());
Andrei Popescu74b3c142010-03-29 12:03:09 +01009636
9637 // Reuse global2 for env3.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009638 v8::Local<Context> env3 = Context::New(
9639 env1->GetIsolate(), 0, v8::Local<v8::ObjectTemplate>(), global2);
9640 CHECK(global2->Equals(env1.local(), env3->Global()).FromJust());
Andrei Popescu74b3c142010-03-29 12:03:09 +01009641
9642 // Start by using the same security token for env3 as for env1 and env2.
9643 env3->SetSecurityToken(foo);
9644
9645 // Create a property on the global object in env3.
9646 {
9647 v8::Context::Scope scope(env3);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009648 CHECK(env3->Global()
9649 ->Set(env3, v8_str("p"), v8::Integer::New(env3->GetIsolate(), 24))
9650 .FromJust());
Andrei Popescu74b3c142010-03-29 12:03:09 +01009651 }
9652
9653 // Check that other.p is now the property in env3 and that we have access.
9654 result = CompileRun("other.p");
9655 CHECK(result->IsInt32());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009656 CHECK_EQ(24, result->Int32Value(env3).FromJust());
Andrei Popescu74b3c142010-03-29 12:03:09 +01009657
9658 // Change security token for env3 to something different from env1 and env2.
9659 env3->SetSecurityToken(v8_str("bar"));
9660
9661 // Check that we do not have access to other.p in env1. |other| is now
9662 // the global object for env3 which has a different security token,
9663 // so access should be blocked.
9664 result = CompileRun("other.p");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009665 CHECK(result.IsEmpty());
9666}
Andrei Popescu74b3c142010-03-29 12:03:09 +01009667
Andrei Popescu74b3c142010-03-29 12:03:09 +01009668
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009669void GetThisX(const v8::FunctionCallbackInfo<v8::Value>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009670 v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009671 info.GetReturnValue().Set(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009672 context->Global()->Get(context, v8_str("x")).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009673}
Andrei Popescu74b3c142010-03-29 12:03:09 +01009674
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009675
9676TEST(DetachedAccesses) {
9677 LocalContext env1;
9678 v8::HandleScope scope(env1->GetIsolate());
9679
9680 // Create second environment.
9681 Local<ObjectTemplate> inner_global_template =
9682 FunctionTemplate::New(env1->GetIsolate())->InstanceTemplate();
9683 inner_global_template ->SetAccessorProperty(
9684 v8_str("this_x"), FunctionTemplate::New(env1->GetIsolate(), GetThisX));
9685 v8::Local<Context> env2 =
9686 Context::New(env1->GetIsolate(), NULL, inner_global_template);
9687
9688 Local<Value> foo = v8_str("foo");
9689
9690 // Set same security token for env1 and env2.
9691 env1->SetSecurityToken(foo);
9692 env2->SetSecurityToken(foo);
9693
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009694 CHECK(env1->Global()
9695 ->Set(env1.local(), v8_str("x"), v8_str("env1_x"))
9696 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009697
9698 {
9699 v8::Context::Scope scope(env2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009700 CHECK(env2->Global()->Set(env2, v8_str("x"), v8_str("env2_x")).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009701 CompileRun(
9702 "function bound_x() { return x; }"
9703 "function get_x() { return this.x; }"
9704 "function get_x_w() { return (function() {return this.x;})(); }");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009705 CHECK(env1->Global()
9706 ->Set(env1.local(), v8_str("bound_x"), CompileRun("bound_x"))
9707 .FromJust());
9708 CHECK(env1->Global()
9709 ->Set(env1.local(), v8_str("get_x"), CompileRun("get_x"))
9710 .FromJust());
9711 CHECK(env1->Global()
9712 ->Set(env1.local(), v8_str("get_x_w"), CompileRun("get_x_w"))
9713 .FromJust());
9714 env1->Global()
9715 ->Set(env1.local(), v8_str("this_x"),
9716 CompileRun("Object.getOwnPropertyDescriptor(this, 'this_x').get"))
9717 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009718 }
9719
9720 Local<Object> env2_global = env2->Global();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009721 env2->DetachGlobal();
9722
9723 Local<Value> result;
9724 result = CompileRun("bound_x()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009725 CHECK(v8_str("env2_x")->Equals(env1.local(), result).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009726 result = CompileRun("get_x()");
9727 CHECK(result.IsEmpty());
9728 result = CompileRun("get_x_w()");
9729 CHECK(result.IsEmpty());
9730 result = CompileRun("this_x()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009731 CHECK(v8_str("env2_x")->Equals(env1.local(), result).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009732
9733 // Reattach env2's proxy
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009734 env2 = Context::New(env1->GetIsolate(), 0, v8::Local<v8::ObjectTemplate>(),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009735 env2_global);
9736 env2->SetSecurityToken(foo);
9737 {
9738 v8::Context::Scope scope(env2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009739 CHECK(env2->Global()->Set(env2, v8_str("x"), v8_str("env3_x")).FromJust());
9740 CHECK(env2->Global()->Set(env2, v8_str("env1"), env1->Global()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009741 result = CompileRun(
9742 "results = [];"
9743 "for (var i = 0; i < 4; i++ ) {"
9744 " results.push(env1.bound_x());"
9745 " results.push(env1.get_x());"
9746 " results.push(env1.get_x_w());"
9747 " results.push(env1.this_x());"
9748 "}"
9749 "results");
9750 Local<v8::Array> results = Local<v8::Array>::Cast(result);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009751 CHECK_EQ(16u, results->Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009752 for (int i = 0; i < 16; i += 4) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009753 CHECK(v8_str("env2_x")
9754 ->Equals(env2, results->Get(env2, i + 0).ToLocalChecked())
9755 .FromJust());
9756 CHECK(v8_str("env1_x")
9757 ->Equals(env2, results->Get(env2, i + 1).ToLocalChecked())
9758 .FromJust());
9759 CHECK(v8_str("env3_x")
9760 ->Equals(env2, results->Get(env2, i + 2).ToLocalChecked())
9761 .FromJust());
9762 CHECK(v8_str("env2_x")
9763 ->Equals(env2, results->Get(env2, i + 3).ToLocalChecked())
9764 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009765 }
9766 }
9767
9768 result = CompileRun(
9769 "results = [];"
9770 "for (var i = 0; i < 4; i++ ) {"
9771 " results.push(bound_x());"
9772 " results.push(get_x());"
9773 " results.push(get_x_w());"
9774 " results.push(this_x());"
9775 "}"
9776 "results");
9777 Local<v8::Array> results = Local<v8::Array>::Cast(result);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009778 CHECK_EQ(16u, results->Length());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009779 for (int i = 0; i < 16; i += 4) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009780 CHECK(v8_str("env2_x")
9781 ->Equals(env1.local(),
9782 results->Get(env1.local(), i + 0).ToLocalChecked())
9783 .FromJust());
9784 CHECK(v8_str("env3_x")
9785 ->Equals(env1.local(),
9786 results->Get(env1.local(), i + 1).ToLocalChecked())
9787 .FromJust());
9788 CHECK(v8_str("env3_x")
9789 ->Equals(env1.local(),
9790 results->Get(env1.local(), i + 2).ToLocalChecked())
9791 .FromJust());
9792 CHECK(v8_str("env2_x")
9793 ->Equals(env1.local(),
9794 results->Get(env1.local(), i + 3).ToLocalChecked())
9795 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009796 }
9797
9798 result = CompileRun(
9799 "results = [];"
9800 "for (var i = 0; i < 4; i++ ) {"
9801 " results.push(this.bound_x());"
9802 " results.push(this.get_x());"
9803 " results.push(this.get_x_w());"
9804 " results.push(this.this_x());"
9805 "}"
9806 "results");
9807 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("env1_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 }
Andrei Popescu74b3c142010-03-29 12:03:09 +01009827}
9828
9829
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009830static bool allowed_access = false;
9831static bool AccessBlocker(Local<v8::Context> accessing_context,
Ben Murdoch097c5b22016-05-18 11:27:45 +01009832 Local<v8::Object> accessed_object,
9833 Local<v8::Value> data) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009834 v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
9835 return context->Global()->Equals(context, accessed_object).FromJust() ||
9836 allowed_access;
Steve Blocka7e24c12009-10-30 11:49:00 +00009837}
9838
9839
9840static int g_echo_value = -1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009841
9842
9843static void EchoGetter(
9844 Local<String> name,
9845 const v8::PropertyCallbackInfo<v8::Value>& info) {
9846 info.GetReturnValue().Set(v8_num(g_echo_value));
Steve Blocka7e24c12009-10-30 11:49:00 +00009847}
9848
9849
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009850static void EchoSetter(Local<String> name, Local<Value> value,
9851 const v8::PropertyCallbackInfo<void>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +00009852 if (value->IsNumber())
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009853 g_echo_value =
9854 value->Int32Value(args.GetIsolate()->GetCurrentContext()).FromJust();
Steve Blocka7e24c12009-10-30 11:49:00 +00009855}
9856
9857
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009858static void UnreachableGetter(
9859 Local<String> name,
9860 const v8::PropertyCallbackInfo<v8::Value>& info) {
Steve Blocka7e24c12009-10-30 11:49:00 +00009861 CHECK(false); // This function should not be called..
Steve Blocka7e24c12009-10-30 11:49:00 +00009862}
9863
9864
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009865static void UnreachableSetter(Local<String>,
9866 Local<Value>,
9867 const v8::PropertyCallbackInfo<void>&) {
Steve Blocka7e24c12009-10-30 11:49:00 +00009868 CHECK(false); // This function should nto be called.
9869}
9870
9871
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009872static void UnreachableFunction(
9873 const v8::FunctionCallbackInfo<v8::Value>& info) {
9874 CHECK(false); // This function should not be called..
9875}
9876
9877
Steve Block1e0659c2011-05-24 12:43:12 +01009878TEST(AccessControl) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009879 v8::Isolate* isolate = CcTest::isolate();
9880 v8::HandleScope handle_scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009881 v8::Local<v8::ObjectTemplate> global_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009882 v8::ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00009883
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009884 global_template->SetAccessCheckCallback(AccessBlocker);
Steve Blocka7e24c12009-10-30 11:49:00 +00009885
9886 // Add an accessor accessible by cross-domain JS code.
9887 global_template->SetAccessor(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009888 v8_str("accessible_prop"), EchoGetter, EchoSetter, v8::Local<Value>(),
Steve Blocka7e24c12009-10-30 11:49:00 +00009889 v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
9890
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009891
Steve Blocka7e24c12009-10-30 11:49:00 +00009892 // Add an accessor that is not accessible by cross-domain JS code.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009893 global_template->SetAccessor(v8_str("blocked_prop"), UnreachableGetter,
9894 UnreachableSetter, v8::Local<Value>(),
Steve Blocka7e24c12009-10-30 11:49:00 +00009895 v8::DEFAULT);
9896
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009897 global_template->SetAccessorProperty(
9898 v8_str("blocked_js_prop"),
9899 v8::FunctionTemplate::New(isolate, UnreachableFunction),
9900 v8::FunctionTemplate::New(isolate, UnreachableFunction),
9901 v8::None,
9902 v8::DEFAULT);
9903
Steve Blocka7e24c12009-10-30 11:49:00 +00009904 // Create an environment
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009905 v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
Steve Blocka7e24c12009-10-30 11:49:00 +00009906 context0->Enter();
9907
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009908 v8::Local<v8::Object> global0 = context0->Global();
Steve Blocka7e24c12009-10-30 11:49:00 +00009909
Steve Block1e0659c2011-05-24 12:43:12 +01009910 // Define a property with JS getter and setter.
9911 CompileRun(
9912 "function getter() { return 'getter'; };\n"
9913 "function setter() { return 'setter'; }\n"
9914 "Object.defineProperty(this, 'js_accessor_p', {get:getter, set:setter})");
9915
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009916 Local<Value> getter =
9917 global0->Get(context0, v8_str("getter")).ToLocalChecked();
9918 Local<Value> setter =
9919 global0->Get(context0, v8_str("setter")).ToLocalChecked();
Steve Block1e0659c2011-05-24 12:43:12 +01009920
9921 // And define normal element.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009922 CHECK(global0->Set(context0, 239, v8_str("239")).FromJust());
Steve Block1e0659c2011-05-24 12:43:12 +01009923
9924 // Define an element with JS getter and setter.
9925 CompileRun(
9926 "function el_getter() { return 'el_getter'; };\n"
9927 "function el_setter() { return 'el_setter'; };\n"
9928 "Object.defineProperty(this, '42', {get: el_getter, set: el_setter});");
9929
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009930 Local<Value> el_getter =
9931 global0->Get(context0, v8_str("el_getter")).ToLocalChecked();
9932 Local<Value> el_setter =
9933 global0->Get(context0, v8_str("el_setter")).ToLocalChecked();
Steve Block1e0659c2011-05-24 12:43:12 +01009934
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009935 v8::HandleScope scope1(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00009936
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009937 v8::Local<Context> context1 = Context::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00009938 context1->Enter();
9939
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009940 v8::Local<v8::Object> global1 = context1->Global();
9941 CHECK(global1->Set(context1, v8_str("other"), global0).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +00009942
Steve Block1e0659c2011-05-24 12:43:12 +01009943 // Access blocked property.
9944 CompileRun("other.blocked_prop = 1");
9945
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009946 CHECK(CompileRun("other.blocked_prop").IsEmpty());
9947 CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, 'blocked_prop')")
9948 .IsEmpty());
9949 CHECK(
9950 CompileRun("propertyIsEnumerable.call(other, 'blocked_prop')").IsEmpty());
Steve Block1e0659c2011-05-24 12:43:12 +01009951
9952 // Access blocked element.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009953 CHECK(CompileRun("other[239] = 1").IsEmpty());
Steve Block1e0659c2011-05-24 12:43:12 +01009954
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009955 CHECK(CompileRun("other[239]").IsEmpty());
9956 CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, '239')").IsEmpty());
9957 CHECK(CompileRun("propertyIsEnumerable.call(other, '239')").IsEmpty());
Steve Block1e0659c2011-05-24 12:43:12 +01009958
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009959 allowed_access = true;
9960 // Now we can enumerate the property.
Steve Block1e0659c2011-05-24 12:43:12 +01009961 ExpectTrue("propertyIsEnumerable.call(other, '239')");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009962 allowed_access = false;
Steve Block1e0659c2011-05-24 12:43:12 +01009963
9964 // Access a property with JS accessor.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009965 CHECK(CompileRun("other.js_accessor_p = 2").IsEmpty());
Steve Block1e0659c2011-05-24 12:43:12 +01009966
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009967 CHECK(CompileRun("other.js_accessor_p").IsEmpty());
9968 CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, 'js_accessor_p')")
9969 .IsEmpty());
Steve Block1e0659c2011-05-24 12:43:12 +01009970
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009971 allowed_access = true;
Steve Block1e0659c2011-05-24 12:43:12 +01009972
9973 ExpectString("other.js_accessor_p", "getter");
9974 ExpectObject(
9975 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get", getter);
Steve Block1e0659c2011-05-24 12:43:12 +01009976 ExpectObject(
9977 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set", setter);
9978 ExpectUndefined(
9979 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
9980
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009981 allowed_access = false;
Steve Block1e0659c2011-05-24 12:43:12 +01009982
9983 // Access an element with JS accessor.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009984 CHECK(CompileRun("other[42] = 2").IsEmpty());
Steve Block1e0659c2011-05-24 12:43:12 +01009985
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009986 CHECK(CompileRun("other[42]").IsEmpty());
9987 CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, '42')").IsEmpty());
Steve Block1e0659c2011-05-24 12:43:12 +01009988
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009989 allowed_access = true;
Steve Block1e0659c2011-05-24 12:43:12 +01009990
9991 ExpectString("other[42]", "el_getter");
9992 ExpectObject("Object.getOwnPropertyDescriptor(other, '42').get", el_getter);
Steve Block1e0659c2011-05-24 12:43:12 +01009993 ExpectObject("Object.getOwnPropertyDescriptor(other, '42').set", el_setter);
9994 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
9995
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009996 allowed_access = false;
Steve Block1e0659c2011-05-24 12:43:12 +01009997
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009998 v8::Local<Value> value;
Steve Blocka7e24c12009-10-30 11:49:00 +00009999
Steve Blocka7e24c12009-10-30 11:49:00 +000010000 // Access accessible property
Steve Block1e0659c2011-05-24 12:43:12 +010010001 value = CompileRun("other.accessible_prop = 3");
Steve Blocka7e24c12009-10-30 11:49:00 +000010002 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010003 CHECK_EQ(3, value->Int32Value(context1).FromJust());
Andrei Popescu31002712010-02-23 13:46:05 +000010004 CHECK_EQ(3, g_echo_value);
Steve Blocka7e24c12009-10-30 11:49:00 +000010005
Steve Block1e0659c2011-05-24 12:43:12 +010010006 value = CompileRun("other.accessible_prop");
Steve Blocka7e24c12009-10-30 11:49:00 +000010007 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010008 CHECK_EQ(3, value->Int32Value(context1).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010009
Steve Block1e0659c2011-05-24 12:43:12 +010010010 value = CompileRun(
10011 "Object.getOwnPropertyDescriptor(other, 'accessible_prop').value");
10012 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010013 CHECK_EQ(3, value->Int32Value(context1).FromJust());
Steve Block1e0659c2011-05-24 12:43:12 +010010014
10015 value = CompileRun("propertyIsEnumerable.call(other, 'accessible_prop')");
Steve Blocka7e24c12009-10-30 11:49:00 +000010016 CHECK(value->IsTrue());
10017
10018 // Enumeration doesn't enumerate accessors from inaccessible objects in
10019 // the prototype chain even if the accessors are in themselves accessible.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010020 // Enumeration doesn't throw, it silently ignores what it can't access.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010021 value = CompileRun(
10022 "(function() {"
10023 " var obj = { '__proto__': other };"
10024 " try {"
10025 " for (var p in obj) {"
10026 " if (p == 'accessible_prop' ||"
10027 " p == 'blocked_js_prop' ||"
10028 " p == 'blocked_js_prop') {"
10029 " return false;"
10030 " }"
10031 " }"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010032 " return true;"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010033 " } catch (e) {"
10034 " return false;"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010035 " }"
10036 "})()");
Steve Block1e0659c2011-05-24 12:43:12 +010010037 CHECK(value->IsTrue());
Steve Blocka7e24c12009-10-30 11:49:00 +000010038
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010039 // Test that preventExtensions fails on a non-accessible object even if that
10040 // object is already non-extensible.
10041 CHECK(global1->Set(context1, v8_str("checked_object"),
10042 global_template->NewInstance(context1).ToLocalChecked())
10043 .FromJust());
10044 allowed_access = true;
10045 CompileRun("Object.preventExtensions(checked_object)");
10046 ExpectFalse("Object.isExtensible(checked_object)");
10047 allowed_access = false;
10048 CHECK(CompileRun("Object.preventExtensions(checked_object)").IsEmpty());
10049
Steve Blocka7e24c12009-10-30 11:49:00 +000010050 context1->Exit();
10051 context0->Exit();
Steve Blocka7e24c12009-10-30 11:49:00 +000010052}
10053
10054
Ben Murdoche0cee9b2011-05-25 10:26:03 +010010055TEST(AccessControlES5) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010056 v8::Isolate* isolate = CcTest::isolate();
10057 v8::HandleScope handle_scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010058 v8::Local<v8::ObjectTemplate> global_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010059 v8::ObjectTemplate::New(isolate);
Ben Murdoche0cee9b2011-05-25 10:26:03 +010010060
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010061 global_template->SetAccessCheckCallback(AccessBlocker);
Ben Murdoche0cee9b2011-05-25 10:26:03 +010010062
Steve Block44f0eee2011-05-26 01:26:41 +010010063 // Add accessible accessor.
10064 global_template->SetAccessor(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010065 v8_str("accessible_prop"), EchoGetter, EchoSetter, v8::Local<Value>(),
Steve Block44f0eee2011-05-26 01:26:41 +010010066 v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
10067
10068
Ben Murdoche0cee9b2011-05-25 10:26:03 +010010069 // Add an accessor that is not accessible by cross-domain JS code.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010070 global_template->SetAccessor(v8_str("blocked_prop"), UnreachableGetter,
10071 UnreachableSetter, v8::Local<Value>(),
Ben Murdoche0cee9b2011-05-25 10:26:03 +010010072 v8::DEFAULT);
10073
10074 // Create an environment
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010075 v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
Ben Murdoche0cee9b2011-05-25 10:26:03 +010010076 context0->Enter();
10077
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010078 v8::Local<v8::Object> global0 = context0->Global();
Ben Murdoche0cee9b2011-05-25 10:26:03 +010010079
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010080 v8::Local<Context> context1 = Context::New(isolate);
Ben Murdoche0cee9b2011-05-25 10:26:03 +010010081 context1->Enter();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010082 v8::Local<v8::Object> global1 = context1->Global();
10083 CHECK(global1->Set(context1, v8_str("other"), global0).FromJust());
Ben Murdoche0cee9b2011-05-25 10:26:03 +010010084
10085 // Regression test for issue 1154.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010086 CHECK(CompileRun("Object.keys(other).length == 1")
10087 ->BooleanValue(context1)
10088 .FromJust());
10089 CHECK(CompileRun("Object.keys(other)[0] == 'accessible_prop'")
10090 ->BooleanValue(context1)
10091 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010092 CHECK(CompileRun("other.blocked_prop").IsEmpty());
Ben Murdoche0cee9b2011-05-25 10:26:03 +010010093
10094 // Regression test for issue 1027.
10095 CompileRun("Object.defineProperty(\n"
10096 " other, 'blocked_prop', {configurable: false})");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010097 CHECK(CompileRun("other.blocked_prop").IsEmpty());
10098 CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, 'blocked_prop')")
10099 .IsEmpty());
Ben Murdoche0cee9b2011-05-25 10:26:03 +010010100
10101 // Regression test for issue 1171.
10102 ExpectTrue("Object.isExtensible(other)");
10103 CompileRun("Object.preventExtensions(other)");
10104 ExpectTrue("Object.isExtensible(other)");
10105
10106 // Object.seal and Object.freeze.
10107 CompileRun("Object.freeze(other)");
10108 ExpectTrue("Object.isExtensible(other)");
10109
10110 CompileRun("Object.seal(other)");
10111 ExpectTrue("Object.isExtensible(other)");
Steve Block44f0eee2011-05-26 01:26:41 +010010112
10113 // Regression test for issue 1250.
10114 // Make sure that we can set the accessible accessors value using normal
10115 // assignment.
10116 CompileRun("other.accessible_prop = 42");
10117 CHECK_EQ(42, g_echo_value);
10118
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010119 // [[DefineOwnProperty]] always throws for access-checked objects.
10120 CHECK(
10121 CompileRun("Object.defineProperty(other, 'accessible_prop', {value: 43})")
10122 .IsEmpty());
10123 CHECK(CompileRun("other.accessible_prop == 42")->IsTrue());
10124 CHECK_EQ(42, g_echo_value); // Make sure we didn't call the setter.
Ben Murdoche0cee9b2011-05-25 10:26:03 +010010125}
10126
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010127static bool AccessAlwaysBlocked(Local<v8::Context> accessing_context,
Ben Murdoch097c5b22016-05-18 11:27:45 +010010128 Local<v8::Object> global,
10129 Local<v8::Value> data) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010130 i::PrintF("Access blocked.\n");
Leon Clarke4515c472010-02-03 11:58:03 +000010131 return false;
10132}
10133
10134
10135THREADED_TEST(AccessControlGetOwnPropertyNames) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010136 v8::Isolate* isolate = CcTest::isolate();
10137 v8::HandleScope handle_scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010138 v8::Local<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New(isolate);
Leon Clarke4515c472010-02-03 11:58:03 +000010139
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010140 obj_template->Set(v8_str("x"), v8::Integer::New(isolate, 42));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010141 obj_template->SetAccessCheckCallback(AccessAlwaysBlocked);
10142
10143 // Add an accessor accessible by cross-domain JS code.
10144 obj_template->SetAccessor(
10145 v8_str("accessible_prop"), EchoGetter, EchoSetter, v8::Local<Value>(),
10146 v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
Leon Clarke4515c472010-02-03 11:58:03 +000010147
10148 // Create an environment
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010149 v8::Local<Context> context0 = Context::New(isolate, NULL, obj_template);
Leon Clarke4515c472010-02-03 11:58:03 +000010150 context0->Enter();
10151
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010152 v8::Local<v8::Object> global0 = context0->Global();
Leon Clarke4515c472010-02-03 11:58:03 +000010153
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010154 v8::HandleScope scope1(CcTest::isolate());
Leon Clarke4515c472010-02-03 11:58:03 +000010155
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010156 v8::Local<Context> context1 = Context::New(isolate);
Leon Clarke4515c472010-02-03 11:58:03 +000010157 context1->Enter();
10158
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010159 v8::Local<v8::Object> global1 = context1->Global();
10160 CHECK(global1->Set(context1, v8_str("other"), global0).FromJust());
10161 CHECK(global1->Set(context1, v8_str("object"),
10162 obj_template->NewInstance(context1).ToLocalChecked())
10163 .FromJust());
Leon Clarke4515c472010-02-03 11:58:03 +000010164
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010165 v8::Local<Value> value;
Leon Clarke4515c472010-02-03 11:58:03 +000010166
10167 // Attempt to get the property names of the other global object and
10168 // of an object that requires access checks. Accessing the other
10169 // global object should be blocked by access checks on the global
10170 // proxy object. Accessing the object that requires access checks
10171 // is blocked by the access checks on the object itself.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010172 value = CompileRun(
10173 "var names = Object.getOwnPropertyNames(other);"
10174 "names.length == 1 && names[0] == 'accessible_prop';");
10175 CHECK(value->BooleanValue(context1).FromJust());
Leon Clarke4515c472010-02-03 11:58:03 +000010176
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010177 value = CompileRun(
10178 "var names = Object.getOwnPropertyNames(object);"
10179 "names.length == 1 && names[0] == 'accessible_prop';");
10180 CHECK(value->BooleanValue(context1).FromJust());
Leon Clarke4515c472010-02-03 11:58:03 +000010181
10182 context1->Exit();
10183 context0->Exit();
Leon Clarke4515c472010-02-03 11:58:03 +000010184}
10185
10186
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010187TEST(Regress470113) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010188 v8::Isolate* isolate = CcTest::isolate();
10189 v8::HandleScope handle_scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010190 v8::Local<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New(isolate);
10191 obj_template->SetAccessCheckCallback(AccessAlwaysBlocked);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010192 LocalContext env;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010193 CHECK(env->Global()
10194 ->Set(env.local(), v8_str("prohibited"),
10195 obj_template->NewInstance(env.local()).ToLocalChecked())
10196 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010197
Emily Bernierd0a1eb72015-03-24 16:35:39 -040010198 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010199 v8::TryCatch try_catch(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040010200 CompileRun(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010201 "'use strict';\n"
10202 "class C extends Object {\n"
10203 " m() { super.powned = 'Powned!'; }\n"
10204 "}\n"
10205 "let c = new C();\n"
10206 "c.m.call(prohibited)");
10207
Emily Bernierd0a1eb72015-03-24 16:35:39 -040010208 CHECK(try_catch.HasCaught());
10209 }
Steve Block8defd9f2010-07-08 12:39:36 +010010210}
10211
10212
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010213static void ConstTenGetter(Local<String> name,
10214 const v8::PropertyCallbackInfo<v8::Value>& info) {
10215 info.GetReturnValue().Set(v8_num(10));
Steve Blocka7e24c12009-10-30 11:49:00 +000010216}
10217
10218
10219THREADED_TEST(CrossDomainAccessors) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010220 v8::Isolate* isolate = CcTest::isolate();
10221 v8::HandleScope handle_scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010222
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010223 v8::Local<v8::FunctionTemplate> func_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010224 v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010225
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010226 v8::Local<v8::ObjectTemplate> global_template =
Steve Blocka7e24c12009-10-30 11:49:00 +000010227 func_template->InstanceTemplate();
10228
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010229 v8::Local<v8::ObjectTemplate> proto_template =
Steve Blocka7e24c12009-10-30 11:49:00 +000010230 func_template->PrototypeTemplate();
10231
10232 // Add an accessor to proto that's accessible by cross-domain JS code.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010233 proto_template->SetAccessor(v8_str("accessible"), ConstTenGetter, 0,
10234 v8::Local<Value>(), v8::ALL_CAN_READ);
Steve Blocka7e24c12009-10-30 11:49:00 +000010235
10236 // Add an accessor that is not accessible by cross-domain JS code.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010237 global_template->SetAccessor(v8_str("unreachable"), UnreachableGetter, 0,
10238 v8::Local<Value>(), v8::DEFAULT);
Steve Blocka7e24c12009-10-30 11:49:00 +000010239
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010240 v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
Steve Blocka7e24c12009-10-30 11:49:00 +000010241 context0->Enter();
10242
10243 Local<v8::Object> global = context0->Global();
10244 // Add a normal property that shadows 'accessible'
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010245 CHECK(global->Set(context0, v8_str("accessible"), v8_num(11)).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010246
10247 // Enter a new context.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010248 v8::HandleScope scope1(CcTest::isolate());
10249 v8::Local<Context> context1 = Context::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010250 context1->Enter();
10251
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010252 v8::Local<v8::Object> global1 = context1->Global();
10253 CHECK(global1->Set(context1, v8_str("other"), global).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010254
10255 // Should return 10, instead of 11
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010256 v8::Local<Value> value =
10257 v8_compile("other.accessible")->Run(context1).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000010258 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010259 CHECK_EQ(10, value->Int32Value(context1).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010260
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010261 v8::MaybeLocal<v8::Value> maybe_value =
10262 v8_compile("other.unreachable")->Run(context1);
10263 CHECK(maybe_value.IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +000010264
10265 context1->Exit();
10266 context0->Exit();
Steve Blocka7e24c12009-10-30 11:49:00 +000010267}
10268
10269
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010270static int access_count = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +000010271
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010272static bool AccessCounter(Local<v8::Context> accessing_context,
Ben Murdoch097c5b22016-05-18 11:27:45 +010010273 Local<v8::Object> accessed_object,
10274 Local<v8::Value> data) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010275 access_count++;
Steve Blocka7e24c12009-10-30 11:49:00 +000010276 return true;
10277}
10278
10279
10280// This one is too easily disturbed by other tests.
10281TEST(AccessControlIC) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010282 access_count = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +000010283
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010284 v8::Isolate* isolate = CcTest::isolate();
10285 v8::HandleScope handle_scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010286
10287 // Create an environment.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010288 v8::Local<Context> context0 = Context::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010289 context0->Enter();
10290
10291 // Create an object that requires access-check functions to be
10292 // called for cross-domain access.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010293 v8::Local<v8::ObjectTemplate> object_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010294 v8::ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010295 object_template->SetAccessCheckCallback(AccessCounter);
10296 Local<v8::Object> object =
10297 object_template->NewInstance(context0).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000010298
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010299 v8::HandleScope scope1(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010300
10301 // Create another environment.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010302 v8::Local<Context> context1 = Context::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010303 context1->Enter();
10304
10305 // Make easy access to the object from the other environment.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010306 v8::Local<v8::Object> global1 = context1->Global();
10307 CHECK(global1->Set(context1, v8_str("obj"), object).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010308
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010309 v8::Local<Value> value;
Steve Blocka7e24c12009-10-30 11:49:00 +000010310
10311 // Check that the named access-control function is called every time.
10312 CompileRun("function testProp(obj) {"
10313 " for (var i = 0; i < 10; i++) obj.prop = 1;"
10314 " for (var j = 0; j < 10; j++) obj.prop;"
10315 " return obj.prop"
10316 "}");
10317 value = CompileRun("testProp(obj)");
10318 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010319 CHECK_EQ(1, value->Int32Value(context1).FromJust());
10320 CHECK_EQ(21, access_count);
Steve Blocka7e24c12009-10-30 11:49:00 +000010321
10322 // Check that the named access-control function is called every time.
10323 CompileRun("var p = 'prop';"
10324 "function testKeyed(obj) {"
10325 " for (var i = 0; i < 10; i++) obj[p] = 1;"
10326 " for (var j = 0; j < 10; j++) obj[p];"
10327 " return obj[p];"
10328 "}");
10329 // Use obj which requires access checks. No inline caching is used
10330 // in that case.
10331 value = CompileRun("testKeyed(obj)");
10332 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010333 CHECK_EQ(1, value->Int32Value(context1).FromJust());
10334 CHECK_EQ(42, access_count);
Steve Blocka7e24c12009-10-30 11:49:00 +000010335 // Force the inline caches into generic state and try again.
10336 CompileRun("testKeyed({ a: 0 })");
10337 CompileRun("testKeyed({ b: 0 })");
10338 value = CompileRun("testKeyed(obj)");
10339 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010340 CHECK_EQ(1, value->Int32Value(context1).FromJust());
10341 CHECK_EQ(63, access_count);
Steve Blocka7e24c12009-10-30 11:49:00 +000010342
10343 // Check that the indexed access-control function is called every time.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010344 access_count = 0;
10345
Steve Blocka7e24c12009-10-30 11:49:00 +000010346 CompileRun("function testIndexed(obj) {"
10347 " for (var i = 0; i < 10; i++) obj[0] = 1;"
10348 " for (var j = 0; j < 10; j++) obj[0];"
10349 " return obj[0]"
10350 "}");
10351 value = CompileRun("testIndexed(obj)");
10352 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010353 CHECK_EQ(1, value->Int32Value(context1).FromJust());
10354 CHECK_EQ(21, access_count);
Steve Blocka7e24c12009-10-30 11:49:00 +000010355 // Force the inline caches into generic state.
10356 CompileRun("testIndexed(new Array(1))");
10357 // Test that the indexed access check is called.
10358 value = CompileRun("testIndexed(obj)");
10359 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010360 CHECK_EQ(1, value->Int32Value(context1).FromJust());
10361 CHECK_EQ(42, access_count);
Steve Blocka7e24c12009-10-30 11:49:00 +000010362
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010363 access_count = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +000010364 // Check that the named access check is called when invoking
10365 // functions on an object that requires access checks.
10366 CompileRun("obj.f = function() {}");
10367 CompileRun("function testCallNormal(obj) {"
10368 " for (var i = 0; i < 10; i++) obj.f();"
10369 "}");
10370 CompileRun("testCallNormal(obj)");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010371 printf("%i\n", access_count);
10372 CHECK_EQ(11, access_count);
Steve Blocka7e24c12009-10-30 11:49:00 +000010373
10374 // Force obj into slow case.
10375 value = CompileRun("delete obj.prop");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010376 CHECK(value->BooleanValue(context1).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010377 // Force inline caches into dictionary probing mode.
10378 CompileRun("var o = { x: 0 }; delete o.x; testProp(o);");
10379 // Test that the named access check is called.
10380 value = CompileRun("testProp(obj);");
10381 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010382 CHECK_EQ(1, value->Int32Value(context1).FromJust());
10383 CHECK_EQ(33, access_count);
Steve Blocka7e24c12009-10-30 11:49:00 +000010384
10385 // Force the call inline cache into dictionary probing mode.
10386 CompileRun("o.f = function() {}; testCallNormal(o)");
10387 // Test that the named access check is still called for each
10388 // invocation of the function.
10389 value = CompileRun("testCallNormal(obj)");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010390 CHECK_EQ(43, access_count);
Steve Blocka7e24c12009-10-30 11:49:00 +000010391
10392 context1->Exit();
10393 context0->Exit();
Steve Blocka7e24c12009-10-30 11:49:00 +000010394}
10395
10396
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010397THREADED_TEST(Version) { v8::V8::GetVersion(); }
Steve Blocka7e24c12009-10-30 11:49:00 +000010398
10399
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010400static void InstanceFunctionCallback(
10401 const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +000010402 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010403 args.GetReturnValue().Set(v8_num(12));
Steve Blocka7e24c12009-10-30 11:49:00 +000010404}
10405
10406
10407THREADED_TEST(InstanceProperties) {
Steve Blocka7e24c12009-10-30 11:49:00 +000010408 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010409 v8::Isolate* isolate = context->GetIsolate();
10410 v8::HandleScope handle_scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010411
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010412 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010413 Local<ObjectTemplate> instance = t->InstanceTemplate();
10414
10415 instance->Set(v8_str("x"), v8_num(42));
10416 instance->Set(v8_str("f"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010417 v8::FunctionTemplate::New(isolate, InstanceFunctionCallback));
Steve Blocka7e24c12009-10-30 11:49:00 +000010418
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010419 Local<Value> o = t->GetFunction(context.local())
10420 .ToLocalChecked()
10421 ->NewInstance(context.local())
10422 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000010423
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010424 CHECK(context->Global()->Set(context.local(), v8_str("i"), o).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010425 Local<Value> value = CompileRun("i.x");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010426 CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010427
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010428 value = CompileRun("i.f()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010429 CHECK_EQ(12, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010430}
10431
10432
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010433static void GlobalObjectInstancePropertiesGet(
Emily Bernierd0a1eb72015-03-24 16:35:39 -040010434 Local<Name> key, const v8::PropertyCallbackInfo<v8::Value>&) {
Steve Blocka7e24c12009-10-30 11:49:00 +000010435 ApiTestFuzzer::Fuzz();
Steve Blocka7e24c12009-10-30 11:49:00 +000010436}
10437
10438
10439THREADED_TEST(GlobalObjectInstanceProperties) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010440 v8::Isolate* isolate = CcTest::isolate();
10441 v8::HandleScope handle_scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010442
10443 Local<Value> global_object;
10444
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010445 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040010446 t->InstanceTemplate()->SetHandler(
10447 v8::NamedPropertyHandlerConfiguration(GlobalObjectInstancePropertiesGet));
Steve Blocka7e24c12009-10-30 11:49:00 +000010448 Local<ObjectTemplate> instance_template = t->InstanceTemplate();
10449 instance_template->Set(v8_str("x"), v8_num(42));
10450 instance_template->Set(v8_str("f"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010451 v8::FunctionTemplate::New(isolate,
10452 InstanceFunctionCallback));
Steve Blocka7e24c12009-10-30 11:49:00 +000010453
Ben Murdochb0fe1622011-05-05 13:52:32 +010010454 // The script to check how Crankshaft compiles missing global function
10455 // invocations. function g is not defined and should throw on call.
10456 const char* script =
10457 "function wrapper(call) {"
10458 " var x = 0, y = 1;"
10459 " for (var i = 0; i < 1000; i++) {"
10460 " x += i * 100;"
10461 " y += i * 100;"
10462 " }"
10463 " if (call) g();"
10464 "}"
10465 "for (var i = 0; i < 17; i++) wrapper(false);"
10466 "var thrown = 0;"
10467 "try { wrapper(true); } catch (e) { thrown = 1; };"
10468 "thrown";
10469
Steve Blocka7e24c12009-10-30 11:49:00 +000010470 {
10471 LocalContext env(NULL, instance_template);
10472 // Hold on to the global object so it can be used again in another
10473 // environment initialization.
10474 global_object = env->Global();
10475
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010476 Local<Value> value = CompileRun("x");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010477 CHECK_EQ(42, value->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010478 value = CompileRun("f()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010479 CHECK_EQ(12, value->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010480 value = CompileRun(script);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010481 CHECK_EQ(1, value->Int32Value(env.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010482 }
10483
10484 {
10485 // Create new environment reusing the global object.
10486 LocalContext env(NULL, instance_template, global_object);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010487 Local<Value> value = CompileRun("x");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010488 CHECK_EQ(42, value->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010489 value = CompileRun("f()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010490 CHECK_EQ(12, value->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010491 value = CompileRun(script);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010492 CHECK_EQ(1, value->Int32Value(env.local()).FromJust());
Ben Murdochb0fe1622011-05-05 13:52:32 +010010493 }
10494}
10495
Ben Murdochc5610432016-08-08 18:44:38 +010010496THREADED_TEST(ObjectGetOwnPropertyNames) {
10497 LocalContext context;
10498 v8::Isolate* isolate = context->GetIsolate();
10499 v8::HandleScope handle_scope(isolate);
10500
10501 v8::Local<v8::Object> value =
10502 v8::Local<v8::Object>::Cast(v8::StringObject::New(v8_str("test")));
10503 v8::Local<v8::Array> properties;
10504
10505 CHECK(value
10506 ->GetOwnPropertyNames(context.local(),
10507 static_cast<v8::PropertyFilter>(
10508 v8::PropertyFilter::ALL_PROPERTIES |
10509 v8::PropertyFilter::SKIP_SYMBOLS))
10510 .ToLocal(&properties));
10511 CHECK_EQ(5, properties->Length());
10512 v8::Local<v8::Value> property;
10513 CHECK(properties->Get(context.local(), 4).ToLocal(&property) &&
10514 property->IsString());
10515 CHECK(property.As<v8::String>()
10516 ->Equals(context.local(), v8_str("length"))
10517 .FromMaybe(false));
10518 for (int i = 0; i < 4; ++i) {
10519 v8::Local<v8::Value> property;
10520 CHECK(properties->Get(context.local(), i).ToLocal(&property) &&
10521 property->IsInt32());
10522 CHECK_EQ(property.As<v8::Int32>()->Value(), i);
10523 }
10524
10525 CHECK(value->GetOwnPropertyNames(context.local(), v8::ONLY_ENUMERABLE)
10526 .ToLocal(&properties));
10527 CHECK_EQ(4, properties->Length());
10528 for (int i = 0; i < 4; ++i) {
10529 v8::Local<v8::Value> property;
10530 CHECK(properties->Get(context.local(), i).ToLocal(&property) &&
10531 property->IsInt32());
10532 CHECK_EQ(property.As<v8::Int32>()->Value(), i);
10533 }
10534
10535 value = value->GetPrototype().As<v8::Object>();
10536 CHECK(value
10537 ->GetOwnPropertyNames(context.local(),
10538 static_cast<v8::PropertyFilter>(
10539 v8::PropertyFilter::ALL_PROPERTIES |
10540 v8::PropertyFilter::SKIP_SYMBOLS))
10541 .ToLocal(&properties));
10542 bool concat_found = false;
10543 bool starts_with_found = false;
10544 for (uint32_t i = 0; i < properties->Length(); ++i) {
10545 v8::Local<v8::Value> property;
10546 CHECK(properties->Get(context.local(), i).ToLocal(&property));
10547 if (!property->IsString()) continue;
10548 if (!concat_found)
10549 concat_found = property.As<v8::String>()
10550 ->Equals(context.local(), v8_str("concat"))
10551 .FromMaybe(false);
10552 if (!starts_with_found)
10553 starts_with_found = property.As<v8::String>()
10554 ->Equals(context.local(), v8_str("startsWith"))
10555 .FromMaybe(false);
10556 }
10557 CHECK(concat_found && starts_with_found);
10558}
Ben Murdochb0fe1622011-05-05 13:52:32 +010010559
10560THREADED_TEST(CallKnownGlobalReceiver) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010561 v8::Isolate* isolate = CcTest::isolate();
10562 v8::HandleScope handle_scope(isolate);
Ben Murdochb0fe1622011-05-05 13:52:32 +010010563
10564 Local<Value> global_object;
10565
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010566 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
Ben Murdochb0fe1622011-05-05 13:52:32 +010010567 Local<ObjectTemplate> instance_template = t->InstanceTemplate();
10568
10569 // The script to check that we leave global object not
10570 // global object proxy on stack when we deoptimize from inside
10571 // arguments evaluation.
10572 // To provoke error we need to both force deoptimization
10573 // from arguments evaluation and to force CallIC to take
10574 // CallIC_Miss code path that can't cope with global proxy.
10575 const char* script =
10576 "function bar(x, y) { try { } finally { } }"
10577 "function baz(x) { try { } finally { } }"
10578 "function bom(x) { try { } finally { } }"
10579 "function foo(x) { bar([x], bom(2)); }"
10580 "for (var i = 0; i < 10000; i++) foo(1);"
10581 "foo";
10582
10583 Local<Value> foo;
10584 {
10585 LocalContext env(NULL, instance_template);
10586 // Hold on to the global object so it can be used again in another
10587 // environment initialization.
10588 global_object = env->Global();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010589 foo = CompileRun(script);
Ben Murdochb0fe1622011-05-05 13:52:32 +010010590 }
10591
10592 {
10593 // Create new environment reusing the global object.
10594 LocalContext env(NULL, instance_template, global_object);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010595 CHECK(env->Global()->Set(env.local(), v8_str("foo"), foo).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010596 CompileRun("foo()");
Steve Blocka7e24c12009-10-30 11:49:00 +000010597 }
10598}
10599
10600
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010601static void ShadowFunctionCallback(
10602 const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +000010603 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010604 args.GetReturnValue().Set(v8_num(42));
Steve Blocka7e24c12009-10-30 11:49:00 +000010605}
10606
10607
10608static int shadow_y;
10609static int shadow_y_setter_call_count;
10610static int shadow_y_getter_call_count;
10611
10612
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010613static void ShadowYSetter(Local<String>,
10614 Local<Value>,
10615 const v8::PropertyCallbackInfo<void>&) {
Steve Blocka7e24c12009-10-30 11:49:00 +000010616 shadow_y_setter_call_count++;
10617 shadow_y = 42;
10618}
10619
10620
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010621static void ShadowYGetter(Local<String> name,
10622 const v8::PropertyCallbackInfo<v8::Value>& info) {
Steve Blocka7e24c12009-10-30 11:49:00 +000010623 ApiTestFuzzer::Fuzz();
10624 shadow_y_getter_call_count++;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010625 info.GetReturnValue().Set(v8_num(shadow_y));
Steve Blocka7e24c12009-10-30 11:49:00 +000010626}
10627
10628
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010629static void ShadowIndexedGet(uint32_t index,
10630 const v8::PropertyCallbackInfo<v8::Value>&) {
Steve Blocka7e24c12009-10-30 11:49:00 +000010631}
10632
10633
Emily Bernierd0a1eb72015-03-24 16:35:39 -040010634static void ShadowNamedGet(Local<Name> key,
10635 const v8::PropertyCallbackInfo<v8::Value>&) {}
Steve Blocka7e24c12009-10-30 11:49:00 +000010636
10637
10638THREADED_TEST(ShadowObject) {
10639 shadow_y = shadow_y_setter_call_count = shadow_y_getter_call_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010640 v8::Isolate* isolate = CcTest::isolate();
10641 v8::HandleScope handle_scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010642
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010643 Local<ObjectTemplate> global_template = v8::ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010644 LocalContext context(NULL, global_template);
10645
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010646 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040010647 t->InstanceTemplate()->SetHandler(
10648 v8::NamedPropertyHandlerConfiguration(ShadowNamedGet));
10649 t->InstanceTemplate()->SetHandler(
10650 v8::IndexedPropertyHandlerConfiguration(ShadowIndexedGet));
Steve Blocka7e24c12009-10-30 11:49:00 +000010651 Local<ObjectTemplate> proto = t->PrototypeTemplate();
10652 Local<ObjectTemplate> instance = t->InstanceTemplate();
10653
Steve Blocka7e24c12009-10-30 11:49:00 +000010654 proto->Set(v8_str("f"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010655 v8::FunctionTemplate::New(isolate,
10656 ShadowFunctionCallback,
10657 Local<Value>()));
Steve Blocka7e24c12009-10-30 11:49:00 +000010658 proto->Set(v8_str("x"), v8_num(12));
10659
10660 instance->SetAccessor(v8_str("y"), ShadowYGetter, ShadowYSetter);
10661
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010662 Local<Value> o = t->GetFunction(context.local())
10663 .ToLocalChecked()
10664 ->NewInstance(context.local())
10665 .ToLocalChecked();
10666 CHECK(context->Global()
10667 ->Set(context.local(), v8_str("__proto__"), o)
10668 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010669
10670 Local<Value> value =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010671 CompileRun("this.propertyIsEnumerable(0)");
Steve Blocka7e24c12009-10-30 11:49:00 +000010672 CHECK(value->IsBoolean());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010673 CHECK(!value->BooleanValue(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010674
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010675 value = CompileRun("x");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010676 CHECK_EQ(12, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010677
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010678 value = CompileRun("f()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010679 CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010680
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010681 CompileRun("y = 43");
Steve Blocka7e24c12009-10-30 11:49:00 +000010682 CHECK_EQ(1, shadow_y_setter_call_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010683 value = CompileRun("y");
Steve Blocka7e24c12009-10-30 11:49:00 +000010684 CHECK_EQ(1, shadow_y_getter_call_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010685 CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010686}
10687
10688
10689THREADED_TEST(HiddenPrototype) {
Steve Blocka7e24c12009-10-30 11:49:00 +000010690 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010691 v8::Isolate* isolate = context->GetIsolate();
10692 v8::HandleScope handle_scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010693
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010694 Local<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010695 t0->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010696 Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010697 t1->SetHiddenPrototype(true);
10698 t1->InstanceTemplate()->Set(v8_str("y"), v8_num(1));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010699 Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010700 t2->SetHiddenPrototype(true);
10701 t2->InstanceTemplate()->Set(v8_str("z"), v8_num(2));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010702 Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000010703 t3->InstanceTemplate()->Set(v8_str("u"), v8_num(3));
10704
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010705 Local<v8::Object> o0 = t0->GetFunction(context.local())
10706 .ToLocalChecked()
10707 ->NewInstance(context.local())
10708 .ToLocalChecked();
10709 Local<v8::Object> o1 = t1->GetFunction(context.local())
10710 .ToLocalChecked()
10711 ->NewInstance(context.local())
10712 .ToLocalChecked();
10713 Local<v8::Object> o2 = t2->GetFunction(context.local())
10714 .ToLocalChecked()
10715 ->NewInstance(context.local())
10716 .ToLocalChecked();
10717 Local<v8::Object> o3 = t3->GetFunction(context.local())
10718 .ToLocalChecked()
10719 ->NewInstance(context.local())
10720 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000010721
10722 // Setting the prototype on an object skips hidden prototypes.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010723 CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
10724 .ToLocalChecked()
10725 ->Int32Value(context.local())
10726 .FromJust());
10727 CHECK(o0->Set(context.local(), v8_str("__proto__"), o1).FromJust());
10728 CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
10729 .ToLocalChecked()
10730 ->Int32Value(context.local())
10731 .FromJust());
10732 CHECK_EQ(1, o0->Get(context.local(), v8_str("y"))
10733 .ToLocalChecked()
10734 ->Int32Value(context.local())
10735 .FromJust());
10736 CHECK(o0->Set(context.local(), v8_str("__proto__"), o2).FromJust());
10737 CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
10738 .ToLocalChecked()
10739 ->Int32Value(context.local())
10740 .FromJust());
10741 CHECK_EQ(1, o0->Get(context.local(), v8_str("y"))
10742 .ToLocalChecked()
10743 ->Int32Value(context.local())
10744 .FromJust());
10745 CHECK_EQ(2, o0->Get(context.local(), v8_str("z"))
10746 .ToLocalChecked()
10747 ->Int32Value(context.local())
10748 .FromJust());
10749 CHECK(o0->Set(context.local(), v8_str("__proto__"), o3).FromJust());
10750 CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
10751 .ToLocalChecked()
10752 ->Int32Value(context.local())
10753 .FromJust());
10754 CHECK_EQ(1, o0->Get(context.local(), v8_str("y"))
10755 .ToLocalChecked()
10756 ->Int32Value(context.local())
10757 .FromJust());
10758 CHECK_EQ(2, o0->Get(context.local(), v8_str("z"))
10759 .ToLocalChecked()
10760 ->Int32Value(context.local())
10761 .FromJust());
10762 CHECK_EQ(3, o0->Get(context.local(), v8_str("u"))
10763 .ToLocalChecked()
10764 ->Int32Value(context.local())
10765 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000010766
10767 // Getting the prototype of o0 should get the first visible one
10768 // which is o3. Therefore, z should not be defined on the prototype
10769 // object.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010770 Local<Value> proto =
10771 o0->Get(context.local(), v8_str("__proto__")).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000010772 CHECK(proto->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010773 CHECK(proto.As<v8::Object>()
10774 ->Get(context.local(), v8_str("z"))
10775 .ToLocalChecked()
10776 ->IsUndefined());
Steve Blocka7e24c12009-10-30 11:49:00 +000010777}
10778
10779
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010780THREADED_TEST(HiddenPrototypeSet) {
Andrei Popescu402d9372010-02-26 13:31:12 +000010781 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010782 v8::Isolate* isolate = context->GetIsolate();
10783 v8::HandleScope handle_scope(isolate);
Andrei Popescu402d9372010-02-26 13:31:12 +000010784
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010785 Local<v8::FunctionTemplate> ot = v8::FunctionTemplate::New(isolate);
10786 Local<v8::FunctionTemplate> ht = v8::FunctionTemplate::New(isolate);
10787 ht->SetHiddenPrototype(true);
10788 Local<v8::FunctionTemplate> pt = v8::FunctionTemplate::New(isolate);
10789 ht->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
10790
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010791 Local<v8::Object> o = ot->GetFunction(context.local())
10792 .ToLocalChecked()
10793 ->NewInstance(context.local())
10794 .ToLocalChecked();
10795 Local<v8::Object> h = ht->GetFunction(context.local())
10796 .ToLocalChecked()
10797 ->NewInstance(context.local())
10798 .ToLocalChecked();
10799 Local<v8::Object> p = pt->GetFunction(context.local())
10800 .ToLocalChecked()
10801 ->NewInstance(context.local())
10802 .ToLocalChecked();
10803 CHECK(o->Set(context.local(), v8_str("__proto__"), h).FromJust());
10804 CHECK(h->Set(context.local(), v8_str("__proto__"), p).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010805
10806 // Setting a property that exists on the hidden prototype goes there.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010807 CHECK(o->Set(context.local(), v8_str("x"), v8_num(7)).FromJust());
10808 CHECK_EQ(7, o->Get(context.local(), v8_str("x"))
10809 .ToLocalChecked()
10810 ->Int32Value(context.local())
10811 .FromJust());
10812 CHECK_EQ(7, h->Get(context.local(), v8_str("x"))
10813 .ToLocalChecked()
10814 ->Int32Value(context.local())
10815 .FromJust());
10816 CHECK(p->Get(context.local(), v8_str("x")).ToLocalChecked()->IsUndefined());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010817
10818 // Setting a new property should not be forwarded to the hidden prototype.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010819 CHECK(o->Set(context.local(), v8_str("y"), v8_num(6)).FromJust());
10820 CHECK_EQ(6, o->Get(context.local(), v8_str("y"))
10821 .ToLocalChecked()
10822 ->Int32Value(context.local())
10823 .FromJust());
10824 CHECK(h->Get(context.local(), v8_str("y")).ToLocalChecked()->IsUndefined());
10825 CHECK(p->Get(context.local(), v8_str("y")).ToLocalChecked()->IsUndefined());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010826
10827 // Setting a property that only exists on a prototype of the hidden prototype
10828 // is treated normally again.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010829 CHECK(p->Set(context.local(), v8_str("z"), v8_num(8)).FromJust());
10830 CHECK_EQ(8, o->Get(context.local(), v8_str("z"))
10831 .ToLocalChecked()
10832 ->Int32Value(context.local())
10833 .FromJust());
10834 CHECK_EQ(8, h->Get(context.local(), v8_str("z"))
10835 .ToLocalChecked()
10836 ->Int32Value(context.local())
10837 .FromJust());
10838 CHECK_EQ(8, p->Get(context.local(), v8_str("z"))
10839 .ToLocalChecked()
10840 ->Int32Value(context.local())
10841 .FromJust());
10842 CHECK(o->Set(context.local(), v8_str("z"), v8_num(9)).FromJust());
10843 CHECK_EQ(9, o->Get(context.local(), v8_str("z"))
10844 .ToLocalChecked()
10845 ->Int32Value(context.local())
10846 .FromJust());
10847 CHECK_EQ(8, h->Get(context.local(), v8_str("z"))
10848 .ToLocalChecked()
10849 ->Int32Value(context.local())
10850 .FromJust());
10851 CHECK_EQ(8, p->Get(context.local(), v8_str("z"))
10852 .ToLocalChecked()
10853 ->Int32Value(context.local())
10854 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010855}
10856
10857
10858// Regression test for issue 2457.
10859THREADED_TEST(HiddenPrototypeIdentityHash) {
10860 LocalContext context;
10861 v8::HandleScope handle_scope(context->GetIsolate());
10862
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010863 Local<FunctionTemplate> t = FunctionTemplate::New(context->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010864 t->SetHiddenPrototype(true);
10865 t->InstanceTemplate()->Set(v8_str("foo"), v8_num(75));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010866 Local<Object> p = t->GetFunction(context.local())
10867 .ToLocalChecked()
10868 ->NewInstance(context.local())
10869 .ToLocalChecked();
10870 Local<Object> o = Object::New(context->GetIsolate());
10871 CHECK(o->SetPrototype(context.local(), p).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010872
10873 int hash = o->GetIdentityHash();
10874 USE(hash);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010875 CHECK(o->Set(context.local(), v8_str("foo"), v8_num(42)).FromJust());
10876 CHECK_EQ(hash, o->GetIdentityHash());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010877}
10878
10879
10880THREADED_TEST(SetPrototype) {
10881 LocalContext context;
10882 v8::Isolate* isolate = context->GetIsolate();
10883 v8::HandleScope handle_scope(isolate);
10884
10885 Local<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New(isolate);
Andrei Popescu402d9372010-02-26 13:31:12 +000010886 t0->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010887 Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
Andrei Popescu402d9372010-02-26 13:31:12 +000010888 t1->SetHiddenPrototype(true);
10889 t1->InstanceTemplate()->Set(v8_str("y"), v8_num(1));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010890 Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
Andrei Popescu402d9372010-02-26 13:31:12 +000010891 t2->SetHiddenPrototype(true);
10892 t2->InstanceTemplate()->Set(v8_str("z"), v8_num(2));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010893 Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
Andrei Popescu402d9372010-02-26 13:31:12 +000010894 t3->InstanceTemplate()->Set(v8_str("u"), v8_num(3));
10895
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010896 Local<v8::Object> o0 = t0->GetFunction(context.local())
10897 .ToLocalChecked()
10898 ->NewInstance(context.local())
10899 .ToLocalChecked();
10900 Local<v8::Object> o1 = t1->GetFunction(context.local())
10901 .ToLocalChecked()
10902 ->NewInstance(context.local())
10903 .ToLocalChecked();
10904 Local<v8::Object> o2 = t2->GetFunction(context.local())
10905 .ToLocalChecked()
10906 ->NewInstance(context.local())
10907 .ToLocalChecked();
10908 Local<v8::Object> o3 = t3->GetFunction(context.local())
10909 .ToLocalChecked()
10910 ->NewInstance(context.local())
10911 .ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000010912
10913 // Setting the prototype on an object does not skip hidden prototypes.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010914 CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
10915 .ToLocalChecked()
10916 ->Int32Value(context.local())
10917 .FromJust());
10918 CHECK(o0->SetPrototype(context.local(), o1).FromJust());
10919 CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
10920 .ToLocalChecked()
10921 ->Int32Value(context.local())
10922 .FromJust());
10923 CHECK_EQ(1, o0->Get(context.local(), v8_str("y"))
10924 .ToLocalChecked()
10925 ->Int32Value(context.local())
10926 .FromJust());
10927 CHECK(o1->SetPrototype(context.local(), o2).FromJust());
10928 CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
10929 .ToLocalChecked()
10930 ->Int32Value(context.local())
10931 .FromJust());
10932 CHECK_EQ(1, o0->Get(context.local(), v8_str("y"))
10933 .ToLocalChecked()
10934 ->Int32Value(context.local())
10935 .FromJust());
10936 CHECK_EQ(2, o0->Get(context.local(), v8_str("z"))
10937 .ToLocalChecked()
10938 ->Int32Value(context.local())
10939 .FromJust());
10940 CHECK(o2->SetPrototype(context.local(), o3).FromJust());
10941 CHECK_EQ(0, o0->Get(context.local(), v8_str("x"))
10942 .ToLocalChecked()
10943 ->Int32Value(context.local())
10944 .FromJust());
10945 CHECK_EQ(1, o0->Get(context.local(), v8_str("y"))
10946 .ToLocalChecked()
10947 ->Int32Value(context.local())
10948 .FromJust());
10949 CHECK_EQ(2, o0->Get(context.local(), v8_str("z"))
10950 .ToLocalChecked()
10951 ->Int32Value(context.local())
10952 .FromJust());
10953 CHECK_EQ(3, o0->Get(context.local(), v8_str("u"))
10954 .ToLocalChecked()
10955 ->Int32Value(context.local())
10956 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000010957
10958 // Getting the prototype of o0 should get the first visible one
10959 // which is o3. Therefore, z should not be defined on the prototype
10960 // object.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010961 Local<Value> proto =
10962 o0->Get(context.local(), v8_str("__proto__")).ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000010963 CHECK(proto->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010964 CHECK(proto.As<v8::Object>()->Equals(context.local(), o3).FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000010965
10966 // However, Object::GetPrototype ignores hidden prototype.
10967 Local<Value> proto0 = o0->GetPrototype();
10968 CHECK(proto0->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010969 CHECK(proto0.As<v8::Object>()->Equals(context.local(), o1).FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000010970
10971 Local<Value> proto1 = o1->GetPrototype();
10972 CHECK(proto1->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010973 CHECK(proto1.As<v8::Object>()->Equals(context.local(), o2).FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000010974
10975 Local<Value> proto2 = o2->GetPrototype();
10976 CHECK(proto2->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010977 CHECK(proto2.As<v8::Object>()->Equals(context.local(), o3).FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000010978}
10979
10980
Ben Murdoch3ef787d2012-04-12 10:51:47 +010010981// Getting property names of an object with a prototype chain that
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010982// triggers dictionary elements in GetOwnPropertyNames() shouldn't
Ben Murdoch3ef787d2012-04-12 10:51:47 +010010983// crash the runtime.
10984THREADED_TEST(Regress91517) {
10985 i::FLAG_allow_natives_syntax = true;
Ben Murdoch3ef787d2012-04-12 10:51:47 +010010986 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010987 v8::Isolate* isolate = context->GetIsolate();
10988 v8::HandleScope handle_scope(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010010989
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010990 Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010010991 t1->SetHiddenPrototype(true);
10992 t1->InstanceTemplate()->Set(v8_str("foo"), v8_num(1));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010993 Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010010994 t2->SetHiddenPrototype(true);
10995 t2->InstanceTemplate()->Set(v8_str("fuz1"), v8_num(2));
Ben Murdoch097c5b22016-05-18 11:27:45 +010010996 t2->InstanceTemplate()->Set(v8_str("objects"),
10997 v8::ObjectTemplate::New(isolate));
Ben Murdoch3ef787d2012-04-12 10:51:47 +010010998 t2->InstanceTemplate()->Set(v8_str("fuz2"), v8_num(2));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010999 Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011000 t3->SetHiddenPrototype(true);
11001 t3->InstanceTemplate()->Set(v8_str("boo"), v8_num(3));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011002 Local<v8::FunctionTemplate> t4 = v8::FunctionTemplate::New(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011003 t4->InstanceTemplate()->Set(v8_str("baz"), v8_num(4));
11004
11005 // Force dictionary-based properties.
11006 i::ScopedVector<char> name_buf(1024);
11007 for (int i = 1; i <= 1000; i++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011008 i::SNPrintF(name_buf, "sdf%d", i);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011009 t2->InstanceTemplate()->Set(v8_str(name_buf.start()), v8_num(2));
11010 }
11011
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011012 Local<v8::Object> o1 = t1->GetFunction(context.local())
11013 .ToLocalChecked()
11014 ->NewInstance(context.local())
11015 .ToLocalChecked();
11016 Local<v8::Object> o2 = t2->GetFunction(context.local())
11017 .ToLocalChecked()
11018 ->NewInstance(context.local())
11019 .ToLocalChecked();
11020 Local<v8::Object> o3 = t3->GetFunction(context.local())
11021 .ToLocalChecked()
11022 ->NewInstance(context.local())
11023 .ToLocalChecked();
11024 Local<v8::Object> o4 = t4->GetFunction(context.local())
11025 .ToLocalChecked()
11026 ->NewInstance(context.local())
11027 .ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011028
11029 // Create prototype chain of hidden prototypes.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011030 CHECK(o4->SetPrototype(context.local(), o3).FromJust());
11031 CHECK(o3->SetPrototype(context.local(), o2).FromJust());
11032 CHECK(o2->SetPrototype(context.local(), o1).FromJust());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011033
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011034 // Call the runtime version of GetOwnPropertyNames() on the natively
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011035 // created object through JavaScript.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011036 CHECK(context->Global()->Set(context.local(), v8_str("obj"), o4).FromJust());
11037 // PROPERTY_FILTER_NONE = 0
11038 CompileRun("var names = %GetOwnPropertyKeys(obj, 0);");
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011039
11040 ExpectInt32("names.length", 1006);
11041 ExpectTrue("names.indexOf(\"baz\") >= 0");
11042 ExpectTrue("names.indexOf(\"boo\") >= 0");
11043 ExpectTrue("names.indexOf(\"foo\") >= 0");
11044 ExpectTrue("names.indexOf(\"fuz1\") >= 0");
Ben Murdoch097c5b22016-05-18 11:27:45 +010011045 ExpectTrue("names.indexOf(\"objects\") >= 0");
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011046 ExpectTrue("names.indexOf(\"fuz2\") >= 0");
11047 ExpectFalse("names[1005] == undefined");
11048}
11049
11050
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011051// Getting property names of an object with a hidden and inherited
11052// prototype should not duplicate the accessor properties inherited.
11053THREADED_TEST(Regress269562) {
11054 i::FLAG_allow_natives_syntax = true;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000011055 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011056 v8::HandleScope handle_scope(context->GetIsolate());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000011057
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011058 Local<v8::FunctionTemplate> t1 =
11059 v8::FunctionTemplate::New(context->GetIsolate());
11060 t1->SetHiddenPrototype(true);
11061
11062 Local<v8::ObjectTemplate> i1 = t1->InstanceTemplate();
11063 i1->SetAccessor(v8_str("foo"),
11064 SimpleAccessorGetter, SimpleAccessorSetter);
11065 i1->SetAccessor(v8_str("bar"),
11066 SimpleAccessorGetter, SimpleAccessorSetter);
11067 i1->SetAccessor(v8_str("baz"),
11068 SimpleAccessorGetter, SimpleAccessorSetter);
11069 i1->Set(v8_str("n1"), v8_num(1));
11070 i1->Set(v8_str("n2"), v8_num(2));
11071
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011072 Local<v8::Object> o1 = t1->GetFunction(context.local())
11073 .ToLocalChecked()
11074 ->NewInstance(context.local())
11075 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011076 Local<v8::FunctionTemplate> t2 =
11077 v8::FunctionTemplate::New(context->GetIsolate());
11078 t2->SetHiddenPrototype(true);
11079
11080 // Inherit from t1 and mark prototype as hidden.
11081 t2->Inherit(t1);
11082 t2->InstanceTemplate()->Set(v8_str("mine"), v8_num(4));
11083
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011084 Local<v8::Object> o2 = t2->GetFunction(context.local())
11085 .ToLocalChecked()
11086 ->NewInstance(context.local())
11087 .ToLocalChecked();
11088 CHECK(o2->SetPrototype(context.local(), o1).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011089
11090 v8::Local<v8::Symbol> sym =
11091 v8::Symbol::New(context->GetIsolate(), v8_str("s1"));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011092 CHECK(o1->Set(context.local(), sym, v8_num(3)).FromJust());
11093 o1->SetPrivate(context.local(),
11094 v8::Private::New(context->GetIsolate(), v8_str("h1")),
11095 v8::Integer::New(context->GetIsolate(), 2013))
11096 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011097
11098 // Call the runtime version of GetOwnPropertyNames() on
11099 // the natively created object through JavaScript.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011100 CHECK(context->Global()->Set(context.local(), v8_str("obj"), o2).FromJust());
11101 CHECK(context->Global()->Set(context.local(), v8_str("sym"), sym).FromJust());
11102 // PROPERTY_FILTER_NONE = 0
11103 CompileRun("var names = %GetOwnPropertyKeys(obj, 0);");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011104
11105 ExpectInt32("names.length", 7);
11106 ExpectTrue("names.indexOf(\"foo\") >= 0");
11107 ExpectTrue("names.indexOf(\"bar\") >= 0");
11108 ExpectTrue("names.indexOf(\"baz\") >= 0");
11109 ExpectTrue("names.indexOf(\"n1\") >= 0");
11110 ExpectTrue("names.indexOf(\"n2\") >= 0");
11111 ExpectTrue("names.indexOf(sym) >= 0");
11112 ExpectTrue("names.indexOf(\"mine\") >= 0");
11113}
11114
11115
11116THREADED_TEST(FunctionReadOnlyPrototype) {
11117 LocalContext context;
11118 v8::Isolate* isolate = context->GetIsolate();
11119 v8::HandleScope handle_scope(isolate);
11120
11121 Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
11122 t1->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(isolate, 42));
Ben Murdoch69a99ed2011-11-30 16:03:39 +000011123 t1->ReadOnlyPrototype();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011124 CHECK(context->Global()
11125 ->Set(context.local(), v8_str("func1"),
11126 t1->GetFunction(context.local()).ToLocalChecked())
11127 .FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000011128 // Configured value of ReadOnly flag.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011129 CHECK(
11130 CompileRun(
11131 "(function() {"
11132 " descriptor = Object.getOwnPropertyDescriptor(func1, 'prototype');"
11133 " return (descriptor['writable'] == false);"
11134 "})()")
11135 ->BooleanValue(context.local())
11136 .FromJust());
11137 CHECK_EQ(
11138 42,
11139 CompileRun("func1.prototype.x")->Int32Value(context.local()).FromJust());
11140 CHECK_EQ(42, CompileRun("func1.prototype = {}; func1.prototype.x")
11141 ->Int32Value(context.local())
11142 .FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000011143
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011144 Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
11145 t2->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(isolate, 42));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011146 CHECK(context->Global()
11147 ->Set(context.local(), v8_str("func2"),
11148 t2->GetFunction(context.local()).ToLocalChecked())
11149 .FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000011150 // Default value of ReadOnly flag.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011151 CHECK(
11152 CompileRun(
11153 "(function() {"
11154 " descriptor = Object.getOwnPropertyDescriptor(func2, 'prototype');"
11155 " return (descriptor['writable'] == true);"
11156 "})()")
11157 ->BooleanValue(context.local())
11158 .FromJust());
11159 CHECK_EQ(
11160 42,
11161 CompileRun("func2.prototype.x")->Int32Value(context.local()).FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000011162}
11163
11164
Andrei Popescu402d9372010-02-26 13:31:12 +000011165THREADED_TEST(SetPrototypeThrows) {
Andrei Popescu402d9372010-02-26 13:31:12 +000011166 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011167 v8::Isolate* isolate = context->GetIsolate();
11168 v8::HandleScope handle_scope(isolate);
Andrei Popescu402d9372010-02-26 13:31:12 +000011169
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011170 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
Andrei Popescu402d9372010-02-26 13:31:12 +000011171
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011172 Local<v8::Object> o0 = t->GetFunction(context.local())
11173 .ToLocalChecked()
11174 ->NewInstance(context.local())
11175 .ToLocalChecked();
11176 Local<v8::Object> o1 = t->GetFunction(context.local())
11177 .ToLocalChecked()
11178 ->NewInstance(context.local())
11179 .ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000011180
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011181 CHECK(o0->SetPrototype(context.local(), o1).FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000011182 // If setting the prototype leads to the cycle, SetPrototype should
11183 // return false and keep VM in sane state.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011184 v8::TryCatch try_catch(isolate);
11185 CHECK(o1->SetPrototype(context.local(), o0).IsNothing());
Andrei Popescu402d9372010-02-26 13:31:12 +000011186 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011187 CHECK(!CcTest::i_isolate()->has_pending_exception());
Andrei Popescu402d9372010-02-26 13:31:12 +000011188
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011189 CHECK_EQ(42, CompileRun("function f() { return 42; }; f()")
11190 ->Int32Value(context.local())
11191 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000011192}
11193
11194
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011195THREADED_TEST(FunctionRemovePrototype) {
Steve Blocka7e24c12009-10-30 11:49:00 +000011196 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011197 v8::Isolate* isolate = context->GetIsolate();
11198 v8::HandleScope handle_scope(isolate);
11199
11200 Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
11201 t1->RemovePrototype();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011202 Local<v8::Function> fun = t1->GetFunction(context.local()).ToLocalChecked();
Ben Murdochc5610432016-08-08 18:44:38 +010011203 CHECK(!fun->IsConstructor());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011204 CHECK(context->Global()->Set(context.local(), v8_str("fun"), fun).FromJust());
11205 CHECK(!CompileRun("'prototype' in fun")
11206 ->BooleanValue(context.local())
11207 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011208
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011209 v8::TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011210 CompileRun("new fun()");
11211 CHECK(try_catch.HasCaught());
11212
11213 try_catch.Reset();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011214 CHECK(fun->NewInstance(context.local()).IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011215 CHECK(try_catch.HasCaught());
11216}
11217
11218
11219THREADED_TEST(GetterSetterExceptions) {
11220 LocalContext context;
11221 v8::Isolate* isolate = context->GetIsolate();
11222 v8::HandleScope handle_scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000011223 CompileRun(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011224 "function Foo() { };"
11225 "function Throw() { throw 5; };"
11226 "var x = { };"
11227 "x.__defineSetter__('set', Throw);"
11228 "x.__defineGetter__('get', Throw);");
11229 Local<v8::Object> x = Local<v8::Object>::Cast(
11230 context->Global()->Get(context.local(), v8_str("x")).ToLocalChecked());
11231 v8::TryCatch try_catch(isolate);
11232 CHECK(x->Set(context.local(), v8_str("set"), v8::Integer::New(isolate, 8))
11233 .IsNothing());
11234 CHECK(x->Get(context.local(), v8_str("get")).IsEmpty());
11235 CHECK(x->Set(context.local(), v8_str("set"), v8::Integer::New(isolate, 8))
11236 .IsNothing());
11237 CHECK(x->Get(context.local(), v8_str("get")).IsEmpty());
11238 CHECK(x->Set(context.local(), v8_str("set"), v8::Integer::New(isolate, 8))
11239 .IsNothing());
11240 CHECK(x->Get(context.local(), v8_str("get")).IsEmpty());
11241 CHECK(x->Set(context.local(), v8_str("set"), v8::Integer::New(isolate, 8))
11242 .IsNothing());
11243 CHECK(x->Get(context.local(), v8_str("get")).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +000011244}
11245
11246
11247THREADED_TEST(Constructor) {
Steve Blocka7e24c12009-10-30 11:49:00 +000011248 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011249 v8::Isolate* isolate = context->GetIsolate();
11250 v8::HandleScope handle_scope(isolate);
11251 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000011252 templ->SetClassName(v8_str("Fun"));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011253 Local<Function> cons = templ->GetFunction(context.local()).ToLocalChecked();
11254 CHECK(
11255 context->Global()->Set(context.local(), v8_str("Fun"), cons).FromJust());
11256 Local<v8::Object> inst = cons->NewInstance(context.local()).ToLocalChecked();
11257 i::Handle<i::JSReceiver> obj(v8::Utils::OpenHandle(*inst));
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011258 CHECK(obj->IsJSObject());
Steve Blocka7e24c12009-10-30 11:49:00 +000011259 Local<Value> value = CompileRun("(new Fun()).constructor === Fun");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011260 CHECK(value->BooleanValue(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011261}
11262
Ben Murdoch257744e2011-11-30 15:57:28 +000011263
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011264static void ConstructorCallback(
11265 const v8::FunctionCallbackInfo<v8::Value>& args) {
Ben Murdoch257744e2011-11-30 15:57:28 +000011266 ApiTestFuzzer::Fuzz();
11267 Local<Object> This;
11268
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011269 v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
Ben Murdoch257744e2011-11-30 15:57:28 +000011270 if (args.IsConstructCall()) {
11271 Local<Object> Holder = args.Holder();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011272 This = Object::New(args.GetIsolate());
Ben Murdoch257744e2011-11-30 15:57:28 +000011273 Local<Value> proto = Holder->GetPrototype();
11274 if (proto->IsObject()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011275 This->SetPrototype(context, proto).FromJust();
Ben Murdoch257744e2011-11-30 15:57:28 +000011276 }
11277 } else {
11278 This = args.This();
11279 }
11280
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011281 This->Set(context, v8_str("a"), args[0]).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011282 args.GetReturnValue().Set(This);
Ben Murdoch257744e2011-11-30 15:57:28 +000011283}
11284
11285
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011286static void FakeConstructorCallback(
11287 const v8::FunctionCallbackInfo<v8::Value>& args) {
Ben Murdoch257744e2011-11-30 15:57:28 +000011288 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011289 args.GetReturnValue().Set(args[0]);
Ben Murdoch257744e2011-11-30 15:57:28 +000011290}
11291
11292
11293THREADED_TEST(ConstructorForObject) {
Ben Murdoch257744e2011-11-30 15:57:28 +000011294 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011295 v8::Isolate* isolate = context->GetIsolate();
11296 v8::HandleScope handle_scope(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011297
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011298 {
11299 Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011300 instance_template->SetCallAsFunctionHandler(ConstructorCallback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011301 Local<Object> instance =
11302 instance_template->NewInstance(context.local()).ToLocalChecked();
11303 CHECK(context->Global()
11304 ->Set(context.local(), v8_str("obj"), instance)
11305 .FromJust());
11306 v8::TryCatch try_catch(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011307 Local<Value> value;
11308 CHECK(!try_catch.HasCaught());
11309
11310 // Call the Object's constructor with a 32-bit signed integer.
11311 value = CompileRun("(function() { var o = new obj(28); return o.a; })()");
11312 CHECK(!try_catch.HasCaught());
11313 CHECK(value->IsInt32());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011314 CHECK_EQ(28, value->Int32Value(context.local()).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000011315
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011316 Local<Value> args1[] = {v8_num(28)};
11317 Local<Value> value_obj1 =
11318 instance->CallAsConstructor(context.local(), 1, args1).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011319 CHECK(value_obj1->IsObject());
11320 Local<Object> object1 = Local<Object>::Cast(value_obj1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011321 value = object1->Get(context.local(), v8_str("a")).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011322 CHECK(value->IsInt32());
11323 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011324 CHECK_EQ(28, value->Int32Value(context.local()).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000011325
11326 // Call the Object's constructor with a String.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011327 value =
11328 CompileRun("(function() { var o = new obj('tipli'); return o.a; })()");
Ben Murdoch257744e2011-11-30 15:57:28 +000011329 CHECK(!try_catch.HasCaught());
11330 CHECK(value->IsString());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011331 String::Utf8Value string_value1(
11332 value->ToString(context.local()).ToLocalChecked());
11333 CHECK_EQ(0, strcmp("tipli", *string_value1));
Ben Murdoch257744e2011-11-30 15:57:28 +000011334
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011335 Local<Value> args2[] = {v8_str("tipli")};
11336 Local<Value> value_obj2 =
11337 instance->CallAsConstructor(context.local(), 1, args2).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011338 CHECK(value_obj2->IsObject());
11339 Local<Object> object2 = Local<Object>::Cast(value_obj2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011340 value = object2->Get(context.local(), v8_str("a")).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011341 CHECK(!try_catch.HasCaught());
11342 CHECK(value->IsString());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011343 String::Utf8Value string_value2(
11344 value->ToString(context.local()).ToLocalChecked());
11345 CHECK_EQ(0, strcmp("tipli", *string_value2));
Ben Murdoch257744e2011-11-30 15:57:28 +000011346
11347 // Call the Object's constructor with a Boolean.
11348 value = CompileRun("(function() { var o = new obj(true); return o.a; })()");
11349 CHECK(!try_catch.HasCaught());
11350 CHECK(value->IsBoolean());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011351 CHECK_EQ(true, value->BooleanValue(context.local()).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000011352
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011353 Local<Value> args3[] = {v8::True(isolate)};
11354 Local<Value> value_obj3 =
11355 instance->CallAsConstructor(context.local(), 1, args3).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011356 CHECK(value_obj3->IsObject());
11357 Local<Object> object3 = Local<Object>::Cast(value_obj3);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011358 value = object3->Get(context.local(), v8_str("a")).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011359 CHECK(!try_catch.HasCaught());
11360 CHECK(value->IsBoolean());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011361 CHECK_EQ(true, value->BooleanValue(context.local()).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000011362
11363 // Call the Object's constructor with undefined.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011364 Local<Value> args4[] = {v8::Undefined(isolate)};
11365 Local<Value> value_obj4 =
11366 instance->CallAsConstructor(context.local(), 1, args4).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011367 CHECK(value_obj4->IsObject());
11368 Local<Object> object4 = Local<Object>::Cast(value_obj4);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011369 value = object4->Get(context.local(), v8_str("a")).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011370 CHECK(!try_catch.HasCaught());
11371 CHECK(value->IsUndefined());
11372
11373 // Call the Object's constructor with null.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011374 Local<Value> args5[] = {v8::Null(isolate)};
11375 Local<Value> value_obj5 =
11376 instance->CallAsConstructor(context.local(), 1, args5).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011377 CHECK(value_obj5->IsObject());
11378 Local<Object> object5 = Local<Object>::Cast(value_obj5);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011379 value = object5->Get(context.local(), v8_str("a")).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011380 CHECK(!try_catch.HasCaught());
11381 CHECK(value->IsNull());
11382 }
11383
11384 // Check exception handling when there is no constructor set for the Object.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011385 {
11386 Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
11387 Local<Object> instance =
11388 instance_template->NewInstance(context.local()).ToLocalChecked();
11389 CHECK(context->Global()
11390 ->Set(context.local(), v8_str("obj2"), instance)
11391 .FromJust());
11392 v8::TryCatch try_catch(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011393 Local<Value> value;
11394 CHECK(!try_catch.HasCaught());
11395
11396 value = CompileRun("new obj2(28)");
11397 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011398 String::Utf8Value exception_value1(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011399 CHECK_EQ(0,
11400 strcmp("TypeError: obj2 is not a constructor", *exception_value1));
Ben Murdoch257744e2011-11-30 15:57:28 +000011401 try_catch.Reset();
11402
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011403 Local<Value> args[] = {v8_num(29)};
11404 CHECK(instance->CallAsConstructor(context.local(), 1, args).IsEmpty());
Ben Murdoch257744e2011-11-30 15:57:28 +000011405 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011406 String::Utf8Value exception_value2(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011407 CHECK_EQ(
11408 0, strcmp("TypeError: object is not a constructor", *exception_value2));
Ben Murdoch257744e2011-11-30 15:57:28 +000011409 try_catch.Reset();
11410 }
11411
11412 // Check the case when constructor throws exception.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011413 {
11414 Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011415 instance_template->SetCallAsFunctionHandler(ThrowValue);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011416 Local<Object> instance =
11417 instance_template->NewInstance(context.local()).ToLocalChecked();
11418 CHECK(context->Global()
11419 ->Set(context.local(), v8_str("obj3"), instance)
11420 .FromJust());
11421 v8::TryCatch try_catch(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011422 Local<Value> value;
11423 CHECK(!try_catch.HasCaught());
11424
11425 value = CompileRun("new obj3(22)");
11426 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011427 String::Utf8Value exception_value1(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011428 CHECK_EQ(0, strcmp("22", *exception_value1));
Ben Murdoch257744e2011-11-30 15:57:28 +000011429 try_catch.Reset();
11430
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011431 Local<Value> args[] = {v8_num(23)};
11432 CHECK(instance->CallAsConstructor(context.local(), 1, args).IsEmpty());
Ben Murdoch257744e2011-11-30 15:57:28 +000011433 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011434 String::Utf8Value exception_value2(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011435 CHECK_EQ(0, strcmp("23", *exception_value2));
Ben Murdoch257744e2011-11-30 15:57:28 +000011436 try_catch.Reset();
11437 }
11438
11439 // Check whether constructor returns with an object or non-object.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011440 {
11441 Local<FunctionTemplate> function_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011442 FunctionTemplate::New(isolate, FakeConstructorCallback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011443 Local<Function> function =
11444 function_template->GetFunction(context.local()).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011445 Local<Object> instance1 = function;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011446 CHECK(context->Global()
11447 ->Set(context.local(), v8_str("obj4"), instance1)
11448 .FromJust());
11449 v8::TryCatch try_catch(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011450 Local<Value> value;
11451 CHECK(!try_catch.HasCaught());
11452
11453 CHECK(instance1->IsObject());
11454 CHECK(instance1->IsFunction());
11455
11456 value = CompileRun("new obj4(28)");
11457 CHECK(!try_catch.HasCaught());
11458 CHECK(value->IsObject());
11459
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011460 Local<Value> args1[] = {v8_num(28)};
11461 value = instance1->CallAsConstructor(context.local(), 1, args1)
11462 .ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011463 CHECK(!try_catch.HasCaught());
11464 CHECK(value->IsObject());
11465
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011466 Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011467 instance_template->SetCallAsFunctionHandler(FakeConstructorCallback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011468 Local<Object> instance2 =
11469 instance_template->NewInstance(context.local()).ToLocalChecked();
11470 CHECK(context->Global()
11471 ->Set(context.local(), v8_str("obj5"), instance2)
11472 .FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000011473 CHECK(!try_catch.HasCaught());
11474
11475 CHECK(instance2->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011476 CHECK(instance2->IsFunction());
Ben Murdoch257744e2011-11-30 15:57:28 +000011477
11478 value = CompileRun("new obj5(28)");
11479 CHECK(!try_catch.HasCaught());
11480 CHECK(!value->IsObject());
11481
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011482 Local<Value> args2[] = {v8_num(28)};
11483 value = instance2->CallAsConstructor(context.local(), 1, args2)
11484 .ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011485 CHECK(!try_catch.HasCaught());
11486 CHECK(!value->IsObject());
11487 }
11488}
11489
11490
Steve Blocka7e24c12009-10-30 11:49:00 +000011491THREADED_TEST(FunctionDescriptorException) {
Steve Blocka7e24c12009-10-30 11:49:00 +000011492 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011493 v8::Isolate* isolate = context->GetIsolate();
11494 v8::HandleScope handle_scope(isolate);
11495 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000011496 templ->SetClassName(v8_str("Fun"));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011497 Local<Function> cons = templ->GetFunction(context.local()).ToLocalChecked();
11498 CHECK(
11499 context->Global()->Set(context.local(), v8_str("Fun"), cons).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011500 Local<Value> value = CompileRun(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011501 "function test() {"
11502 " try {"
11503 " (new Fun()).blah()"
11504 " } catch (e) {"
11505 " var str = String(e);"
11506 // " if (str.indexOf('TypeError') == -1) return 1;"
11507 // " if (str.indexOf('[object Fun]') != -1) return 2;"
11508 // " if (str.indexOf('#<Fun>') == -1) return 3;"
11509 " return 0;"
11510 " }"
11511 " return 4;"
11512 "}"
11513 "test();");
11514 CHECK_EQ(0, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011515}
11516
11517
11518THREADED_TEST(EvalAliasedDynamic) {
Steve Blocka7e24c12009-10-30 11:49:00 +000011519 LocalContext current;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011520 v8::HandleScope scope(current->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000011521
11522 // Tests where aliased eval can only be resolved dynamically.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011523 Local<Script> script = v8_compile(
11524 "function f(x) { "
11525 " var foo = 2;"
11526 " with (x) { return eval('foo'); }"
11527 "}"
11528 "foo = 0;"
11529 "result1 = f(new Object());"
11530 "result2 = f(this);"
11531 "var x = new Object();"
11532 "x.eval = function(x) { return 1; };"
11533 "result3 = f(x);");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011534 script->Run(current.local()).ToLocalChecked();
11535 CHECK_EQ(2, current->Global()
11536 ->Get(current.local(), v8_str("result1"))
11537 .ToLocalChecked()
11538 ->Int32Value(current.local())
11539 .FromJust());
11540 CHECK_EQ(0, current->Global()
11541 ->Get(current.local(), v8_str("result2"))
11542 .ToLocalChecked()
11543 ->Int32Value(current.local())
11544 .FromJust());
11545 CHECK_EQ(1, current->Global()
11546 ->Get(current.local(), v8_str("result3"))
11547 .ToLocalChecked()
11548 ->Int32Value(current.local())
11549 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011550
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011551 v8::TryCatch try_catch(current->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011552 script = v8_compile(
11553 "function f(x) { "
11554 " var bar = 2;"
11555 " with (x) { return eval('bar'); }"
11556 "}"
11557 "result4 = f(this)");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011558 script->Run(current.local()).ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011559 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011560 CHECK_EQ(2, current->Global()
11561 ->Get(current.local(), v8_str("result4"))
11562 .ToLocalChecked()
11563 ->Int32Value(current.local())
11564 .FromJust());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011565
Steve Blocka7e24c12009-10-30 11:49:00 +000011566 try_catch.Reset();
11567}
11568
11569
11570THREADED_TEST(CrossEval) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011571 v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000011572 LocalContext other;
11573 LocalContext current;
11574
11575 Local<String> token = v8_str("<security token>");
11576 other->SetSecurityToken(token);
11577 current->SetSecurityToken(token);
11578
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011579 // Set up reference from current to other.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011580 CHECK(current->Global()
11581 ->Set(current.local(), v8_str("other"), other->Global())
11582 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011583
11584 // Check that new variables are introduced in other context.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011585 Local<Script> script = v8_compile("other.eval('var foo = 1234')");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011586 script->Run(current.local()).ToLocalChecked();
11587 Local<Value> foo =
11588 other->Global()->Get(current.local(), v8_str("foo")).ToLocalChecked();
11589 CHECK_EQ(1234, foo->Int32Value(other.local()).FromJust());
11590 CHECK(!current->Global()->Has(current.local(), v8_str("foo")).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011591
11592 // Check that writing to non-existing properties introduces them in
11593 // the other context.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011594 script = v8_compile("other.eval('na = 1234')");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011595 script->Run(current.local()).ToLocalChecked();
11596 CHECK_EQ(1234, other->Global()
11597 ->Get(current.local(), v8_str("na"))
11598 .ToLocalChecked()
11599 ->Int32Value(other.local())
11600 .FromJust());
11601 CHECK(!current->Global()->Has(current.local(), v8_str("na")).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011602
11603 // Check that global variables in current context are not visible in other
11604 // context.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011605 v8::TryCatch try_catch(CcTest::isolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011606 script = v8_compile("var bar = 42; other.eval('bar');");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011607 CHECK(script->Run(current.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +000011608 CHECK(try_catch.HasCaught());
11609 try_catch.Reset();
11610
11611 // Check that local variables in current context are not visible in other
11612 // context.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011613 script = v8_compile(
11614 "(function() { "
11615 " var baz = 87;"
11616 " return other.eval('baz');"
11617 "})();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011618 CHECK(script->Run(current.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +000011619 CHECK(try_catch.HasCaught());
11620 try_catch.Reset();
11621
11622 // Check that global variables in the other environment are visible
11623 // when evaluting code.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011624 CHECK(other->Global()
11625 ->Set(other.local(), v8_str("bis"), v8_num(1234))
11626 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011627 script = v8_compile("other.eval('bis')");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011628 CHECK_EQ(1234, script->Run(current.local())
11629 .ToLocalChecked()
11630 ->Int32Value(current.local())
11631 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011632 CHECK(!try_catch.HasCaught());
11633
11634 // Check that the 'this' pointer points to the global object evaluating
11635 // code.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011636 CHECK(other->Global()
11637 ->Set(current.local(), v8_str("t"), other->Global())
11638 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011639 script = v8_compile("other.eval('this == t')");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011640 Local<Value> result = script->Run(current.local()).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000011641 CHECK(result->IsTrue());
11642 CHECK(!try_catch.HasCaught());
11643
11644 // Check that variables introduced in with-statement are not visible in
11645 // other context.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011646 script = v8_compile("with({x:2}){other.eval('x')}");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011647 CHECK(script->Run(current.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +000011648 CHECK(try_catch.HasCaught());
11649 try_catch.Reset();
11650
11651 // Check that you cannot use 'eval.call' with another object than the
11652 // current global object.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011653 script = v8_compile("other.y = 1; eval.call(other, 'y')");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011654 CHECK(script->Run(current.local()).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +000011655 CHECK(try_catch.HasCaught());
11656}
11657
11658
11659// Test that calling eval in a context which has been detached from
Emily Bernierd0a1eb72015-03-24 16:35:39 -040011660// its global proxy works.
Steve Blocka7e24c12009-10-30 11:49:00 +000011661THREADED_TEST(EvalInDetachedGlobal) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011662 v8::Isolate* isolate = CcTest::isolate();
11663 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000011664
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011665 v8::Local<Context> context0 = Context::New(isolate);
11666 v8::Local<Context> context1 = Context::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000011667
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011668 // Set up function in context0 that uses eval from context0.
Steve Blocka7e24c12009-10-30 11:49:00 +000011669 context0->Enter();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011670 v8::Local<v8::Value> fun = CompileRun(
11671 "var x = 42;"
11672 "(function() {"
11673 " var e = eval;"
11674 " return function(s) { return e(s); }"
11675 "})()");
Steve Blocka7e24c12009-10-30 11:49:00 +000011676 context0->Exit();
11677
11678 // Put the function into context1 and call it before and after
11679 // detaching the global. Before detaching, the call succeeds and
11680 // after detaching and exception is thrown.
11681 context1->Enter();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011682 CHECK(context1->Global()->Set(context1, v8_str("fun"), fun).FromJust());
11683 v8::Local<v8::Value> x_value = CompileRun("fun('x')");
11684 CHECK_EQ(42, x_value->Int32Value(context1).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011685 context0->DetachGlobal();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011686 v8::TryCatch catcher(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000011687 x_value = CompileRun("fun('x')");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011688 CHECK_EQ(42, x_value->Int32Value(context1).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011689 context1->Exit();
Steve Blocka7e24c12009-10-30 11:49:00 +000011690}
11691
11692
11693THREADED_TEST(CrossLazyLoad) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011694 v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000011695 LocalContext other;
11696 LocalContext current;
11697
11698 Local<String> token = v8_str("<security token>");
11699 other->SetSecurityToken(token);
11700 current->SetSecurityToken(token);
11701
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011702 // Set up reference from current to other.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011703 CHECK(current->Global()
11704 ->Set(current.local(), v8_str("other"), other->Global())
11705 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011706
11707 // Trigger lazy loading in other context.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011708 Local<Script> script = v8_compile("other.eval('new Date(42)')");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011709 Local<Value> value = script->Run(current.local()).ToLocalChecked();
11710 CHECK_EQ(42.0, value->NumberValue(current.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011711}
11712
11713
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011714static void call_as_function(const v8::FunctionCallbackInfo<v8::Value>& args) {
Andrei Popescu402d9372010-02-26 13:31:12 +000011715 ApiTestFuzzer::Fuzz();
Steve Blocka7e24c12009-10-30 11:49:00 +000011716 if (args.IsConstructCall()) {
11717 if (args[0]->IsInt32()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011718 args.GetReturnValue().Set(
11719 v8_num(-args[0]
11720 ->Int32Value(args.GetIsolate()->GetCurrentContext())
11721 .FromJust()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011722 return;
Steve Blocka7e24c12009-10-30 11:49:00 +000011723 }
11724 }
11725
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011726 args.GetReturnValue().Set(args[0]);
11727}
11728
11729
11730static void ReturnThis(const v8::FunctionCallbackInfo<v8::Value>& args) {
11731 args.GetReturnValue().Set(args.This());
Steve Blocka7e24c12009-10-30 11:49:00 +000011732}
11733
11734
11735// Test that a call handler can be set for objects which will allow
11736// non-function objects created through the API to be called as
11737// functions.
11738THREADED_TEST(CallAsFunction) {
Steve Blocka7e24c12009-10-30 11:49:00 +000011739 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011740 v8::Isolate* isolate = context->GetIsolate();
11741 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000011742
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011743 {
11744 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011745 Local<ObjectTemplate> instance_template = t->InstanceTemplate();
11746 instance_template->SetCallAsFunctionHandler(call_as_function);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011747 Local<v8::Object> instance = t->GetFunction(context.local())
11748 .ToLocalChecked()
11749 ->NewInstance(context.local())
11750 .ToLocalChecked();
11751 CHECK(context->Global()
11752 ->Set(context.local(), v8_str("obj"), instance)
11753 .FromJust());
11754 v8::TryCatch try_catch(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011755 Local<Value> value;
11756 CHECK(!try_catch.HasCaught());
Steve Blocka7e24c12009-10-30 11:49:00 +000011757
Ben Murdoch257744e2011-11-30 15:57:28 +000011758 value = CompileRun("obj(42)");
11759 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011760 CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011761
Ben Murdoch257744e2011-11-30 15:57:28 +000011762 value = CompileRun("(function(o){return o(49)})(obj)");
11763 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011764 CHECK_EQ(49, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011765
Ben Murdoch257744e2011-11-30 15:57:28 +000011766 // test special case of call as function
11767 value = CompileRun("[obj]['0'](45)");
11768 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011769 CHECK_EQ(45, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011770
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011771 value = CompileRun(
11772 "obj.call = Function.prototype.call;"
11773 "obj.call(null, 87)");
Ben Murdoch257744e2011-11-30 15:57:28 +000011774 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011775 CHECK_EQ(87, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011776
Ben Murdoch257744e2011-11-30 15:57:28 +000011777 // Regression tests for bug #1116356: Calling call through call/apply
11778 // must work for non-function receivers.
11779 const char* apply_99 = "Function.prototype.call.apply(obj, [this, 99])";
11780 value = CompileRun(apply_99);
11781 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011782 CHECK_EQ(99, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011783
Ben Murdoch257744e2011-11-30 15:57:28 +000011784 const char* call_17 = "Function.prototype.call.call(obj, this, 17)";
11785 value = CompileRun(call_17);
11786 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011787 CHECK_EQ(17, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000011788
Ben Murdoch257744e2011-11-30 15:57:28 +000011789 // Check that the call-as-function handler can be called through
11790 // new.
11791 value = CompileRun("new obj(43)");
11792 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011793 CHECK_EQ(-43, value->Int32Value(context.local()).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000011794
11795 // Check that the call-as-function handler can be called through
11796 // the API.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011797 v8::Local<Value> args[] = {v8_num(28)};
11798 value = instance->CallAsFunction(context.local(), instance, 1, args)
11799 .ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000011800 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011801 CHECK_EQ(28, value->Int32Value(context.local()).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000011802 }
11803
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011804 {
11805 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010011806 Local<ObjectTemplate> instance_template(t->InstanceTemplate());
11807 USE(instance_template);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011808 Local<v8::Object> instance = t->GetFunction(context.local())
11809 .ToLocalChecked()
11810 ->NewInstance(context.local())
11811 .ToLocalChecked();
11812 CHECK(context->Global()
11813 ->Set(context.local(), v8_str("obj2"), instance)
11814 .FromJust());
11815 v8::TryCatch try_catch(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011816 Local<Value> value;
11817 CHECK(!try_catch.HasCaught());
11818
11819 // Call an object without call-as-function handler through the JS
11820 value = CompileRun("obj2(28)");
11821 CHECK(value.IsEmpty());
11822 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011823 String::Utf8Value exception_value1(try_catch.Exception());
11824 // TODO(verwaest): Better message
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011825 CHECK_EQ(0, strcmp("TypeError: obj2 is not a function", *exception_value1));
Ben Murdoch257744e2011-11-30 15:57:28 +000011826 try_catch.Reset();
11827
11828 // Call an object without call-as-function handler through the API
11829 value = CompileRun("obj2(28)");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011830 v8::Local<Value> args[] = {v8_num(28)};
11831 CHECK(
11832 instance->CallAsFunction(context.local(), instance, 1, args).IsEmpty());
Ben Murdoch257744e2011-11-30 15:57:28 +000011833 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011834 String::Utf8Value exception_value2(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011835 CHECK_EQ(0,
11836 strcmp("TypeError: object is not a function", *exception_value2));
Ben Murdoch257744e2011-11-30 15:57:28 +000011837 try_catch.Reset();
11838 }
11839
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011840 {
11841 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011842 Local<ObjectTemplate> instance_template = t->InstanceTemplate();
11843 instance_template->SetCallAsFunctionHandler(ThrowValue);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011844 Local<v8::Object> instance = t->GetFunction(context.local())
11845 .ToLocalChecked()
11846 ->NewInstance(context.local())
11847 .ToLocalChecked();
11848 CHECK(context->Global()
11849 ->Set(context.local(), v8_str("obj3"), instance)
11850 .FromJust());
11851 v8::TryCatch try_catch(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011852 Local<Value> value;
11853 CHECK(!try_catch.HasCaught());
11854
11855 // Catch the exception which is thrown by call-as-function handler
11856 value = CompileRun("obj3(22)");
11857 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011858 String::Utf8Value exception_value1(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011859 CHECK_EQ(0, strcmp("22", *exception_value1));
Ben Murdoch257744e2011-11-30 15:57:28 +000011860 try_catch.Reset();
11861
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011862 v8::Local<Value> args[] = {v8_num(23)};
11863 CHECK(
11864 instance->CallAsFunction(context.local(), instance, 1, args).IsEmpty());
Ben Murdoch257744e2011-11-30 15:57:28 +000011865 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011866 String::Utf8Value exception_value2(try_catch.Exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011867 CHECK_EQ(0, strcmp("23", *exception_value2));
Ben Murdoch257744e2011-11-30 15:57:28 +000011868 try_catch.Reset();
11869 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011870
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011871 {
11872 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011873 Local<ObjectTemplate> instance_template = t->InstanceTemplate();
11874 instance_template->SetCallAsFunctionHandler(ReturnThis);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011875 Local<v8::Object> instance = t->GetFunction(context.local())
11876 .ToLocalChecked()
11877 ->NewInstance(context.local())
11878 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011879
11880 Local<v8::Value> a1 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011881 instance->CallAsFunction(context.local(), v8::Undefined(isolate), 0,
11882 NULL)
11883 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011884 CHECK(a1->StrictEquals(instance));
11885 Local<v8::Value> a2 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011886 instance->CallAsFunction(context.local(), v8::Null(isolate), 0, NULL)
11887 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011888 CHECK(a2->StrictEquals(instance));
11889 Local<v8::Value> a3 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011890 instance->CallAsFunction(context.local(), v8_num(42), 0, NULL)
11891 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011892 CHECK(a3->StrictEquals(instance));
11893 Local<v8::Value> a4 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011894 instance->CallAsFunction(context.local(), v8_str("hello"), 0, NULL)
11895 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011896 CHECK(a4->StrictEquals(instance));
11897 Local<v8::Value> a5 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011898 instance->CallAsFunction(context.local(), v8::True(isolate), 0, NULL)
11899 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011900 CHECK(a5->StrictEquals(instance));
11901 }
11902
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011903 {
11904 CompileRun(
11905 "function ReturnThisSloppy() {"
11906 " return this;"
11907 "}"
11908 "function ReturnThisStrict() {"
11909 " 'use strict';"
11910 " return this;"
11911 "}");
11912 Local<Function> ReturnThisSloppy = Local<Function>::Cast(
11913 context->Global()
11914 ->Get(context.local(), v8_str("ReturnThisSloppy"))
11915 .ToLocalChecked());
11916 Local<Function> ReturnThisStrict = Local<Function>::Cast(
11917 context->Global()
11918 ->Get(context.local(), v8_str("ReturnThisStrict"))
11919 .ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011920
11921 Local<v8::Value> a1 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011922 ReturnThisSloppy->CallAsFunction(context.local(),
11923 v8::Undefined(isolate), 0, NULL)
11924 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011925 CHECK(a1->StrictEquals(context->Global()));
11926 Local<v8::Value> a2 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011927 ReturnThisSloppy->CallAsFunction(context.local(), v8::Null(isolate), 0,
11928 NULL)
11929 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011930 CHECK(a2->StrictEquals(context->Global()));
11931 Local<v8::Value> a3 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011932 ReturnThisSloppy->CallAsFunction(context.local(), v8_num(42), 0, NULL)
11933 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011934 CHECK(a3->IsNumberObject());
11935 CHECK_EQ(42.0, a3.As<v8::NumberObject>()->ValueOf());
11936 Local<v8::Value> a4 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011937 ReturnThisSloppy->CallAsFunction(context.local(), v8_str("hello"), 0,
11938 NULL)
11939 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011940 CHECK(a4->IsStringObject());
11941 CHECK(a4.As<v8::StringObject>()->ValueOf()->StrictEquals(v8_str("hello")));
11942 Local<v8::Value> a5 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011943 ReturnThisSloppy->CallAsFunction(context.local(), v8::True(isolate), 0,
11944 NULL)
11945 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011946 CHECK(a5->IsBooleanObject());
11947 CHECK(a5.As<v8::BooleanObject>()->ValueOf());
11948
11949 Local<v8::Value> a6 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011950 ReturnThisStrict->CallAsFunction(context.local(),
11951 v8::Undefined(isolate), 0, NULL)
11952 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011953 CHECK(a6->IsUndefined());
11954 Local<v8::Value> a7 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011955 ReturnThisStrict->CallAsFunction(context.local(), v8::Null(isolate), 0,
11956 NULL)
11957 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011958 CHECK(a7->IsNull());
11959 Local<v8::Value> a8 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011960 ReturnThisStrict->CallAsFunction(context.local(), v8_num(42), 0, NULL)
11961 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011962 CHECK(a8->StrictEquals(v8_num(42)));
11963 Local<v8::Value> a9 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011964 ReturnThisStrict->CallAsFunction(context.local(), v8_str("hello"), 0,
11965 NULL)
11966 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011967 CHECK(a9->StrictEquals(v8_str("hello")));
11968 Local<v8::Value> a10 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011969 ReturnThisStrict->CallAsFunction(context.local(), v8::True(isolate), 0,
11970 NULL)
11971 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011972 CHECK(a10->StrictEquals(v8::True(isolate)));
11973 }
Ben Murdoch257744e2011-11-30 15:57:28 +000011974}
11975
11976
11977// Check whether a non-function object is callable.
11978THREADED_TEST(CallableObject) {
Ben Murdoch257744e2011-11-30 15:57:28 +000011979 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011980 v8::Isolate* isolate = context->GetIsolate();
11981 v8::HandleScope scope(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011982
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011983 {
11984 Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011985 instance_template->SetCallAsFunctionHandler(call_as_function);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011986 Local<Object> instance =
11987 instance_template->NewInstance(context.local()).ToLocalChecked();
11988 v8::TryCatch try_catch(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011989
11990 CHECK(instance->IsCallable());
11991 CHECK(!try_catch.HasCaught());
11992 }
11993
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000011994 {
11995 Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
11996 Local<Object> instance =
11997 instance_template->NewInstance(context.local()).ToLocalChecked();
11998 v8::TryCatch try_catch(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000011999
12000 CHECK(!instance->IsCallable());
12001 CHECK(!try_catch.HasCaught());
12002 }
12003
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012004 {
12005 Local<FunctionTemplate> function_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012006 FunctionTemplate::New(isolate, call_as_function);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012007 Local<Function> function =
12008 function_template->GetFunction(context.local()).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000012009 Local<Object> instance = function;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012010 v8::TryCatch try_catch(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000012011
12012 CHECK(instance->IsCallable());
12013 CHECK(!try_catch.HasCaught());
12014 }
12015
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012016 {
12017 Local<FunctionTemplate> function_template = FunctionTemplate::New(isolate);
12018 Local<Function> function =
12019 function_template->GetFunction(context.local()).ToLocalChecked();
Ben Murdoch257744e2011-11-30 15:57:28 +000012020 Local<Object> instance = function;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012021 v8::TryCatch try_catch(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000012022
12023 CHECK(instance->IsCallable());
12024 CHECK(!try_catch.HasCaught());
12025 }
Steve Blocka7e24c12009-10-30 11:49:00 +000012026}
12027
12028
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012029THREADED_TEST(Regress567998) {
12030 LocalContext env;
12031 v8::HandleScope scope(env->GetIsolate());
12032
12033 Local<v8::FunctionTemplate> desc =
12034 v8::FunctionTemplate::New(env->GetIsolate());
12035 desc->InstanceTemplate()->MarkAsUndetectable(); // undetectable
12036 desc->InstanceTemplate()->SetCallAsFunctionHandler(ReturnThis); // callable
12037
12038 Local<v8::Object> obj = desc->GetFunction(env.local())
12039 .ToLocalChecked()
12040 ->NewInstance(env.local())
12041 .ToLocalChecked();
12042 CHECK(
12043 env->Global()->Set(env.local(), v8_str("undetectable"), obj).FromJust());
12044
12045 ExpectString("undetectable.toString()", "[object Object]");
12046 ExpectString("typeof undetectable", "undefined");
12047 ExpectString("typeof(undetectable)", "undefined");
12048 ExpectBoolean("typeof undetectable == 'undefined'", true);
12049 ExpectBoolean("typeof undetectable == 'object'", false);
12050 ExpectBoolean("if (undetectable) { true; } else { false; }", false);
12051 ExpectBoolean("!undetectable", true);
12052
12053 ExpectObject("true&&undetectable", obj);
12054 ExpectBoolean("false&&undetectable", false);
12055 ExpectBoolean("true||undetectable", true);
12056 ExpectObject("false||undetectable", obj);
12057
12058 ExpectObject("undetectable&&true", obj);
12059 ExpectObject("undetectable&&false", obj);
12060 ExpectBoolean("undetectable||true", true);
12061 ExpectBoolean("undetectable||false", false);
12062
12063 ExpectBoolean("undetectable==null", true);
12064 ExpectBoolean("null==undetectable", true);
12065 ExpectBoolean("undetectable==undefined", true);
12066 ExpectBoolean("undefined==undetectable", true);
12067 ExpectBoolean("undetectable==undetectable", true);
12068
12069 ExpectBoolean("undetectable===null", false);
12070 ExpectBoolean("null===undetectable", false);
12071 ExpectBoolean("undetectable===undefined", false);
12072 ExpectBoolean("undefined===undetectable", false);
12073 ExpectBoolean("undetectable===undetectable", true);
12074}
12075
12076
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012077static int Recurse(v8::Isolate* isolate, int depth, int iterations) {
12078 v8::HandleScope scope(isolate);
12079 if (depth == 0) return v8::HandleScope::NumberOfHandles(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000012080 for (int i = 0; i < iterations; i++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012081 Local<v8::Number> n(v8::Integer::New(isolate, 42));
Steve Blocka7e24c12009-10-30 11:49:00 +000012082 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012083 return Recurse(isolate, depth - 1, iterations);
Steve Blocka7e24c12009-10-30 11:49:00 +000012084}
12085
12086
12087THREADED_TEST(HandleIteration) {
12088 static const int kIterations = 500;
12089 static const int kNesting = 200;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012090 LocalContext context;
12091 v8::Isolate* isolate = context->GetIsolate();
12092 v8::HandleScope scope0(isolate);
12093 CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
Steve Blocka7e24c12009-10-30 11:49:00 +000012094 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012095 v8::HandleScope scope1(isolate);
12096 CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
Steve Blocka7e24c12009-10-30 11:49:00 +000012097 for (int i = 0; i < kIterations; i++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012098 Local<v8::Number> n(v8::Integer::New(CcTest::isolate(), 42));
12099 CHECK_EQ(i + 1, v8::HandleScope::NumberOfHandles(isolate));
Steve Blocka7e24c12009-10-30 11:49:00 +000012100 }
12101
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012102 CHECK_EQ(kIterations, v8::HandleScope::NumberOfHandles(isolate));
Steve Blocka7e24c12009-10-30 11:49:00 +000012103 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012104 v8::HandleScope scope2(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000012105 for (int j = 0; j < kIterations; j++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012106 Local<v8::Number> n(v8::Integer::New(CcTest::isolate(), 42));
12107 CHECK_EQ(j + 1 + kIterations,
12108 v8::HandleScope::NumberOfHandles(isolate));
Steve Blocka7e24c12009-10-30 11:49:00 +000012109 }
12110 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012111 CHECK_EQ(kIterations, v8::HandleScope::NumberOfHandles(isolate));
Steve Blocka7e24c12009-10-30 11:49:00 +000012112 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012113 CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
12114 CHECK_EQ(kNesting * kIterations, Recurse(isolate, kNesting, kIterations));
Steve Blocka7e24c12009-10-30 11:49:00 +000012115}
12116
12117
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012118static void InterceptorCallICFastApi(
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012119 Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
Andrei Popescu402d9372010-02-26 13:31:12 +000012120 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012121 CheckReturnValue(info, FUNCTION_ADDR(InterceptorCallICFastApi));
12122 int* call_count =
12123 reinterpret_cast<int*>(v8::External::Cast(*info.Data())->Value());
Andrei Popescu402d9372010-02-26 13:31:12 +000012124 ++(*call_count);
12125 if ((*call_count) % 20 == 0) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012126 CcTest::heap()->CollectAllGarbage();
Andrei Popescu402d9372010-02-26 13:31:12 +000012127 }
Andrei Popescu402d9372010-02-26 13:31:12 +000012128}
12129
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012130static void FastApiCallback_TrivialSignature(
12131 const v8::FunctionCallbackInfo<v8::Value>& args) {
Andrei Popescu402d9372010-02-26 13:31:12 +000012132 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012133 CheckReturnValue(args, FUNCTION_ADDR(FastApiCallback_TrivialSignature));
12134 v8::Isolate* isolate = CcTest::isolate();
12135 CHECK_EQ(isolate, args.GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012136 CHECK(args.This()
12137 ->Equals(isolate->GetCurrentContext(), args.Holder())
12138 .FromJust());
12139 CHECK(args.Data()
12140 ->Equals(isolate->GetCurrentContext(), v8_str("method_data"))
12141 .FromJust());
12142 args.GetReturnValue().Set(
12143 args[0]->Int32Value(isolate->GetCurrentContext()).FromJust() + 1);
Andrei Popescu402d9372010-02-26 13:31:12 +000012144}
12145
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012146static void FastApiCallback_SimpleSignature(
12147 const v8::FunctionCallbackInfo<v8::Value>& args) {
Andrei Popescu402d9372010-02-26 13:31:12 +000012148 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012149 CheckReturnValue(args, FUNCTION_ADDR(FastApiCallback_SimpleSignature));
12150 v8::Isolate* isolate = CcTest::isolate();
12151 CHECK_EQ(isolate, args.GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012152 CHECK(args.This()
12153 ->GetPrototype()
12154 ->Equals(isolate->GetCurrentContext(), args.Holder())
12155 .FromJust());
12156 CHECK(args.Data()
12157 ->Equals(isolate->GetCurrentContext(), v8_str("method_data"))
12158 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000012159 // Note, we're using HasRealNamedProperty instead of Has to avoid
12160 // invoking the interceptor again.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012161 CHECK(args.Holder()
12162 ->HasRealNamedProperty(isolate->GetCurrentContext(), v8_str("foo"))
12163 .FromJust());
12164 args.GetReturnValue().Set(
12165 args[0]->Int32Value(isolate->GetCurrentContext()).FromJust() + 1);
Andrei Popescu402d9372010-02-26 13:31:12 +000012166}
12167
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012168
Andrei Popescu402d9372010-02-26 13:31:12 +000012169// Helper to maximize the odds of object moving.
12170static void GenerateSomeGarbage() {
12171 CompileRun(
12172 "var garbage;"
12173 "for (var i = 0; i < 1000; i++) {"
12174 " garbage = [1/i, \"garbage\" + i, garbage, {foo: garbage}];"
12175 "}"
12176 "garbage = undefined;");
12177}
12178
Ben Murdoche0cee9b2011-05-25 10:26:03 +010012179
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012180void DirectApiCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Block1e0659c2011-05-24 12:43:12 +010012181 static int count = 0;
12182 if (count++ % 3 == 0) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012183 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012184 // This should move the stub
Steve Block1e0659c2011-05-24 12:43:12 +010012185 GenerateSomeGarbage(); // This should ensure the old stub memory is flushed
12186 }
Steve Block1e0659c2011-05-24 12:43:12 +010012187}
12188
12189
12190THREADED_TEST(CallICFastApi_DirectCall_GCMoveStub) {
Steve Block1e0659c2011-05-24 12:43:12 +010012191 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012192 v8::Isolate* isolate = context->GetIsolate();
12193 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012194 v8::Local<v8::ObjectTemplate> nativeobject_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012195 v8::ObjectTemplate::New(isolate);
12196 nativeobject_templ->Set(isolate, "callback",
12197 v8::FunctionTemplate::New(isolate,
12198 DirectApiCallback));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012199 v8::Local<v8::Object> nativeobject_obj =
12200 nativeobject_templ->NewInstance(context.local()).ToLocalChecked();
12201 CHECK(context->Global()
12202 ->Set(context.local(), v8_str("nativeobject"), nativeobject_obj)
12203 .FromJust());
Steve Block1e0659c2011-05-24 12:43:12 +010012204 // call the api function multiple times to ensure direct call stub creation.
12205 CompileRun(
12206 "function f() {"
12207 " for (var i = 1; i <= 30; i++) {"
12208 " nativeobject.callback();"
12209 " }"
12210 "}"
12211 "f();");
12212}
12213
12214
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012215void ThrowingDirectApiCallback(
12216 const v8::FunctionCallbackInfo<v8::Value>& args) {
12217 args.GetIsolate()->ThrowException(v8_str("g"));
Steve Block1e0659c2011-05-24 12:43:12 +010012218}
12219
12220
12221THREADED_TEST(CallICFastApi_DirectCall_Throw) {
Steve Block1e0659c2011-05-24 12:43:12 +010012222 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012223 v8::Isolate* isolate = context->GetIsolate();
12224 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012225 v8::Local<v8::ObjectTemplate> nativeobject_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012226 v8::ObjectTemplate::New(isolate);
12227 nativeobject_templ->Set(isolate, "callback",
12228 v8::FunctionTemplate::New(isolate,
12229 ThrowingDirectApiCallback));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012230 v8::Local<v8::Object> nativeobject_obj =
12231 nativeobject_templ->NewInstance(context.local()).ToLocalChecked();
12232 CHECK(context->Global()
12233 ->Set(context.local(), v8_str("nativeobject"), nativeobject_obj)
12234 .FromJust());
Steve Block1e0659c2011-05-24 12:43:12 +010012235 // call the api function multiple times to ensure direct call stub creation.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012236 v8::Local<Value> result = CompileRun(
Steve Block1e0659c2011-05-24 12:43:12 +010012237 "var result = '';"
12238 "function f() {"
12239 " for (var i = 1; i <= 5; i++) {"
12240 " try { nativeobject.callback(); } catch (e) { result += e; }"
12241 " }"
12242 "}"
12243 "f(); result;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012244 CHECK(v8_str("ggggg")->Equals(context.local(), result).FromJust());
Steve Block1e0659c2011-05-24 12:43:12 +010012245}
12246
12247
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012248static int p_getter_count_3;
12249
12250
12251static Local<Value> DoDirectGetter() {
12252 if (++p_getter_count_3 % 3 == 0) {
12253 CcTest::heap()->CollectAllGarbage();
Ben Murdoche0cee9b2011-05-25 10:26:03 +010012254 GenerateSomeGarbage();
12255 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012256 return v8_str("Direct Getter Result");
12257}
12258
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012259
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012260static void DirectGetterCallback(
12261 Local<String> name,
12262 const v8::PropertyCallbackInfo<v8::Value>& info) {
12263 CheckReturnValue(info, FUNCTION_ADDR(DirectGetterCallback));
12264 info.GetReturnValue().Set(DoDirectGetter());
Ben Murdoche0cee9b2011-05-25 10:26:03 +010012265}
12266
12267
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012268template<typename Accessor>
12269static void LoadICFastApi_DirectCall_GCMoveStub(Accessor accessor) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +010012270 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012271 v8::Isolate* isolate = context->GetIsolate();
12272 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012273 v8::Local<v8::ObjectTemplate> obj = v8::ObjectTemplate::New(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012274 obj->SetAccessor(v8_str("p1"), accessor);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012275 CHECK(context->Global()
12276 ->Set(context.local(), v8_str("o1"),
12277 obj->NewInstance(context.local()).ToLocalChecked())
12278 .FromJust());
12279 p_getter_count_3 = 0;
12280 v8::Local<v8::Value> result = CompileRun(
Ben Murdoche0cee9b2011-05-25 10:26:03 +010012281 "function f() {"
12282 " for (var i = 0; i < 30; i++) o1.p1;"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012283 " return o1.p1"
Ben Murdoche0cee9b2011-05-25 10:26:03 +010012284 "}"
12285 "f();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012286 CHECK(v8_str("Direct Getter Result")
12287 ->Equals(context.local(), result)
12288 .FromJust());
12289 CHECK_EQ(31, p_getter_count_3);
Ben Murdoche0cee9b2011-05-25 10:26:03 +010012290}
12291
12292
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012293THREADED_PROFILED_TEST(LoadICFastApi_DirectCall_GCMoveStub) {
12294 LoadICFastApi_DirectCall_GCMoveStub(DirectGetterCallback);
12295}
12296
12297
12298void ThrowingDirectGetterCallback(
12299 Local<String> name,
12300 const v8::PropertyCallbackInfo<v8::Value>& info) {
12301 info.GetIsolate()->ThrowException(v8_str("g"));
Ben Murdoche0cee9b2011-05-25 10:26:03 +010012302}
12303
12304
12305THREADED_TEST(LoadICFastApi_DirectCall_Throw) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +010012306 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012307 v8::Isolate* isolate = context->GetIsolate();
12308 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012309 v8::Local<v8::ObjectTemplate> obj = v8::ObjectTemplate::New(isolate);
Ben Murdoche0cee9b2011-05-25 10:26:03 +010012310 obj->SetAccessor(v8_str("p1"), ThrowingDirectGetterCallback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012311 CHECK(context->Global()
12312 ->Set(context.local(), v8_str("o1"),
12313 obj->NewInstance(context.local()).ToLocalChecked())
12314 .FromJust());
12315 v8::Local<Value> result = CompileRun(
Ben Murdoche0cee9b2011-05-25 10:26:03 +010012316 "var result = '';"
12317 "for (var i = 0; i < 5; i++) {"
12318 " try { o1.p1; } catch (e) { result += e; }"
12319 "}"
12320 "result;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012321 CHECK(v8_str("ggggg")->Equals(context.local(), result).FromJust());
Ben Murdoche0cee9b2011-05-25 10:26:03 +010012322}
12323
12324
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012325THREADED_PROFILED_TEST(InterceptorCallICFastApi_TrivialSignature) {
Andrei Popescu402d9372010-02-26 13:31:12 +000012326 int interceptor_call_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012327 v8::Isolate* isolate = CcTest::isolate();
12328 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012329 v8::Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012330 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012331 v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
12332 isolate, FastApiCallback_TrivialSignature, v8_str("method_data"),
12333 v8::Local<v8::Signature>());
12334 v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
Andrei Popescu402d9372010-02-26 13:31:12 +000012335 proto_templ->Set(v8_str("method"), method_templ);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012336 v8::Local<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012337 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012338 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012339 v8::External::New(isolate, &interceptor_call_count)));
Andrei Popescu402d9372010-02-26 13:31:12 +000012340 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012341 v8::Local<v8::Function> fun =
12342 fun_templ->GetFunction(context.local()).ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000012343 GenerateSomeGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012344 CHECK(context->Global()
12345 ->Set(context.local(), v8_str("o"),
12346 fun->NewInstance(context.local()).ToLocalChecked())
12347 .FromJust());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012348 CompileRun(
Andrei Popescu402d9372010-02-26 13:31:12 +000012349 "var result = 0;"
12350 "for (var i = 0; i < 100; i++) {"
12351 " result = o.method(41);"
Ben Murdochc7cc0282012-03-05 14:35:55 +000012352 "}");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012353 CHECK_EQ(42, context->Global()
12354 ->Get(context.local(), v8_str("result"))
12355 .ToLocalChecked()
12356 ->Int32Value(context.local())
12357 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000012358 CHECK_EQ(100, interceptor_call_count);
12359}
12360
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012361
12362THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature) {
Andrei Popescu402d9372010-02-26 13:31:12 +000012363 int interceptor_call_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012364 v8::Isolate* isolate = CcTest::isolate();
12365 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012366 v8::Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012367 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012368 v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012369 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12370 v8::Signature::New(isolate, fun_templ));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012371 v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
Andrei Popescu402d9372010-02-26 13:31:12 +000012372 proto_templ->Set(v8_str("method"), method_templ);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012373 fun_templ->SetHiddenPrototype(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012374 v8::Local<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012375 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012376 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012377 v8::External::New(isolate, &interceptor_call_count)));
Andrei Popescu402d9372010-02-26 13:31:12 +000012378 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012379 v8::Local<v8::Function> fun =
12380 fun_templ->GetFunction(context.local()).ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000012381 GenerateSomeGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012382 CHECK(context->Global()
12383 ->Set(context.local(), v8_str("o"),
12384 fun->NewInstance(context.local()).ToLocalChecked())
12385 .FromJust());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012386 CompileRun(
Andrei Popescu402d9372010-02-26 13:31:12 +000012387 "o.foo = 17;"
12388 "var receiver = {};"
12389 "receiver.__proto__ = o;"
12390 "var result = 0;"
12391 "for (var i = 0; i < 100; i++) {"
12392 " result = receiver.method(41);"
Ben Murdochc7cc0282012-03-05 14:35:55 +000012393 "}");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012394 CHECK_EQ(42, context->Global()
12395 ->Get(context.local(), v8_str("result"))
12396 .ToLocalChecked()
12397 ->Int32Value(context.local())
12398 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000012399 CHECK_EQ(100, interceptor_call_count);
12400}
12401
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012402
12403THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss1) {
Andrei Popescu402d9372010-02-26 13:31:12 +000012404 int interceptor_call_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012405 v8::Isolate* isolate = CcTest::isolate();
12406 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012407 v8::Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012408 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012409 v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012410 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12411 v8::Signature::New(isolate, fun_templ));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012412 v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
Andrei Popescu402d9372010-02-26 13:31:12 +000012413 proto_templ->Set(v8_str("method"), method_templ);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012414 fun_templ->SetHiddenPrototype(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012415 v8::Local<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012416 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012417 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012418 v8::External::New(isolate, &interceptor_call_count)));
Andrei Popescu402d9372010-02-26 13:31:12 +000012419 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012420 v8::Local<v8::Function> fun =
12421 fun_templ->GetFunction(context.local()).ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000012422 GenerateSomeGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012423 CHECK(context->Global()
12424 ->Set(context.local(), v8_str("o"),
12425 fun->NewInstance(context.local()).ToLocalChecked())
12426 .FromJust());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012427 CompileRun(
Andrei Popescu402d9372010-02-26 13:31:12 +000012428 "o.foo = 17;"
12429 "var receiver = {};"
12430 "receiver.__proto__ = o;"
12431 "var result = 0;"
12432 "var saved_result = 0;"
12433 "for (var i = 0; i < 100; i++) {"
12434 " result = receiver.method(41);"
12435 " if (i == 50) {"
12436 " saved_result = result;"
12437 " receiver = {method: function(x) { return x - 1 }};"
12438 " }"
Ben Murdochc7cc0282012-03-05 14:35:55 +000012439 "}");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012440 CHECK_EQ(40, context->Global()
12441 ->Get(context.local(), v8_str("result"))
12442 .ToLocalChecked()
12443 ->Int32Value(context.local())
12444 .FromJust());
12445 CHECK_EQ(42, context->Global()
12446 ->Get(context.local(), v8_str("saved_result"))
12447 .ToLocalChecked()
12448 ->Int32Value(context.local())
12449 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000012450 CHECK_GE(interceptor_call_count, 50);
12451}
12452
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012453
12454THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss2) {
Andrei Popescu402d9372010-02-26 13:31:12 +000012455 int interceptor_call_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012456 v8::Isolate* isolate = CcTest::isolate();
12457 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012458 v8::Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012459 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012460 v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012461 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12462 v8::Signature::New(isolate, fun_templ));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012463 v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
Andrei Popescu402d9372010-02-26 13:31:12 +000012464 proto_templ->Set(v8_str("method"), method_templ);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012465 fun_templ->SetHiddenPrototype(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012466 v8::Local<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012467 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012468 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012469 v8::External::New(isolate, &interceptor_call_count)));
Andrei Popescu402d9372010-02-26 13:31:12 +000012470 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012471 v8::Local<v8::Function> fun =
12472 fun_templ->GetFunction(context.local()).ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000012473 GenerateSomeGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012474 CHECK(context->Global()
12475 ->Set(context.local(), v8_str("o"),
12476 fun->NewInstance(context.local()).ToLocalChecked())
12477 .FromJust());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012478 CompileRun(
Andrei Popescu402d9372010-02-26 13:31:12 +000012479 "o.foo = 17;"
12480 "var receiver = {};"
12481 "receiver.__proto__ = o;"
12482 "var result = 0;"
12483 "var saved_result = 0;"
12484 "for (var i = 0; i < 100; i++) {"
12485 " result = receiver.method(41);"
12486 " if (i == 50) {"
12487 " saved_result = result;"
12488 " o.method = function(x) { return x - 1 };"
12489 " }"
Ben Murdochc7cc0282012-03-05 14:35:55 +000012490 "}");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012491 CHECK_EQ(40, context->Global()
12492 ->Get(context.local(), v8_str("result"))
12493 .ToLocalChecked()
12494 ->Int32Value(context.local())
12495 .FromJust());
12496 CHECK_EQ(42, context->Global()
12497 ->Get(context.local(), v8_str("saved_result"))
12498 .ToLocalChecked()
12499 ->Int32Value(context.local())
12500 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000012501 CHECK_GE(interceptor_call_count, 50);
12502}
12503
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012504
12505THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss3) {
Steve Block6ded16b2010-05-10 14:33:55 +010012506 int interceptor_call_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012507 v8::Isolate* isolate = CcTest::isolate();
12508 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012509 v8::Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012510 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012511 v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012512 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12513 v8::Signature::New(isolate, fun_templ));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012514 v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
Steve Block6ded16b2010-05-10 14:33:55 +010012515 proto_templ->Set(v8_str("method"), method_templ);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012516 fun_templ->SetHiddenPrototype(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012517 v8::Local<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012518 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012519 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012520 v8::External::New(isolate, &interceptor_call_count)));
Steve Block6ded16b2010-05-10 14:33:55 +010012521 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012522 v8::Local<v8::Function> fun =
12523 fun_templ->GetFunction(context.local()).ToLocalChecked();
Steve Block6ded16b2010-05-10 14:33:55 +010012524 GenerateSomeGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012525 CHECK(context->Global()
12526 ->Set(context.local(), v8_str("o"),
12527 fun->NewInstance(context.local()).ToLocalChecked())
12528 .FromJust());
12529 v8::TryCatch try_catch(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012530 CompileRun(
Steve Block6ded16b2010-05-10 14:33:55 +010012531 "o.foo = 17;"
12532 "var receiver = {};"
12533 "receiver.__proto__ = o;"
12534 "var result = 0;"
12535 "var saved_result = 0;"
12536 "for (var i = 0; i < 100; i++) {"
12537 " result = receiver.method(41);"
12538 " if (i == 50) {"
12539 " saved_result = result;"
12540 " receiver = 333;"
12541 " }"
Ben Murdochc7cc0282012-03-05 14:35:55 +000012542 "}");
Steve Block6ded16b2010-05-10 14:33:55 +010012543 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012544 // TODO(verwaest): Adjust message.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012545 CHECK(
12546 v8_str("TypeError: receiver.method is not a function")
12547 ->Equals(
12548 context.local(),
12549 try_catch.Exception()->ToString(context.local()).ToLocalChecked())
12550 .FromJust());
12551 CHECK_EQ(42, context->Global()
12552 ->Get(context.local(), v8_str("saved_result"))
12553 .ToLocalChecked()
12554 ->Int32Value(context.local())
12555 .FromJust());
Steve Block6ded16b2010-05-10 14:33:55 +010012556 CHECK_GE(interceptor_call_count, 50);
12557}
12558
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012559
12560THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_TypeError) {
Andrei Popescu402d9372010-02-26 13:31:12 +000012561 int interceptor_call_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012562 v8::Isolate* isolate = CcTest::isolate();
12563 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012564 v8::Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012565 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012566 v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012567 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12568 v8::Signature::New(isolate, fun_templ));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012569 v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
Andrei Popescu402d9372010-02-26 13:31:12 +000012570 proto_templ->Set(v8_str("method"), method_templ);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012571 fun_templ->SetHiddenPrototype(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012572 v8::Local<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012573 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012574 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012575 v8::External::New(isolate, &interceptor_call_count)));
Andrei Popescu402d9372010-02-26 13:31:12 +000012576 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012577 v8::Local<v8::Function> fun =
12578 fun_templ->GetFunction(context.local()).ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000012579 GenerateSomeGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012580 CHECK(context->Global()
12581 ->Set(context.local(), v8_str("o"),
12582 fun->NewInstance(context.local()).ToLocalChecked())
12583 .FromJust());
12584 v8::TryCatch try_catch(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012585 CompileRun(
Andrei Popescu402d9372010-02-26 13:31:12 +000012586 "o.foo = 17;"
12587 "var receiver = {};"
12588 "receiver.__proto__ = o;"
12589 "var result = 0;"
12590 "var saved_result = 0;"
12591 "for (var i = 0; i < 100; i++) {"
12592 " result = receiver.method(41);"
12593 " if (i == 50) {"
12594 " saved_result = result;"
12595 " receiver = {method: receiver.method};"
12596 " }"
Ben Murdochc7cc0282012-03-05 14:35:55 +000012597 "}");
Andrei Popescu402d9372010-02-26 13:31:12 +000012598 CHECK(try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012599 CHECK(
12600 v8_str("TypeError: Illegal invocation")
12601 ->Equals(
12602 context.local(),
12603 try_catch.Exception()->ToString(context.local()).ToLocalChecked())
12604 .FromJust());
12605 CHECK_EQ(42, context->Global()
12606 ->Get(context.local(), v8_str("saved_result"))
12607 .ToLocalChecked()
12608 ->Int32Value(context.local())
12609 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000012610 CHECK_GE(interceptor_call_count, 50);
12611}
12612
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012613
12614THREADED_PROFILED_TEST(CallICFastApi_TrivialSignature) {
12615 v8::Isolate* isolate = CcTest::isolate();
12616 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012617 v8::Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012618 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012619 v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
12620 isolate, FastApiCallback_TrivialSignature, v8_str("method_data"),
12621 v8::Local<v8::Signature>());
12622 v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
Andrei Popescu402d9372010-02-26 13:31:12 +000012623 proto_templ->Set(v8_str("method"), method_templ);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012624 v8::Local<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012625 USE(templ);
Andrei Popescu402d9372010-02-26 13:31:12 +000012626 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012627 v8::Local<v8::Function> fun =
12628 fun_templ->GetFunction(context.local()).ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000012629 GenerateSomeGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012630 CHECK(context->Global()
12631 ->Set(context.local(), v8_str("o"),
12632 fun->NewInstance(context.local()).ToLocalChecked())
12633 .FromJust());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012634 CompileRun(
Andrei Popescu402d9372010-02-26 13:31:12 +000012635 "var result = 0;"
12636 "for (var i = 0; i < 100; i++) {"
12637 " result = o.method(41);"
Ben Murdochc7cc0282012-03-05 14:35:55 +000012638 "}");
Andrei Popescu402d9372010-02-26 13:31:12 +000012639
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012640 CHECK_EQ(42, context->Global()
12641 ->Get(context.local(), v8_str("result"))
12642 .ToLocalChecked()
12643 ->Int32Value(context.local())
12644 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000012645}
12646
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012647
12648THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature) {
12649 v8::Isolate* isolate = CcTest::isolate();
12650 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012651 v8::Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012652 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012653 v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012654 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12655 v8::Signature::New(isolate, fun_templ));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012656 v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
Andrei Popescu402d9372010-02-26 13:31:12 +000012657 proto_templ->Set(v8_str("method"), method_templ);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012658 fun_templ->SetHiddenPrototype(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012659 v8::Local<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012660 CHECK(!templ.IsEmpty());
Andrei Popescu402d9372010-02-26 13:31:12 +000012661 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012662 v8::Local<v8::Function> fun =
12663 fun_templ->GetFunction(context.local()).ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000012664 GenerateSomeGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012665 CHECK(context->Global()
12666 ->Set(context.local(), v8_str("o"),
12667 fun->NewInstance(context.local()).ToLocalChecked())
12668 .FromJust());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012669 CompileRun(
Andrei Popescu402d9372010-02-26 13:31:12 +000012670 "o.foo = 17;"
12671 "var receiver = {};"
12672 "receiver.__proto__ = o;"
12673 "var result = 0;"
12674 "for (var i = 0; i < 100; i++) {"
12675 " result = receiver.method(41);"
Ben Murdochc7cc0282012-03-05 14:35:55 +000012676 "}");
Andrei Popescu402d9372010-02-26 13:31:12 +000012677
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012678 CHECK_EQ(42, context->Global()
12679 ->Get(context.local(), v8_str("result"))
12680 .ToLocalChecked()
12681 ->Int32Value(context.local())
12682 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000012683}
12684
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012685
12686THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_Miss1) {
12687 v8::Isolate* isolate = CcTest::isolate();
12688 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012689 v8::Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012690 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012691 v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012692 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12693 v8::Signature::New(isolate, fun_templ));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012694 v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
Andrei Popescu402d9372010-02-26 13:31:12 +000012695 proto_templ->Set(v8_str("method"), method_templ);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012696 fun_templ->SetHiddenPrototype(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012697 v8::Local<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012698 CHECK(!templ.IsEmpty());
Andrei Popescu402d9372010-02-26 13:31:12 +000012699 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012700 v8::Local<v8::Function> fun =
12701 fun_templ->GetFunction(context.local()).ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000012702 GenerateSomeGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012703 CHECK(context->Global()
12704 ->Set(context.local(), v8_str("o"),
12705 fun->NewInstance(context.local()).ToLocalChecked())
12706 .FromJust());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012707 CompileRun(
Andrei Popescu402d9372010-02-26 13:31:12 +000012708 "o.foo = 17;"
12709 "var receiver = {};"
12710 "receiver.__proto__ = o;"
12711 "var result = 0;"
12712 "var saved_result = 0;"
12713 "for (var i = 0; i < 100; i++) {"
12714 " result = receiver.method(41);"
12715 " if (i == 50) {"
12716 " saved_result = result;"
12717 " receiver = {method: function(x) { return x - 1 }};"
12718 " }"
Ben Murdochc7cc0282012-03-05 14:35:55 +000012719 "}");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012720 CHECK_EQ(40, context->Global()
12721 ->Get(context.local(), v8_str("result"))
12722 .ToLocalChecked()
12723 ->Int32Value(context.local())
12724 .FromJust());
12725 CHECK_EQ(42, context->Global()
12726 ->Get(context.local(), v8_str("saved_result"))
12727 .ToLocalChecked()
12728 ->Int32Value(context.local())
12729 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000012730}
12731
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012732
12733THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_Miss2) {
12734 v8::Isolate* isolate = CcTest::isolate();
12735 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012736 v8::Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012737 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012738 v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012739 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12740 v8::Signature::New(isolate, fun_templ));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012741 v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
Steve Block6ded16b2010-05-10 14:33:55 +010012742 proto_templ->Set(v8_str("method"), method_templ);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012743 fun_templ->SetHiddenPrototype(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012744 v8::Local<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012745 CHECK(!templ.IsEmpty());
Steve Block6ded16b2010-05-10 14:33:55 +010012746 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012747 v8::Local<v8::Function> fun =
12748 fun_templ->GetFunction(context.local()).ToLocalChecked();
Steve Block6ded16b2010-05-10 14:33:55 +010012749 GenerateSomeGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012750 CHECK(context->Global()
12751 ->Set(context.local(), v8_str("o"),
12752 fun->NewInstance(context.local()).ToLocalChecked())
12753 .FromJust());
12754 v8::TryCatch try_catch(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010012755 CompileRun(
Steve Block6ded16b2010-05-10 14:33:55 +010012756 "o.foo = 17;"
12757 "var receiver = {};"
12758 "receiver.__proto__ = o;"
12759 "var result = 0;"
12760 "var saved_result = 0;"
12761 "for (var i = 0; i < 100; i++) {"
12762 " result = receiver.method(41);"
12763 " if (i == 50) {"
12764 " saved_result = result;"
12765 " receiver = 333;"
12766 " }"
Ben Murdochc7cc0282012-03-05 14:35:55 +000012767 "}");
Steve Block6ded16b2010-05-10 14:33:55 +010012768 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012769 // TODO(verwaest): Adjust message.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012770 CHECK(
12771 v8_str("TypeError: receiver.method is not a function")
12772 ->Equals(
12773 context.local(),
12774 try_catch.Exception()->ToString(context.local()).ToLocalChecked())
12775 .FromJust());
12776 CHECK_EQ(42, context->Global()
12777 ->Get(context.local(), v8_str("saved_result"))
12778 .ToLocalChecked()
12779 ->Int32Value(context.local())
12780 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012781}
12782
12783
12784THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_TypeError) {
12785 v8::Isolate* isolate = CcTest::isolate();
12786 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012787 v8::Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012788 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012789 v8::Local<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012790 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12791 v8::Signature::New(isolate, fun_templ));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012792 v8::Local<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012793 proto_templ->Set(v8_str("method"), method_templ);
12794 fun_templ->SetHiddenPrototype(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012795 v8::Local<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012796 CHECK(!templ.IsEmpty());
12797 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012798 v8::Local<v8::Function> fun =
12799 fun_templ->GetFunction(context.local()).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012800 GenerateSomeGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012801 CHECK(context->Global()
12802 ->Set(context.local(), v8_str("o"),
12803 fun->NewInstance(context.local()).ToLocalChecked())
12804 .FromJust());
12805 v8::TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012806 CompileRun(
12807 "o.foo = 17;"
12808 "var receiver = {};"
12809 "receiver.__proto__ = o;"
12810 "var result = 0;"
12811 "var saved_result = 0;"
12812 "for (var i = 0; i < 100; i++) {"
12813 " result = receiver.method(41);"
12814 " if (i == 50) {"
12815 " saved_result = result;"
12816 " receiver = Object.create(receiver);"
12817 " }"
12818 "}");
12819 CHECK(try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012820 CHECK(
12821 v8_str("TypeError: Illegal invocation")
12822 ->Equals(
12823 context.local(),
12824 try_catch.Exception()->ToString(context.local()).ToLocalChecked())
12825 .FromJust());
12826 CHECK_EQ(42, context->Global()
12827 ->Get(context.local(), v8_str("saved_result"))
12828 .ToLocalChecked()
12829 ->Int32Value(context.local())
12830 .FromJust());
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +010012831}
12832
12833
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012834static void ThrowingGetter(Local<String> name,
12835 const v8::PropertyCallbackInfo<v8::Value>& info) {
Ben Murdoch8b112d22011-06-08 16:22:53 +010012836 ApiTestFuzzer::Fuzz();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012837 info.GetIsolate()->ThrowException(Local<Value>());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012838 info.GetReturnValue().SetUndefined();
Ben Murdoch8b112d22011-06-08 16:22:53 +010012839}
12840
12841
12842THREADED_TEST(VariousGetPropertiesAndThrowingCallbacks) {
Ben Murdoch8b112d22011-06-08 16:22:53 +010012843 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012844 HandleScope scope(context->GetIsolate());
Ben Murdoch8b112d22011-06-08 16:22:53 +010012845
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012846 Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
Ben Murdoch8b112d22011-06-08 16:22:53 +010012847 Local<ObjectTemplate> instance_templ = templ->InstanceTemplate();
12848 instance_templ->SetAccessor(v8_str("f"), ThrowingGetter);
12849
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012850 Local<Object> instance = templ->GetFunction(context.local())
12851 .ToLocalChecked()
12852 ->NewInstance(context.local())
12853 .ToLocalChecked();
Ben Murdoch8b112d22011-06-08 16:22:53 +010012854
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012855 Local<Object> another = Object::New(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012856 CHECK(another->SetPrototype(context.local(), instance).FromJust());
Ben Murdoch8b112d22011-06-08 16:22:53 +010012857
12858 Local<Object> with_js_getter = CompileRun(
12859 "o = {};\n"
12860 "o.__defineGetter__('f', function() { throw undefined; });\n"
12861 "o\n").As<Object>();
12862 CHECK(!with_js_getter.IsEmpty());
12863
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012864 TryCatch try_catch(context->GetIsolate());
Ben Murdoch8b112d22011-06-08 16:22:53 +010012865
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012866 v8::MaybeLocal<Value> result =
12867 instance->GetRealNamedProperty(context.local(), v8_str("f"));
Ben Murdoch8b112d22011-06-08 16:22:53 +010012868 CHECK(try_catch.HasCaught());
12869 try_catch.Reset();
12870 CHECK(result.IsEmpty());
12871
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012872 Maybe<PropertyAttribute> attr =
12873 instance->GetRealNamedPropertyAttributes(context.local(), v8_str("f"));
12874 CHECK(!try_catch.HasCaught());
12875 CHECK(Just(None) == attr);
12876
12877 result = another->GetRealNamedProperty(context.local(), v8_str("f"));
Ben Murdoch8b112d22011-06-08 16:22:53 +010012878 CHECK(try_catch.HasCaught());
12879 try_catch.Reset();
12880 CHECK(result.IsEmpty());
12881
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012882 attr = another->GetRealNamedPropertyAttributes(context.local(), v8_str("f"));
12883 CHECK(!try_catch.HasCaught());
12884 CHECK(Just(None) == attr);
12885
12886 result = another->GetRealNamedPropertyInPrototypeChain(context.local(),
12887 v8_str("f"));
Ben Murdoch8b112d22011-06-08 16:22:53 +010012888 CHECK(try_catch.HasCaught());
12889 try_catch.Reset();
12890 CHECK(result.IsEmpty());
12891
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012892 attr = another->GetRealNamedPropertyAttributesInPrototypeChain(
12893 context.local(), v8_str("f"));
12894 CHECK(!try_catch.HasCaught());
12895 CHECK(Just(None) == attr);
12896
12897 result = another->Get(context.local(), v8_str("f"));
Ben Murdoch8b112d22011-06-08 16:22:53 +010012898 CHECK(try_catch.HasCaught());
12899 try_catch.Reset();
12900 CHECK(result.IsEmpty());
12901
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012902 result = with_js_getter->GetRealNamedProperty(context.local(), v8_str("f"));
Ben Murdoch8b112d22011-06-08 16:22:53 +010012903 CHECK(try_catch.HasCaught());
12904 try_catch.Reset();
12905 CHECK(result.IsEmpty());
12906
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012907 attr = with_js_getter->GetRealNamedPropertyAttributes(context.local(),
12908 v8_str("f"));
12909 CHECK(!try_catch.HasCaught());
12910 CHECK(Just(None) == attr);
12911
12912 result = with_js_getter->Get(context.local(), v8_str("f"));
Ben Murdoch8b112d22011-06-08 16:22:53 +010012913 CHECK(try_catch.HasCaught());
12914 try_catch.Reset();
12915 CHECK(result.IsEmpty());
Ben Murdochda12d292016-06-02 14:46:10 +010012916
12917 Local<Object> target = CompileRun("({})").As<Object>();
12918 Local<Object> handler = CompileRun("({})").As<Object>();
12919 Local<v8::Proxy> proxy =
12920 v8::Proxy::New(context.local(), target, handler).ToLocalChecked();
12921
12922 result = target->GetRealNamedProperty(context.local(), v8_str("f"));
12923 CHECK(!try_catch.HasCaught());
12924 CHECK(result.IsEmpty());
12925
12926 result = proxy->GetRealNamedProperty(context.local(), v8_str("f"));
12927 CHECK(!try_catch.HasCaught());
12928 CHECK(result.IsEmpty());
Ben Murdoch8b112d22011-06-08 16:22:53 +010012929}
12930
12931
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012932static void ThrowingCallbackWithTryCatch(
12933 const v8::FunctionCallbackInfo<v8::Value>& args) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012934 TryCatch try_catch(args.GetIsolate());
Ben Murdoch8b112d22011-06-08 16:22:53 +010012935 // Verboseness is important: it triggers message delivery which can call into
12936 // external code.
12937 try_catch.SetVerbose(true);
12938 CompileRun("throw 'from JS';");
12939 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012940 CHECK(!CcTest::i_isolate()->has_pending_exception());
12941 CHECK(!CcTest::i_isolate()->has_scheduled_exception());
Ben Murdoch8b112d22011-06-08 16:22:53 +010012942}
12943
12944
12945static int call_depth;
12946
12947
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012948static void WithTryCatch(Local<Message> message, Local<Value> data) {
12949 TryCatch try_catch(CcTest::isolate());
Ben Murdoch8b112d22011-06-08 16:22:53 +010012950}
12951
12952
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012953static void ThrowFromJS(Local<Message> message, Local<Value> data) {
Ben Murdoch8b112d22011-06-08 16:22:53 +010012954 if (--call_depth) CompileRun("throw 'ThrowInJS';");
12955}
12956
12957
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012958static void ThrowViaApi(Local<Message> message, Local<Value> data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012959 if (--call_depth) CcTest::isolate()->ThrowException(v8_str("ThrowViaApi"));
Ben Murdoch8b112d22011-06-08 16:22:53 +010012960}
12961
12962
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012963static void WebKitLike(Local<Message> message, Local<Value> data) {
12964 Local<String> errorMessageString = message->Get();
Ben Murdoch8b112d22011-06-08 16:22:53 +010012965 CHECK(!errorMessageString.IsEmpty());
12966 message->GetStackTrace();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012967 message->GetScriptOrigin().ResourceName();
Ben Murdoch8b112d22011-06-08 16:22:53 +010012968}
12969
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012970
Ben Murdoch8b112d22011-06-08 16:22:53 +010012971THREADED_TEST(ExceptionsDoNotPropagatePastTryCatch) {
Ben Murdoch8b112d22011-06-08 16:22:53 +010012972 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012973 v8::Isolate* isolate = context->GetIsolate();
12974 HandleScope scope(isolate);
Ben Murdoch8b112d22011-06-08 16:22:53 +010012975
12976 Local<Function> func =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012977 FunctionTemplate::New(isolate, ThrowingCallbackWithTryCatch)
12978 ->GetFunction(context.local())
12979 .ToLocalChecked();
12980 CHECK(
12981 context->Global()->Set(context.local(), v8_str("func"), func).FromJust());
Ben Murdoch8b112d22011-06-08 16:22:53 +010012982
12983 MessageCallback callbacks[] =
12984 { NULL, WebKitLike, ThrowViaApi, ThrowFromJS, WithTryCatch };
12985 for (unsigned i = 0; i < sizeof(callbacks)/sizeof(callbacks[0]); i++) {
12986 MessageCallback callback = callbacks[i];
12987 if (callback != NULL) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012988 isolate->AddMessageListener(callback);
Ben Murdoch8b112d22011-06-08 16:22:53 +010012989 }
Ben Murdoch257744e2011-11-30 15:57:28 +000012990 // Some small number to control number of times message handler should
12991 // throw an exception.
Ben Murdoch8b112d22011-06-08 16:22:53 +010012992 call_depth = 5;
12993 ExpectFalse(
12994 "var thrown = false;\n"
12995 "try { func(); } catch(e) { thrown = true; }\n"
12996 "thrown\n");
12997 if (callback != NULL) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012998 isolate->RemoveMessageListeners(callback);
Ben Murdoch8b112d22011-06-08 16:22:53 +010012999 }
13000 }
13001}
13002
13003
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013004static void ParentGetter(Local<String> name,
13005 const v8::PropertyCallbackInfo<v8::Value>& info) {
Steve Blocka7e24c12009-10-30 11:49:00 +000013006 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013007 info.GetReturnValue().Set(v8_num(1));
Steve Blocka7e24c12009-10-30 11:49:00 +000013008}
13009
13010
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013011static void ChildGetter(Local<String> name,
13012 const v8::PropertyCallbackInfo<v8::Value>& info) {
Steve Blocka7e24c12009-10-30 11:49:00 +000013013 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013014 info.GetReturnValue().Set(v8_num(42));
Steve Blocka7e24c12009-10-30 11:49:00 +000013015}
13016
13017
13018THREADED_TEST(Overriding) {
Steve Blocka7e24c12009-10-30 11:49:00 +000013019 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013020 v8::Isolate* isolate = context->GetIsolate();
13021 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000013022
13023 // Parent template.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013024 Local<v8::FunctionTemplate> parent_templ = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000013025 Local<ObjectTemplate> parent_instance_templ =
13026 parent_templ->InstanceTemplate();
13027 parent_instance_templ->SetAccessor(v8_str("f"), ParentGetter);
13028
13029 // Template that inherits from the parent template.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013030 Local<v8::FunctionTemplate> child_templ = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000013031 Local<ObjectTemplate> child_instance_templ =
13032 child_templ->InstanceTemplate();
13033 child_templ->Inherit(parent_templ);
13034 // Override 'f'. The child version of 'f' should get called for child
13035 // instances.
13036 child_instance_templ->SetAccessor(v8_str("f"), ChildGetter);
13037 // Add 'g' twice. The 'g' added last should get called for instances.
13038 child_instance_templ->SetAccessor(v8_str("g"), ParentGetter);
13039 child_instance_templ->SetAccessor(v8_str("g"), ChildGetter);
13040
13041 // Add 'h' as an accessor to the proto template with ReadOnly attributes
13042 // so 'h' can be shadowed on the instance object.
13043 Local<ObjectTemplate> child_proto_templ = child_templ->PrototypeTemplate();
13044 child_proto_templ->SetAccessor(v8_str("h"), ParentGetter, 0,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013045 v8::Local<Value>(), v8::DEFAULT, v8::ReadOnly);
Steve Blocka7e24c12009-10-30 11:49:00 +000013046
13047 // Add 'i' as an accessor to the instance template with ReadOnly attributes
13048 // but the attribute does not have effect because it is duplicated with
13049 // NULL setter.
13050 child_instance_templ->SetAccessor(v8_str("i"), ChildGetter, 0,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013051 v8::Local<Value>(), v8::DEFAULT,
13052 v8::ReadOnly);
Steve Blocka7e24c12009-10-30 11:49:00 +000013053
13054
13055 // Instantiate the child template.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013056 Local<v8::Object> instance = child_templ->GetFunction(context.local())
13057 .ToLocalChecked()
13058 ->NewInstance(context.local())
13059 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000013060
13061 // Check that the child function overrides the parent one.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013062 CHECK(context->Global()
13063 ->Set(context.local(), v8_str("o"), instance)
13064 .FromJust());
13065 Local<Value> value = v8_compile("o.f")->Run(context.local()).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000013066 // Check that the 'g' that was added last is hit.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013067 CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
13068 value = v8_compile("o.g")->Run(context.local()).ToLocalChecked();
13069 CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013070
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013071 // Check that 'h' cannot be shadowed.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013072 value = v8_compile("o.h = 3; o.h")->Run(context.local()).ToLocalChecked();
13073 CHECK_EQ(1, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013074
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013075 // Check that 'i' cannot be shadowed or changed.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013076 value = v8_compile("o.i = 3; o.i")->Run(context.local()).ToLocalChecked();
13077 CHECK_EQ(42, value->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013078}
13079
13080
Ben Murdoch097c5b22016-05-18 11:27:45 +010013081static void ShouldThrowOnErrorGetter(
13082 Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
13083 ApiTestFuzzer::Fuzz();
13084 v8::Isolate* isolate = info.GetIsolate();
13085 Local<Boolean> should_throw_on_error =
13086 Boolean::New(isolate, info.ShouldThrowOnError());
13087 info.GetReturnValue().Set(should_throw_on_error);
13088}
13089
13090
13091template <typename T>
13092static void ShouldThrowOnErrorSetter(Local<Name> name, Local<v8::Value> value,
13093 const v8::PropertyCallbackInfo<T>& info) {
13094 ApiTestFuzzer::Fuzz();
13095 v8::Isolate* isolate = info.GetIsolate();
13096 auto context = isolate->GetCurrentContext();
13097 Local<Boolean> should_throw_on_error_value =
13098 Boolean::New(isolate, info.ShouldThrowOnError());
13099 CHECK(context->Global()
13100 ->Set(isolate->GetCurrentContext(), v8_str("should_throw_setter"),
13101 should_throw_on_error_value)
13102 .FromJust());
13103}
13104
13105
13106THREADED_TEST(AccessorShouldThrowOnError) {
Ben Murdoch097c5b22016-05-18 11:27:45 +010013107 LocalContext context;
13108 v8::Isolate* isolate = context->GetIsolate();
13109 v8::HandleScope scope(isolate);
13110 Local<Object> global = context->Global();
13111
13112 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
13113 Local<ObjectTemplate> instance_templ = templ->InstanceTemplate();
13114 instance_templ->SetAccessor(v8_str("f"), ShouldThrowOnErrorGetter,
13115 ShouldThrowOnErrorSetter<void>);
13116
13117 Local<v8::Object> instance = templ->GetFunction(context.local())
13118 .ToLocalChecked()
13119 ->NewInstance(context.local())
13120 .ToLocalChecked();
13121
13122 CHECK(global->Set(context.local(), v8_str("o"), instance).FromJust());
13123
13124 // SLOPPY mode
13125 Local<Value> value = v8_compile("o.f")->Run(context.local()).ToLocalChecked();
13126 CHECK(value->IsFalse());
13127 v8_compile("o.f = 153")->Run(context.local()).ToLocalChecked();
13128 value = global->Get(context.local(), v8_str("should_throw_setter"))
13129 .ToLocalChecked();
13130 CHECK(value->IsFalse());
13131
13132 // STRICT mode
13133 value = v8_compile("'use strict';o.f")->Run(context.local()).ToLocalChecked();
13134 CHECK(value->IsFalse());
13135 v8_compile("'use strict'; o.f = 153")->Run(context.local()).ToLocalChecked();
13136 value = global->Get(context.local(), v8_str("should_throw_setter"))
13137 .ToLocalChecked();
13138 CHECK(value->IsTrue());
Ben Murdoch097c5b22016-05-18 11:27:45 +010013139}
13140
13141
13142static void ShouldThrowOnErrorQuery(
13143 Local<Name> name, const v8::PropertyCallbackInfo<v8::Integer>& info) {
13144 ApiTestFuzzer::Fuzz();
13145 v8::Isolate* isolate = info.GetIsolate();
13146 info.GetReturnValue().Set(v8::None);
13147
13148 auto context = isolate->GetCurrentContext();
13149 Local<Boolean> should_throw_on_error_value =
13150 Boolean::New(isolate, info.ShouldThrowOnError());
13151 CHECK(context->Global()
13152 ->Set(isolate->GetCurrentContext(), v8_str("should_throw_query"),
13153 should_throw_on_error_value)
13154 .FromJust());
13155}
13156
13157
13158static void ShouldThrowOnErrorDeleter(
13159 Local<Name> name, const v8::PropertyCallbackInfo<v8::Boolean>& info) {
13160 ApiTestFuzzer::Fuzz();
13161 v8::Isolate* isolate = info.GetIsolate();
13162 info.GetReturnValue().Set(v8::True(isolate));
13163
13164 auto context = isolate->GetCurrentContext();
13165 Local<Boolean> should_throw_on_error_value =
13166 Boolean::New(isolate, info.ShouldThrowOnError());
13167 CHECK(context->Global()
13168 ->Set(isolate->GetCurrentContext(), v8_str("should_throw_deleter"),
13169 should_throw_on_error_value)
13170 .FromJust());
13171}
13172
13173
13174static void ShouldThrowOnErrorPropertyEnumerator(
13175 const v8::PropertyCallbackInfo<v8::Array>& info) {
13176 ApiTestFuzzer::Fuzz();
13177 v8::Isolate* isolate = info.GetIsolate();
13178 Local<v8::Array> names = v8::Array::New(isolate, 1);
13179 CHECK(names->Set(isolate->GetCurrentContext(), names, v8_num(1)).FromJust());
13180 info.GetReturnValue().Set(names);
13181
13182 auto context = isolate->GetCurrentContext();
13183 Local<Boolean> should_throw_on_error_value =
13184 Boolean::New(isolate, info.ShouldThrowOnError());
13185 CHECK(context->Global()
13186 ->Set(isolate->GetCurrentContext(),
13187 v8_str("should_throw_enumerator"),
13188 should_throw_on_error_value)
13189 .FromJust());
13190}
13191
13192
13193THREADED_TEST(InterceptorShouldThrowOnError) {
Ben Murdoch097c5b22016-05-18 11:27:45 +010013194 LocalContext context;
13195 v8::Isolate* isolate = context->GetIsolate();
13196 v8::HandleScope scope(isolate);
13197 Local<Object> global = context->Global();
13198
13199 auto interceptor_templ = v8::ObjectTemplate::New(isolate);
13200 v8::NamedPropertyHandlerConfiguration handler(
13201 ShouldThrowOnErrorGetter, ShouldThrowOnErrorSetter<Value>,
13202 ShouldThrowOnErrorQuery, ShouldThrowOnErrorDeleter,
13203 ShouldThrowOnErrorPropertyEnumerator);
13204 interceptor_templ->SetHandler(handler);
13205
13206 Local<v8::Object> instance =
13207 interceptor_templ->NewInstance(context.local()).ToLocalChecked();
13208
13209 CHECK(global->Set(context.local(), v8_str("o"), instance).FromJust());
13210
13211 // SLOPPY mode
13212 Local<Value> value = v8_compile("o.f")->Run(context.local()).ToLocalChecked();
13213 CHECK(value->IsFalse());
13214 v8_compile("o.f = 153")->Run(context.local()).ToLocalChecked();
13215 value = global->Get(context.local(), v8_str("should_throw_setter"))
13216 .ToLocalChecked();
13217 CHECK(value->IsFalse());
13218
13219 v8_compile("delete o.f")->Run(context.local()).ToLocalChecked();
13220 value = global->Get(context.local(), v8_str("should_throw_deleter"))
13221 .ToLocalChecked();
13222 CHECK(value->IsFalse());
13223
13224 v8_compile("Object.getOwnPropertyNames(o)")
13225 ->Run(context.local())
13226 .ToLocalChecked();
13227 value = global->Get(context.local(), v8_str("should_throw_enumerator"))
13228 .ToLocalChecked();
13229 CHECK(value->IsFalse());
13230
13231 // STRICT mode
13232 value = v8_compile("'use strict';o.f")->Run(context.local()).ToLocalChecked();
13233 CHECK(value->IsFalse());
13234 v8_compile("'use strict'; o.f = 153")->Run(context.local()).ToLocalChecked();
13235 value = global->Get(context.local(), v8_str("should_throw_setter"))
13236 .ToLocalChecked();
13237 CHECK(value->IsTrue());
13238
13239 v8_compile("'use strict'; delete o.f")->Run(context.local()).ToLocalChecked();
13240 value = global->Get(context.local(), v8_str("should_throw_deleter"))
13241 .ToLocalChecked();
13242 CHECK(value->IsTrue());
13243
13244 v8_compile("'use strict'; Object.getOwnPropertyNames(o)")
13245 ->Run(context.local())
13246 .ToLocalChecked();
13247 value = global->Get(context.local(), v8_str("should_throw_enumerator"))
13248 .ToLocalChecked();
13249 CHECK(value->IsFalse());
Ben Murdoch097c5b22016-05-18 11:27:45 +010013250}
13251
13252
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013253static void IsConstructHandler(
13254 const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +000013255 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013256 args.GetReturnValue().Set(args.IsConstructCall());
Steve Blocka7e24c12009-10-30 11:49:00 +000013257}
13258
13259
13260THREADED_TEST(IsConstructCall) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013261 v8::Isolate* isolate = CcTest::isolate();
13262 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000013263
13264 // Function template with call handler.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013265 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000013266 templ->SetCallHandler(IsConstructHandler);
13267
13268 LocalContext context;
13269
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013270 CHECK(context->Global()
13271 ->Set(context.local(), v8_str("f"),
13272 templ->GetFunction(context.local()).ToLocalChecked())
13273 .FromJust());
13274 Local<Value> value = v8_compile("f()")->Run(context.local()).ToLocalChecked();
13275 CHECK(!value->BooleanValue(context.local()).FromJust());
13276 value = v8_compile("new f()")->Run(context.local()).ToLocalChecked();
13277 CHECK(value->BooleanValue(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013278}
13279
Ben Murdochc5610432016-08-08 18:44:38 +010013280static void NewTargetHandler(const v8::FunctionCallbackInfo<v8::Value>& args) {
13281 ApiTestFuzzer::Fuzz();
13282 args.GetReturnValue().Set(args.NewTarget());
13283}
13284
13285THREADED_TEST(NewTargetHandler) {
13286 v8::Isolate* isolate = CcTest::isolate();
13287 v8::HandleScope scope(isolate);
13288
13289 // Function template with call handler.
13290 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
13291 templ->SetCallHandler(NewTargetHandler);
13292
13293 LocalContext context;
13294
13295 Local<Function> function =
13296 templ->GetFunction(context.local()).ToLocalChecked();
13297 CHECK(context->Global()
13298 ->Set(context.local(), v8_str("f"), function)
13299 .FromJust());
13300 Local<Value> value = CompileRun("f()");
13301 CHECK(value->IsUndefined());
13302 value = CompileRun("new f()");
13303 CHECK(value->IsFunction());
13304 CHECK(value == function);
13305 Local<Value> subclass = CompileRun("var g = class extends f { }; g");
13306 CHECK(subclass->IsFunction());
13307 value = CompileRun("new g()");
13308 CHECK(value->IsFunction());
13309 CHECK(value == subclass);
13310 value = CompileRun("Reflect.construct(f, [], Array)");
13311 CHECK(value->IsFunction());
13312 CHECK(value ==
13313 context->Global()
13314 ->Get(context.local(), v8_str("Array"))
13315 .ToLocalChecked());
13316}
Steve Blocka7e24c12009-10-30 11:49:00 +000013317
13318THREADED_TEST(ObjectProtoToString) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013319 v8::Isolate* isolate = CcTest::isolate();
13320 v8::HandleScope scope(isolate);
13321 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000013322 templ->SetClassName(v8_str("MyClass"));
13323
13324 LocalContext context;
13325
13326 Local<String> customized_tostring = v8_str("customized toString");
13327
13328 // Replace Object.prototype.toString
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013329 v8_compile(
13330 "Object.prototype.toString = function() {"
13331 " return 'customized toString';"
13332 "}")
13333 ->Run(context.local())
13334 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000013335
13336 // Normal ToString call should call replaced Object.prototype.toString
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013337 Local<v8::Object> instance = templ->GetFunction(context.local())
13338 .ToLocalChecked()
13339 ->NewInstance(context.local())
13340 .ToLocalChecked();
13341 Local<String> value = instance->ToString(context.local()).ToLocalChecked();
13342 CHECK(value->IsString() &&
13343 value->Equals(context.local(), customized_tostring).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013344
13345 // ObjectProtoToString should not call replace toString function.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013346 value = instance->ObjectProtoToString(context.local()).ToLocalChecked();
13347 CHECK(value->IsString() &&
13348 value->Equals(context.local(), v8_str("[object MyClass]")).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013349
13350 // Check global
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013351 value =
13352 context->Global()->ObjectProtoToString(context.local()).ToLocalChecked();
13353 CHECK(value->IsString() &&
Ben Murdoch61f157c2016-09-16 13:49:30 +010013354 value->Equals(context.local(), v8_str("[object Object]")).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013355
13356 // Check ordinary object
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013357 Local<Value> object =
13358 v8_compile("new Object()")->Run(context.local()).ToLocalChecked();
13359 value = object.As<v8::Object>()
13360 ->ObjectProtoToString(context.local())
13361 .ToLocalChecked();
13362 CHECK(value->IsString() &&
13363 value->Equals(context.local(), v8_str("[object Object]")).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013364}
13365
13366
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013367TEST(ObjectProtoToStringES6) {
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -080013368 LocalContext context;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013369 v8::Isolate* isolate = CcTest::isolate();
13370 v8::HandleScope scope(isolate);
13371 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
13372 templ->SetClassName(v8_str("MyClass"));
13373
13374 Local<String> customized_tostring = v8_str("customized toString");
13375
13376 // Replace Object.prototype.toString
13377 CompileRun(
13378 "Object.prototype.toString = function() {"
13379 " return 'customized toString';"
13380 "}");
13381
13382 // Normal ToString call should call replaced Object.prototype.toString
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013383 Local<v8::Object> instance = templ->GetFunction(context.local())
13384 .ToLocalChecked()
13385 ->NewInstance(context.local())
13386 .ToLocalChecked();
13387 Local<String> value = instance->ToString(context.local()).ToLocalChecked();
13388 CHECK(value->IsString() &&
13389 value->Equals(context.local(), customized_tostring).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013390
13391 // ObjectProtoToString should not call replace toString function.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013392 value = instance->ObjectProtoToString(context.local()).ToLocalChecked();
13393 CHECK(value->IsString() &&
13394 value->Equals(context.local(), v8_str("[object MyClass]")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013395
13396 // Check global
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013397 value =
13398 context->Global()->ObjectProtoToString(context.local()).ToLocalChecked();
13399 CHECK(value->IsString() &&
Ben Murdoch61f157c2016-09-16 13:49:30 +010013400 value->Equals(context.local(), v8_str("[object Object]")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013401
13402 // Check ordinary object
13403 Local<Value> object = CompileRun("new Object()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013404 value = object.As<v8::Object>()
13405 ->ObjectProtoToString(context.local())
13406 .ToLocalChecked();
13407 CHECK(value->IsString() &&
13408 value->Equals(context.local(), v8_str("[object Object]")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013409
13410 // Check that ES6 semantics using @@toStringTag work
13411 Local<v8::Symbol> toStringTag = v8::Symbol::GetToStringTag(isolate);
13412
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013413#define TEST_TOSTRINGTAG(type, tag, expected) \
13414 do { \
13415 object = CompileRun("new " #type "()"); \
13416 CHECK(object.As<v8::Object>() \
13417 ->Set(context.local(), toStringTag, v8_str(#tag)) \
13418 .FromJust()); \
13419 value = object.As<v8::Object>() \
13420 ->ObjectProtoToString(context.local()) \
13421 .ToLocalChecked(); \
13422 CHECK(value->IsString() && \
13423 value->Equals(context.local(), v8_str("[object " #expected "]")) \
13424 .FromJust()); \
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013425 } while (0)
13426
13427 TEST_TOSTRINGTAG(Array, Object, Object);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013428 TEST_TOSTRINGTAG(Object, Arguments, Arguments);
13429 TEST_TOSTRINGTAG(Object, Array, Array);
13430 TEST_TOSTRINGTAG(Object, Boolean, Boolean);
13431 TEST_TOSTRINGTAG(Object, Date, Date);
13432 TEST_TOSTRINGTAG(Object, Error, Error);
13433 TEST_TOSTRINGTAG(Object, Function, Function);
13434 TEST_TOSTRINGTAG(Object, Number, Number);
13435 TEST_TOSTRINGTAG(Object, RegExp, RegExp);
13436 TEST_TOSTRINGTAG(Object, String, String);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013437 TEST_TOSTRINGTAG(Object, Foo, Foo);
13438
13439#undef TEST_TOSTRINGTAG
13440
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013441 Local<v8::RegExp> valueRegExp =
13442 v8::RegExp::New(context.local(), v8_str("^$"), v8::RegExp::kNone)
13443 .ToLocalChecked();
13444 Local<Value> valueNumber = v8_num(123);
13445 Local<v8::Symbol> valueSymbol = v8_symbol("TestSymbol");
13446 Local<v8::Function> valueFunction =
13447 CompileRun("(function fn() {})").As<v8::Function>();
13448 Local<v8::Object> valueObject = v8::Object::New(v8::Isolate::GetCurrent());
13449 Local<v8::Primitive> valueNull = v8::Null(v8::Isolate::GetCurrent());
13450 Local<v8::Primitive> valueUndef = v8::Undefined(v8::Isolate::GetCurrent());
13451
13452#define TEST_TOSTRINGTAG(type, tagValue, expected) \
13453 do { \
13454 object = CompileRun("new " #type "()"); \
13455 CHECK(object.As<v8::Object>() \
13456 ->Set(context.local(), toStringTag, tagValue) \
13457 .FromJust()); \
13458 value = object.As<v8::Object>() \
13459 ->ObjectProtoToString(context.local()) \
13460 .ToLocalChecked(); \
13461 CHECK(value->IsString() && \
13462 value->Equals(context.local(), v8_str("[object " #expected "]")) \
13463 .FromJust()); \
13464 } while (0)
13465
13466#define TEST_TOSTRINGTAG_TYPES(tagValue) \
13467 TEST_TOSTRINGTAG(Array, tagValue, Array); \
13468 TEST_TOSTRINGTAG(Object, tagValue, Object); \
13469 TEST_TOSTRINGTAG(Function, tagValue, Function); \
13470 TEST_TOSTRINGTAG(Date, tagValue, Date); \
13471 TEST_TOSTRINGTAG(RegExp, tagValue, RegExp); \
13472 TEST_TOSTRINGTAG(Error, tagValue, Error); \
13473
13474 // Test non-String-valued @@toStringTag
13475 TEST_TOSTRINGTAG_TYPES(valueRegExp);
13476 TEST_TOSTRINGTAG_TYPES(valueNumber);
13477 TEST_TOSTRINGTAG_TYPES(valueSymbol);
13478 TEST_TOSTRINGTAG_TYPES(valueFunction);
13479 TEST_TOSTRINGTAG_TYPES(valueObject);
13480 TEST_TOSTRINGTAG_TYPES(valueNull);
13481 TEST_TOSTRINGTAG_TYPES(valueUndef);
13482
13483#undef TEST_TOSTRINGTAG
13484#undef TEST_TOSTRINGTAG_TYPES
13485
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013486 // @@toStringTag getter throws
13487 Local<Value> obj = v8::Object::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013488 obj.As<v8::Object>()
13489 ->SetAccessor(context.local(), toStringTag, ThrowingSymbolAccessorGetter)
13490 .FromJust();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013491 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013492 TryCatch try_catch(isolate);
13493 CHECK(obj.As<v8::Object>()->ObjectProtoToString(context.local()).IsEmpty());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013494 CHECK(try_catch.HasCaught());
13495 }
13496
13497 // @@toStringTag getter does not throw
13498 obj = v8::Object::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013499 obj.As<v8::Object>()
13500 ->SetAccessor(context.local(), toStringTag,
13501 SymbolAccessorGetterReturnsDefault, 0, v8_str("Test"))
13502 .FromJust();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013503 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013504 TryCatch try_catch(isolate);
13505 value = obj.As<v8::Object>()
13506 ->ObjectProtoToString(context.local())
13507 .ToLocalChecked();
13508 CHECK(value->IsString() &&
13509 value->Equals(context.local(), v8_str("[object Test]")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013510 CHECK(!try_catch.HasCaught());
13511 }
13512
13513 // JS @@toStringTag value
13514 obj = CompileRun("obj = {}; obj[Symbol.toStringTag] = 'Test'; obj");
13515 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013516 TryCatch try_catch(isolate);
13517 value = obj.As<v8::Object>()
13518 ->ObjectProtoToString(context.local())
13519 .ToLocalChecked();
13520 CHECK(value->IsString() &&
13521 value->Equals(context.local(), v8_str("[object Test]")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013522 CHECK(!try_catch.HasCaught());
13523 }
13524
13525 // JS @@toStringTag getter throws
13526 obj = CompileRun(
13527 "obj = {}; Object.defineProperty(obj, Symbol.toStringTag, {"
13528 " get: function() { throw 'Test'; }"
13529 "}); obj");
13530 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013531 TryCatch try_catch(isolate);
13532 CHECK(obj.As<v8::Object>()->ObjectProtoToString(context.local()).IsEmpty());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013533 CHECK(try_catch.HasCaught());
13534 }
13535
13536 // JS @@toStringTag getter does not throw
13537 obj = CompileRun(
13538 "obj = {}; Object.defineProperty(obj, Symbol.toStringTag, {"
13539 " get: function() { return 'Test'; }"
13540 "}); obj");
13541 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013542 TryCatch try_catch(isolate);
13543 value = obj.As<v8::Object>()
13544 ->ObjectProtoToString(context.local())
13545 .ToLocalChecked();
13546 CHECK(value->IsString() &&
13547 value->Equals(context.local(), v8_str("[object Test]")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013548 CHECK(!try_catch.HasCaught());
13549 }
13550}
13551
13552
13553THREADED_TEST(ObjectGetConstructorName) {
13554 v8::Isolate* isolate = CcTest::isolate();
13555 LocalContext context;
13556 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013557 v8_compile(
13558 "function Parent() {};"
13559 "function Child() {};"
13560 "Child.prototype = new Parent();"
13561 "Child.prototype.constructor = Child;"
Ben Murdochda12d292016-06-02 14:46:10 +010013562 "var outer = { inner: (0, function() { }) };"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013563 "var p = new Parent();"
13564 "var c = new Child();"
13565 "var x = new outer.inner();"
13566 "var proto = Child.prototype;")
13567 ->Run(context.local())
13568 .ToLocalChecked();
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -080013569
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013570 Local<v8::Value> p =
13571 context->Global()->Get(context.local(), v8_str("p")).ToLocalChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013572 CHECK(p->IsObject() &&
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013573 p->ToObject(context.local())
13574 .ToLocalChecked()
13575 ->GetConstructorName()
13576 ->Equals(context.local(), v8_str("Parent"))
13577 .FromJust());
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -080013578
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013579 Local<v8::Value> c =
13580 context->Global()->Get(context.local(), v8_str("c")).ToLocalChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013581 CHECK(c->IsObject() &&
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013582 c->ToObject(context.local())
13583 .ToLocalChecked()
13584 ->GetConstructorName()
13585 ->Equals(context.local(), v8_str("Child"))
13586 .FromJust());
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -080013587
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013588 Local<v8::Value> x =
13589 context->Global()->Get(context.local(), v8_str("x")).ToLocalChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013590 CHECK(x->IsObject() &&
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013591 x->ToObject(context.local())
13592 .ToLocalChecked()
13593 ->GetConstructorName()
13594 ->Equals(context.local(), v8_str("outer.inner"))
13595 .FromJust());
13596
13597 Local<v8::Value> child_prototype =
13598 context->Global()->Get(context.local(), v8_str("proto")).ToLocalChecked();
13599 CHECK(child_prototype->IsObject() &&
13600 child_prototype->ToObject(context.local())
13601 .ToLocalChecked()
13602 ->GetConstructorName()
13603 ->Equals(context.local(), v8_str("Parent"))
13604 .FromJust());
13605}
13606
13607
13608THREADED_TEST(SubclassGetConstructorName) {
13609 v8::Isolate* isolate = CcTest::isolate();
13610 LocalContext context;
13611 v8::HandleScope scope(isolate);
13612 v8_compile(
13613 "\"use strict\";"
13614 "class Parent {}"
13615 "class Child extends Parent {}"
13616 "var p = new Parent();"
13617 "var c = new Child();")
13618 ->Run(context.local())
13619 .ToLocalChecked();
13620
13621 Local<v8::Value> p =
13622 context->Global()->Get(context.local(), v8_str("p")).ToLocalChecked();
13623 CHECK(p->IsObject() &&
13624 p->ToObject(context.local())
13625 .ToLocalChecked()
13626 ->GetConstructorName()
13627 ->Equals(context.local(), v8_str("Parent"))
13628 .FromJust());
13629
13630 Local<v8::Value> c =
13631 context->Global()->Get(context.local(), v8_str("c")).ToLocalChecked();
13632 CHECK(c->IsObject() &&
13633 c->ToObject(context.local())
13634 .ToLocalChecked()
13635 ->GetConstructorName()
13636 ->Equals(context.local(), v8_str("Child"))
13637 .FromJust());
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -080013638}
13639
13640
Steve Blocka7e24c12009-10-30 11:49:00 +000013641bool ApiTestFuzzer::fuzzing_ = false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013642v8::base::Semaphore ApiTestFuzzer::all_tests_done_(0);
Steve Blocka7e24c12009-10-30 11:49:00 +000013643int ApiTestFuzzer::active_tests_;
13644int ApiTestFuzzer::tests_being_run_;
13645int ApiTestFuzzer::current_;
13646
13647
13648// We are in a callback and want to switch to another thread (if we
13649// are currently running the thread fuzzing test).
13650void ApiTestFuzzer::Fuzz() {
13651 if (!fuzzing_) return;
13652 ApiTestFuzzer* test = RegisterThreadedTest::nth(current_)->fuzzer_;
13653 test->ContextSwitch();
13654}
13655
13656
13657// Let the next thread go. Since it is also waiting on the V8 lock it may
13658// not start immediately.
13659bool ApiTestFuzzer::NextThread() {
13660 int test_position = GetNextTestNumber();
Steve Blockd0582a62009-12-15 09:54:21 +000013661 const char* test_name = RegisterThreadedTest::nth(current_)->name();
Steve Blocka7e24c12009-10-30 11:49:00 +000013662 if (test_position == current_) {
Steve Blockd0582a62009-12-15 09:54:21 +000013663 if (kLogThreading)
13664 printf("Stay with %s\n", test_name);
Steve Blocka7e24c12009-10-30 11:49:00 +000013665 return false;
13666 }
Steve Blockd0582a62009-12-15 09:54:21 +000013667 if (kLogThreading) {
13668 printf("Switch from %s to %s\n",
13669 test_name,
13670 RegisterThreadedTest::nth(test_position)->name());
13671 }
Steve Blocka7e24c12009-10-30 11:49:00 +000013672 current_ = test_position;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013673 RegisterThreadedTest::nth(current_)->fuzzer_->gate_.Signal();
Steve Blocka7e24c12009-10-30 11:49:00 +000013674 return true;
13675}
13676
13677
13678void ApiTestFuzzer::Run() {
13679 // When it is our turn...
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013680 gate_.Wait();
Steve Blocka7e24c12009-10-30 11:49:00 +000013681 {
13682 // ... get the V8 lock and start running the test.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013683 v8::Locker locker(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000013684 CallTest();
13685 }
13686 // This test finished.
13687 active_ = false;
13688 active_tests_--;
13689 // If it was the last then signal that fact.
13690 if (active_tests_ == 0) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013691 all_tests_done_.Signal();
Steve Blocka7e24c12009-10-30 11:49:00 +000013692 } else {
13693 // Otherwise select a new test and start that.
13694 NextThread();
13695 }
13696}
13697
13698
13699static unsigned linear_congruential_generator;
13700
13701
Ben Murdoch3ef787d2012-04-12 10:51:47 +010013702void ApiTestFuzzer::SetUp(PartOfTest part) {
Steve Blocka7e24c12009-10-30 11:49:00 +000013703 linear_congruential_generator = i::FLAG_testing_prng_seed;
13704 fuzzing_ = true;
Ben Murdoch257744e2011-11-30 15:57:28 +000013705 int count = RegisterThreadedTest::count();
13706 int start = count * part / (LAST_PART + 1);
13707 int end = (count * (part + 1) / (LAST_PART + 1)) - 1;
13708 active_tests_ = tests_being_run_ = end - start + 1;
Steve Blocka7e24c12009-10-30 11:49:00 +000013709 for (int i = 0; i < tests_being_run_; i++) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000013710 RegisterThreadedTest::nth(i)->fuzzer_ = new ApiTestFuzzer(i + start);
Steve Blocka7e24c12009-10-30 11:49:00 +000013711 }
13712 for (int i = 0; i < active_tests_; i++) {
13713 RegisterThreadedTest::nth(i)->fuzzer_->Start();
13714 }
13715}
13716
13717
13718static void CallTestNumber(int test_number) {
13719 (RegisterThreadedTest::nth(test_number)->callback())();
13720}
13721
13722
13723void ApiTestFuzzer::RunAllTests() {
13724 // Set off the first test.
13725 current_ = -1;
13726 NextThread();
13727 // Wait till they are all done.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013728 all_tests_done_.Wait();
Steve Blocka7e24c12009-10-30 11:49:00 +000013729}
13730
13731
13732int ApiTestFuzzer::GetNextTestNumber() {
13733 int next_test;
13734 do {
13735 next_test = (linear_congruential_generator >> 16) % tests_being_run_;
13736 linear_congruential_generator *= 1664525u;
13737 linear_congruential_generator += 1013904223u;
13738 } while (!RegisterThreadedTest::nth(next_test)->fuzzer_->active_);
13739 return next_test;
13740}
13741
13742
13743void ApiTestFuzzer::ContextSwitch() {
13744 // If the new thread is the same as the current thread there is nothing to do.
13745 if (NextThread()) {
13746 // Now it can start.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013747 v8::Unlocker unlocker(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000013748 // Wait till someone starts us again.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013749 gate_.Wait();
Steve Blocka7e24c12009-10-30 11:49:00 +000013750 // And we're off.
13751 }
13752}
13753
13754
13755void ApiTestFuzzer::TearDown() {
13756 fuzzing_ = false;
13757 for (int i = 0; i < RegisterThreadedTest::count(); i++) {
13758 ApiTestFuzzer *fuzzer = RegisterThreadedTest::nth(i)->fuzzer_;
13759 if (fuzzer != NULL) fuzzer->Join();
13760 }
13761}
13762
13763
13764// Lets not be needlessly self-referential.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013765TEST(Threading1) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010013766 ApiTestFuzzer::SetUp(ApiTestFuzzer::FIRST_PART);
Steve Blocka7e24c12009-10-30 11:49:00 +000013767 ApiTestFuzzer::RunAllTests();
13768 ApiTestFuzzer::TearDown();
13769}
13770
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013771
Steve Blocka7e24c12009-10-30 11:49:00 +000013772TEST(Threading2) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010013773 ApiTestFuzzer::SetUp(ApiTestFuzzer::SECOND_PART);
Steve Blocka7e24c12009-10-30 11:49:00 +000013774 ApiTestFuzzer::RunAllTests();
13775 ApiTestFuzzer::TearDown();
13776}
13777
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013778
Ben Murdoch257744e2011-11-30 15:57:28 +000013779TEST(Threading3) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010013780 ApiTestFuzzer::SetUp(ApiTestFuzzer::THIRD_PART);
Ben Murdoch257744e2011-11-30 15:57:28 +000013781 ApiTestFuzzer::RunAllTests();
13782 ApiTestFuzzer::TearDown();
13783}
13784
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013785
Ben Murdoch257744e2011-11-30 15:57:28 +000013786TEST(Threading4) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010013787 ApiTestFuzzer::SetUp(ApiTestFuzzer::FOURTH_PART);
Ben Murdoch257744e2011-11-30 15:57:28 +000013788 ApiTestFuzzer::RunAllTests();
13789 ApiTestFuzzer::TearDown();
13790}
Steve Blocka7e24c12009-10-30 11:49:00 +000013791
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013792
Steve Blocka7e24c12009-10-30 11:49:00 +000013793void ApiTestFuzzer::CallTest() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013794 v8::Isolate::Scope scope(CcTest::isolate());
Steve Blockd0582a62009-12-15 09:54:21 +000013795 if (kLogThreading)
13796 printf("Start test %d\n", test_number_);
Steve Blocka7e24c12009-10-30 11:49:00 +000013797 CallTestNumber(test_number_);
Steve Blockd0582a62009-12-15 09:54:21 +000013798 if (kLogThreading)
13799 printf("End test %d\n", test_number_);
Steve Blocka7e24c12009-10-30 11:49:00 +000013800}
13801
13802
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013803static void ThrowInJS(const v8::FunctionCallbackInfo<v8::Value>& args) {
13804 v8::Isolate* isolate = args.GetIsolate();
13805 CHECK(v8::Locker::IsLocked(isolate));
Steve Blocka7e24c12009-10-30 11:49:00 +000013806 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013807 v8::Unlocker unlocker(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000013808 const char* code = "throw 7;";
13809 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013810 v8::Locker nested_locker(isolate);
13811 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013812 v8::Local<Value> exception;
13813 {
13814 v8::TryCatch try_catch(isolate);
13815 v8::Local<Value> value = CompileRun(code);
Steve Blocka7e24c12009-10-30 11:49:00 +000013816 CHECK(value.IsEmpty());
13817 CHECK(try_catch.HasCaught());
13818 // Make sure to wrap the exception in a new handle because
13819 // the handle returned from the TryCatch is destroyed
13820 // when the TryCatch is destroyed.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013821 exception = Local<Value>::New(isolate, try_catch.Exception());
Steve Blocka7e24c12009-10-30 11:49:00 +000013822 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013823 args.GetIsolate()->ThrowException(exception);
Steve Blocka7e24c12009-10-30 11:49:00 +000013824 }
13825}
13826
13827
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013828static void ThrowInJSNoCatch(const v8::FunctionCallbackInfo<v8::Value>& args) {
13829 CHECK(v8::Locker::IsLocked(CcTest::isolate()));
Steve Blocka7e24c12009-10-30 11:49:00 +000013830 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013831 v8::Unlocker unlocker(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000013832 const char* code = "throw 7;";
13833 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013834 v8::Locker nested_locker(CcTest::isolate());
13835 v8::HandleScope scope(args.GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013836 v8::Local<Value> value = CompileRun(code);
Steve Blocka7e24c12009-10-30 11:49:00 +000013837 CHECK(value.IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013838 args.GetReturnValue().Set(v8_str("foo"));
Steve Blocka7e24c12009-10-30 11:49:00 +000013839 }
13840}
13841
13842
13843// These are locking tests that don't need to be run again
13844// as part of the locking aggregation tests.
13845TEST(NestedLockers) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013846 v8::Isolate* isolate = CcTest::isolate();
13847 v8::Locker locker(isolate);
13848 CHECK(v8::Locker::IsLocked(isolate));
Steve Blocka7e24c12009-10-30 11:49:00 +000013849 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013850 v8::HandleScope scope(env->GetIsolate());
13851 Local<v8::FunctionTemplate> fun_templ =
13852 v8::FunctionTemplate::New(isolate, ThrowInJS);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013853 Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
13854 CHECK(env->Global()->Set(env.local(), v8_str("throw_in_js"), fun).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013855 Local<Script> script = v8_compile("(function () {"
13856 " try {"
13857 " throw_in_js();"
13858 " return 42;"
13859 " } catch (e) {"
13860 " return e * 13;"
13861 " }"
13862 "})();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013863 CHECK_EQ(91, script->Run(env.local())
13864 .ToLocalChecked()
13865 ->Int32Value(env.local())
13866 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013867}
13868
13869
13870// These are locking tests that don't need to be run again
13871// as part of the locking aggregation tests.
13872TEST(NestedLockersNoTryCatch) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013873 v8::Locker locker(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000013874 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013875 v8::HandleScope scope(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000013876 Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013877 v8::FunctionTemplate::New(env->GetIsolate(), ThrowInJSNoCatch);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013878 Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
13879 CHECK(env->Global()->Set(env.local(), v8_str("throw_in_js"), fun).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013880 Local<Script> script = v8_compile("(function () {"
13881 " try {"
13882 " throw_in_js();"
13883 " return 42;"
13884 " } catch (e) {"
13885 " return e * 13;"
13886 " }"
13887 "})();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013888 CHECK_EQ(91, script->Run(env.local())
13889 .ToLocalChecked()
13890 ->Int32Value(env.local())
13891 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013892}
13893
13894
13895THREADED_TEST(RecursiveLocking) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013896 v8::Locker locker(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000013897 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013898 v8::Locker locker2(CcTest::isolate());
13899 CHECK(v8::Locker::IsLocked(CcTest::isolate()));
Steve Blocka7e24c12009-10-30 11:49:00 +000013900 }
13901}
13902
13903
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013904static void UnlockForAMoment(const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +000013905 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013906 v8::Unlocker unlocker(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000013907}
13908
13909
13910THREADED_TEST(LockUnlockLock) {
13911 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013912 v8::Locker locker(CcTest::isolate());
13913 v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000013914 LocalContext env;
13915 Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013916 v8::FunctionTemplate::New(CcTest::isolate(), UnlockForAMoment);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013917 Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
13918 CHECK(env->Global()
13919 ->Set(env.local(), v8_str("unlock_for_a_moment"), fun)
13920 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013921 Local<Script> script = v8_compile("(function () {"
13922 " unlock_for_a_moment();"
13923 " return 42;"
13924 "})();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013925 CHECK_EQ(42, script->Run(env.local())
13926 .ToLocalChecked()
13927 ->Int32Value(env.local())
13928 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013929 }
13930 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013931 v8::Locker locker(CcTest::isolate());
13932 v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000013933 LocalContext env;
13934 Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013935 v8::FunctionTemplate::New(CcTest::isolate(), UnlockForAMoment);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013936 Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
13937 CHECK(env->Global()
13938 ->Set(env.local(), v8_str("unlock_for_a_moment"), fun)
13939 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013940 Local<Script> script = v8_compile("(function () {"
13941 " unlock_for_a_moment();"
13942 " return 42;"
13943 "})();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013944 CHECK_EQ(42, script->Run(env.local())
13945 .ToLocalChecked()
13946 ->Int32Value(env.local())
13947 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000013948 }
13949}
13950
13951
Leon Clarked91b9f72010-01-27 17:25:45 +000013952static int GetGlobalObjectsCount() {
Leon Clarkeeab96aa2010-01-27 16:31:12 +000013953 int count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013954 i::HeapIterator it(CcTest::heap());
Leon Clarked91b9f72010-01-27 17:25:45 +000013955 for (i::HeapObject* object = it.next(); object != NULL; object = it.next())
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013956 if (object->IsJSGlobalObject()) {
13957 i::JSGlobalObject* g = i::JSGlobalObject::cast(object);
13958 // Skip dummy global object.
13959 if (i::GlobalDictionary::cast(g->properties())->NumberOfElements() != 0) {
13960 count++;
13961 }
13962 }
Leon Clarked91b9f72010-01-27 17:25:45 +000013963 return count;
13964}
13965
13966
Ben Murdochf87a2032010-10-22 12:50:53 +010013967static void CheckSurvivingGlobalObjectsCount(int expected) {
Steve Blocka7e24c12009-10-30 11:49:00 +000013968 // We need to collect all garbage twice to be sure that everything
13969 // has been collected. This is because inline caches are cleared in
13970 // the first garbage collection but some of the maps have already
13971 // been marked at that point. Therefore some of the maps are not
13972 // collected until the second garbage collection.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013973 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013974 CcTest::heap()->CollectAllGarbage(i::Heap::kMakeHeapIterableMask);
Leon Clarked91b9f72010-01-27 17:25:45 +000013975 int count = GetGlobalObjectsCount();
Steve Blocka7e24c12009-10-30 11:49:00 +000013976#ifdef DEBUG
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013977 if (count != expected) CcTest::heap()->TracePathToGlobal();
Steve Blocka7e24c12009-10-30 11:49:00 +000013978#endif
Ben Murdochf87a2032010-10-22 12:50:53 +010013979 CHECK_EQ(expected, count);
Steve Blocka7e24c12009-10-30 11:49:00 +000013980}
13981
13982
13983TEST(DontLeakGlobalObjects) {
13984 // Regression test for issues 1139850 and 1174891.
13985
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013986 i::FLAG_expose_gc = true;
Steve Blocka7e24c12009-10-30 11:49:00 +000013987 v8::V8::Initialize();
13988
Steve Blocka7e24c12009-10-30 11:49:00 +000013989 for (int i = 0; i < 5; i++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013990 { v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000013991 LocalContext context;
13992 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013993 CcTest::isolate()->ContextDisposedNotification();
Ben Murdochf87a2032010-10-22 12:50:53 +010013994 CheckSurvivingGlobalObjectsCount(0);
Steve Blocka7e24c12009-10-30 11:49:00 +000013995
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013996 { v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000013997 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013998 v8_compile("Date")->Run(context.local()).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000013999 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014000 CcTest::isolate()->ContextDisposedNotification();
Ben Murdochf87a2032010-10-22 12:50:53 +010014001 CheckSurvivingGlobalObjectsCount(0);
Steve Blocka7e24c12009-10-30 11:49:00 +000014002
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014003 { v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000014004 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014005 v8_compile("/aaa/")->Run(context.local()).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000014006 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014007 CcTest::isolate()->ContextDisposedNotification();
Ben Murdochf87a2032010-10-22 12:50:53 +010014008 CheckSurvivingGlobalObjectsCount(0);
Steve Blocka7e24c12009-10-30 11:49:00 +000014009
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014010 { v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000014011 const char* extension_list[] = { "v8/gc" };
14012 v8::ExtensionConfiguration extensions(1, extension_list);
14013 LocalContext context(&extensions);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014014 v8_compile("gc();")->Run(context.local()).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000014015 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014016 CcTest::isolate()->ContextDisposedNotification();
Ben Murdochf87a2032010-10-22 12:50:53 +010014017 CheckSurvivingGlobalObjectsCount(0);
Steve Blocka7e24c12009-10-30 11:49:00 +000014018 }
14019}
14020
14021
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014022TEST(CopyablePersistent) {
14023 LocalContext context;
14024 v8::Isolate* isolate = context->GetIsolate();
14025 i::GlobalHandles* globals =
14026 reinterpret_cast<i::Isolate*>(isolate)->global_handles();
14027 int initial_handles = globals->global_handles_count();
14028 typedef v8::Persistent<v8::Object, v8::CopyablePersistentTraits<v8::Object> >
14029 CopyableObject;
14030 {
14031 CopyableObject handle1;
14032 {
14033 v8::HandleScope scope(isolate);
14034 handle1.Reset(isolate, v8::Object::New(isolate));
14035 }
14036 CHECK_EQ(initial_handles + 1, globals->global_handles_count());
14037 CopyableObject handle2;
14038 handle2 = handle1;
14039 CHECK(handle1 == handle2);
14040 CHECK_EQ(initial_handles + 2, globals->global_handles_count());
14041 CopyableObject handle3(handle2);
14042 CHECK(handle1 == handle3);
14043 CHECK_EQ(initial_handles + 3, globals->global_handles_count());
14044 }
14045 // Verify autodispose
14046 CHECK_EQ(initial_handles, globals->global_handles_count());
14047}
14048
14049
14050static void WeakApiCallback(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014051 const v8::WeakCallbackInfo<Persistent<v8::Object>>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014052 data.GetParameter()->Reset();
14053 delete data.GetParameter();
14054}
14055
14056
14057TEST(WeakCallbackApi) {
14058 LocalContext context;
14059 v8::Isolate* isolate = context->GetIsolate();
14060 i::GlobalHandles* globals =
14061 reinterpret_cast<i::Isolate*>(isolate)->global_handles();
14062 int initial_handles = globals->global_handles_count();
14063 {
14064 v8::HandleScope scope(isolate);
14065 v8::Local<v8::Object> obj = v8::Object::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014066 CHECK(
14067 obj->Set(context.local(), v8_str("key"), v8::Integer::New(isolate, 231))
14068 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014069 v8::Persistent<v8::Object>* handle =
14070 new v8::Persistent<v8::Object>(isolate, obj);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014071 handle->SetWeak<v8::Persistent<v8::Object>>(
14072 handle, WeakApiCallback, v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014073 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014074 reinterpret_cast<i::Isolate*>(isolate)->heap()->CollectAllGarbage(
14075 i::Heap::kAbortIncrementalMarkingMask);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014076 // Verify disposed.
14077 CHECK_EQ(initial_handles, globals->global_handles_count());
14078}
14079
14080
Steve Blocka7e24c12009-10-30 11:49:00 +000014081v8::Persistent<v8::Object> some_object;
14082v8::Persistent<v8::Object> bad_handle;
14083
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014084
14085void NewPersistentHandleCallback2(
14086 const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014087 v8::HandleScope scope(data.GetIsolate());
14088 bad_handle.Reset(data.GetIsolate(), some_object);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014089}
14090
14091
14092void NewPersistentHandleCallback1(
14093 const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014094 data.GetParameter()->Reset();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014095 data.SetSecondPassCallback(NewPersistentHandleCallback2);
Steve Blocka7e24c12009-10-30 11:49:00 +000014096}
14097
14098
14099THREADED_TEST(NewPersistentHandleFromWeakCallback) {
14100 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014101 v8::Isolate* isolate = context->GetIsolate();
Steve Blocka7e24c12009-10-30 11:49:00 +000014102
14103 v8::Persistent<v8::Object> handle1, handle2;
14104 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014105 v8::HandleScope scope(isolate);
14106 some_object.Reset(isolate, v8::Object::New(isolate));
14107 handle1.Reset(isolate, v8::Object::New(isolate));
14108 handle2.Reset(isolate, v8::Object::New(isolate));
Steve Blocka7e24c12009-10-30 11:49:00 +000014109 }
14110 // Note: order is implementation dependent alas: currently
14111 // global handle nodes are processed by PostGarbageCollectionProcessing
14112 // in reverse allocation order, so if second allocated handle is deleted,
14113 // weak callback of the first handle would be able to 'reallocate' it.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014114 handle1.SetWeak(&handle1, NewPersistentHandleCallback1,
14115 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014116 handle2.Reset();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014117 CcTest::heap()->CollectAllGarbage();
Steve Blocka7e24c12009-10-30 11:49:00 +000014118}
14119
14120
14121v8::Persistent<v8::Object> to_be_disposed;
14122
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014123
14124void DisposeAndForceGcCallback2(
14125 const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014126 to_be_disposed.Reset();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014127 CcTest::heap()->CollectAllGarbage();
14128}
14129
14130
14131void DisposeAndForceGcCallback1(
14132 const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014133 data.GetParameter()->Reset();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014134 data.SetSecondPassCallback(DisposeAndForceGcCallback2);
Steve Blocka7e24c12009-10-30 11:49:00 +000014135}
14136
14137
14138THREADED_TEST(DoNotUseDeletedNodesInSecondLevelGc) {
14139 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014140 v8::Isolate* isolate = context->GetIsolate();
Steve Blocka7e24c12009-10-30 11:49:00 +000014141
14142 v8::Persistent<v8::Object> handle1, handle2;
14143 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014144 v8::HandleScope scope(isolate);
14145 handle1.Reset(isolate, v8::Object::New(isolate));
14146 handle2.Reset(isolate, v8::Object::New(isolate));
Steve Blocka7e24c12009-10-30 11:49:00 +000014147 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014148 handle1.SetWeak(&handle1, DisposeAndForceGcCallback1,
14149 v8::WeakCallbackType::kParameter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014150 to_be_disposed.Reset(isolate, handle2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014151 CcTest::heap()->CollectAllGarbage();
Steve Blocka7e24c12009-10-30 11:49:00 +000014152}
14153
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014154void DisposingCallback(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014155 const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014156 data.GetParameter()->Reset();
Steve Blockd0582a62009-12-15 09:54:21 +000014157}
14158
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014159void HandleCreatingCallback2(
14160 const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014161 v8::HandleScope scope(data.GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014162 v8::Global<v8::Object>(data.GetIsolate(), v8::Object::New(data.GetIsolate()));
14163}
14164
14165
14166void HandleCreatingCallback1(
14167 const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014168 data.GetParameter()->Reset();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014169 data.SetSecondPassCallback(HandleCreatingCallback2);
Steve Blockd0582a62009-12-15 09:54:21 +000014170}
14171
14172
14173THREADED_TEST(NoGlobalHandlesOrphaningDueToWeakCallback) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014174 v8::Locker locker(CcTest::isolate());
Steve Blockd0582a62009-12-15 09:54:21 +000014175 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014176 v8::Isolate* isolate = context->GetIsolate();
Steve Blockd0582a62009-12-15 09:54:21 +000014177
14178 v8::Persistent<v8::Object> handle1, handle2, handle3;
14179 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014180 v8::HandleScope scope(isolate);
14181 handle3.Reset(isolate, v8::Object::New(isolate));
14182 handle2.Reset(isolate, v8::Object::New(isolate));
14183 handle1.Reset(isolate, v8::Object::New(isolate));
Steve Blockd0582a62009-12-15 09:54:21 +000014184 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014185 handle2.SetWeak(&handle2, DisposingCallback,
14186 v8::WeakCallbackType::kParameter);
14187 handle3.SetWeak(&handle3, HandleCreatingCallback1,
14188 v8::WeakCallbackType::kParameter);
14189 CcTest::heap()->CollectAllGarbage();
14190 EmptyMessageQueues(isolate);
Steve Blockd0582a62009-12-15 09:54:21 +000014191}
14192
Steve Blocka7e24c12009-10-30 11:49:00 +000014193
14194THREADED_TEST(CheckForCrossContextObjectLiterals) {
14195 v8::V8::Initialize();
14196
14197 const int nof = 2;
14198 const char* sources[nof] = {
14199 "try { [ 2, 3, 4 ].forEach(5); } catch(e) { e.toString(); }",
14200 "Object()"
14201 };
14202
14203 for (int i = 0; i < nof; i++) {
14204 const char* source = sources[i];
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014205 { v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000014206 LocalContext context;
14207 CompileRun(source);
14208 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014209 { v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000014210 LocalContext context;
14211 CompileRun(source);
14212 }
14213 }
14214}
14215
14216
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014217static v8::Local<Value> NestedScope(v8::Local<Context> env) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014218 v8::EscapableHandleScope inner(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000014219 env->Enter();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014220 v8::Local<Value> three = v8_num(3);
14221 v8::Local<Value> value = inner.Escape(three);
Steve Blocka7e24c12009-10-30 11:49:00 +000014222 env->Exit();
14223 return value;
14224}
14225
14226
14227THREADED_TEST(NestedHandleScopeAndContexts) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014228 v8::Isolate* isolate = CcTest::isolate();
14229 v8::HandleScope outer(isolate);
14230 v8::Local<Context> env = Context::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000014231 env->Enter();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014232 v8::Local<Value> value = NestedScope(env);
14233 v8::Local<String> str(value->ToString(env).ToLocalChecked());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010014234 CHECK(!str.IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +000014235 env->Exit();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014236}
14237
14238
14239static bool MatchPointers(void* key1, void* key2) {
14240 return key1 == key2;
14241}
14242
14243
14244struct SymbolInfo {
14245 size_t id;
14246 size_t size;
14247 std::string name;
14248};
14249
14250
14251class SetFunctionEntryHookTest {
14252 public:
14253 SetFunctionEntryHookTest() {
14254 CHECK(instance_ == NULL);
14255 instance_ = this;
14256 }
14257 ~SetFunctionEntryHookTest() {
14258 CHECK(instance_ == this);
14259 instance_ = NULL;
14260 }
14261 void Reset() {
14262 symbols_.clear();
14263 symbol_locations_.clear();
14264 invocations_.clear();
14265 }
14266 void RunTest();
14267 void OnJitEvent(const v8::JitCodeEvent* event);
14268 static void JitEvent(const v8::JitCodeEvent* event) {
14269 CHECK(instance_ != NULL);
14270 instance_->OnJitEvent(event);
14271 }
14272
14273 void OnEntryHook(uintptr_t function,
14274 uintptr_t return_addr_location);
14275 static void EntryHook(uintptr_t function,
14276 uintptr_t return_addr_location) {
14277 CHECK(instance_ != NULL);
14278 instance_->OnEntryHook(function, return_addr_location);
14279 }
14280
14281 static void RuntimeCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
14282 CHECK(instance_ != NULL);
14283 args.GetReturnValue().Set(v8_num(42));
14284 }
14285 void RunLoopInNewEnv(v8::Isolate* isolate);
14286
14287 // Records addr as location of symbol.
14288 void InsertSymbolAt(i::Address addr, SymbolInfo* symbol);
14289
14290 // Finds the symbol containing addr
14291 SymbolInfo* FindSymbolForAddr(i::Address addr);
14292 // Returns the number of invocations where the caller name contains
14293 // \p caller_name and the function name contains \p function_name.
14294 int CountInvocations(const char* caller_name,
14295 const char* function_name);
14296
14297 i::Handle<i::JSFunction> foo_func_;
14298 i::Handle<i::JSFunction> bar_func_;
14299
14300 typedef std::map<size_t, SymbolInfo> SymbolMap;
14301 typedef std::map<i::Address, SymbolInfo*> SymbolLocationMap;
14302 typedef std::map<std::pair<SymbolInfo*, SymbolInfo*>, int> InvocationMap;
14303 SymbolMap symbols_;
14304 SymbolLocationMap symbol_locations_;
14305 InvocationMap invocations_;
14306
14307 static SetFunctionEntryHookTest* instance_;
14308};
14309SetFunctionEntryHookTest* SetFunctionEntryHookTest::instance_ = NULL;
14310
14311
14312// Returns true if addr is in the range [start, start+len).
14313static bool Overlaps(i::Address start, size_t len, i::Address addr) {
14314 if (start <= addr && start + len > addr)
14315 return true;
14316
14317 return false;
14318}
14319
14320void SetFunctionEntryHookTest::InsertSymbolAt(i::Address addr,
14321 SymbolInfo* symbol) {
14322 // Insert the symbol at the new location.
14323 SymbolLocationMap::iterator it =
14324 symbol_locations_.insert(std::make_pair(addr, symbol)).first;
14325 // Now erase symbols to the left and right that overlap this one.
14326 while (it != symbol_locations_.begin()) {
14327 SymbolLocationMap::iterator left = it;
14328 --left;
14329 if (!Overlaps(left->first, left->second->size, addr))
14330 break;
14331 symbol_locations_.erase(left);
14332 }
14333
14334 // Now erase symbols to the left and right that overlap this one.
14335 while (true) {
14336 SymbolLocationMap::iterator right = it;
14337 ++right;
14338 if (right == symbol_locations_.end())
14339 break;
14340 if (!Overlaps(addr, symbol->size, right->first))
14341 break;
14342 symbol_locations_.erase(right);
14343 }
14344}
14345
14346
14347void SetFunctionEntryHookTest::OnJitEvent(const v8::JitCodeEvent* event) {
14348 switch (event->type) {
14349 case v8::JitCodeEvent::CODE_ADDED: {
14350 CHECK(event->code_start != NULL);
14351 CHECK_NE(0, static_cast<int>(event->code_len));
14352 CHECK(event->name.str != NULL);
14353 size_t symbol_id = symbols_.size();
14354
14355 // Record the new symbol.
14356 SymbolInfo& info = symbols_[symbol_id];
14357 info.id = symbol_id;
14358 info.size = event->code_len;
14359 info.name.assign(event->name.str, event->name.str + event->name.len);
14360
14361 // And record it's location.
14362 InsertSymbolAt(reinterpret_cast<i::Address>(event->code_start), &info);
14363 }
14364 break;
14365
14366 case v8::JitCodeEvent::CODE_MOVED: {
14367 // We would like to never see code move that we haven't seen before,
14368 // but the code creation event does not happen until the line endings
14369 // have been calculated (this is so that we can report the line in the
14370 // script at which the function source is found, see
14371 // Compiler::RecordFunctionCompilation) and the line endings
14372 // calculations can cause a GC, which can move the newly created code
14373 // before its existence can be logged.
14374 SymbolLocationMap::iterator it(
14375 symbol_locations_.find(
14376 reinterpret_cast<i::Address>(event->code_start)));
14377 if (it != symbol_locations_.end()) {
14378 // Found a symbol at this location, move it.
14379 SymbolInfo* info = it->second;
14380 symbol_locations_.erase(it);
14381 InsertSymbolAt(reinterpret_cast<i::Address>(event->new_code_start),
14382 info);
14383 }
14384 }
14385 default:
14386 break;
14387 }
14388}
14389
14390void SetFunctionEntryHookTest::OnEntryHook(
14391 uintptr_t function, uintptr_t return_addr_location) {
14392 // Get the function's code object.
14393 i::Code* function_code = i::Code::GetCodeFromTargetAddress(
14394 reinterpret_cast<i::Address>(function));
14395 CHECK(function_code != NULL);
14396
14397 // Then try and look up the caller's code object.
14398 i::Address caller = *reinterpret_cast<i::Address*>(return_addr_location);
14399
14400 // Count the invocation.
14401 SymbolInfo* caller_symbol = FindSymbolForAddr(caller);
14402 SymbolInfo* function_symbol =
14403 FindSymbolForAddr(reinterpret_cast<i::Address>(function));
14404 ++invocations_[std::make_pair(caller_symbol, function_symbol)];
14405
14406 if (!bar_func_.is_null() && function_code == bar_func_->code()) {
14407 // Check that we have a symbol for the "bar" function at the right location.
14408 SymbolLocationMap::iterator it(
14409 symbol_locations_.find(function_code->instruction_start()));
14410 CHECK(it != symbol_locations_.end());
14411 }
14412
14413 if (!foo_func_.is_null() && function_code == foo_func_->code()) {
14414 // Check that we have a symbol for "foo" at the right location.
14415 SymbolLocationMap::iterator it(
14416 symbol_locations_.find(function_code->instruction_start()));
14417 CHECK(it != symbol_locations_.end());
14418 }
14419}
14420
14421
14422SymbolInfo* SetFunctionEntryHookTest::FindSymbolForAddr(i::Address addr) {
14423 SymbolLocationMap::iterator it(symbol_locations_.lower_bound(addr));
14424 // Do we have a direct hit on a symbol?
14425 if (it != symbol_locations_.end()) {
14426 if (it->first == addr)
14427 return it->second;
14428 }
14429
14430 // If not a direct hit, it'll have to be the previous symbol.
14431 if (it == symbol_locations_.begin())
14432 return NULL;
14433
14434 --it;
14435 size_t offs = addr - it->first;
14436 if (offs < it->second->size)
14437 return it->second;
14438
14439 return NULL;
14440}
14441
14442
14443int SetFunctionEntryHookTest::CountInvocations(
14444 const char* caller_name, const char* function_name) {
14445 InvocationMap::iterator it(invocations_.begin());
14446 int invocations = 0;
14447 for (; it != invocations_.end(); ++it) {
14448 SymbolInfo* caller = it->first.first;
14449 SymbolInfo* function = it->first.second;
14450
14451 // Filter out non-matching functions.
14452 if (function_name != NULL) {
14453 if (function->name.find(function_name) == std::string::npos)
14454 continue;
14455 }
14456
14457 // Filter out non-matching callers.
14458 if (caller_name != NULL) {
14459 if (caller == NULL)
14460 continue;
14461 if (caller->name.find(caller_name) == std::string::npos)
14462 continue;
14463 }
14464
14465 // It matches add the invocation count to the tally.
14466 invocations += it->second;
14467 }
14468
14469 return invocations;
14470}
14471
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014472void SetFunctionEntryHookTest::RunLoopInNewEnv(v8::Isolate* isolate) {
14473 v8::HandleScope outer(isolate);
14474 v8::Local<Context> env = Context::New(isolate);
14475 env->Enter();
14476
14477 Local<ObjectTemplate> t = ObjectTemplate::New(isolate);
14478 t->Set(v8_str("asdf"), v8::FunctionTemplate::New(isolate, RuntimeCallback));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014479 CHECK(env->Global()
14480 ->Set(env, v8_str("obj"), t->NewInstance(env).ToLocalChecked())
14481 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014482
14483 const char* script =
14484 "function bar() {\n"
14485 " var sum = 0;\n"
14486 " for (i = 0; i < 100; ++i)\n"
14487 " sum = foo(i);\n"
14488 " return sum;\n"
14489 "}\n"
14490 "function foo(i) { return i * i; }\n"
14491 "// Invoke on the runtime function.\n"
14492 "obj.asdf()";
14493 CompileRun(script);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014494 bar_func_ = i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(
14495 *env->Global()->Get(env, v8_str("bar")).ToLocalChecked()));
14496 CHECK(!bar_func_.is_null());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014497
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014498 foo_func_ = i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(
14499 *env->Global()->Get(env, v8_str("foo")).ToLocalChecked()));
14500 CHECK(!foo_func_.is_null());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014501
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014502 v8::Local<v8::Value> value = CompileRun("bar();");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014503 CHECK(value->IsNumber());
14504 CHECK_EQ(9801.0, v8::Number::Cast(*value)->Value());
14505
14506 // Test the optimized codegen path.
14507 value = CompileRun("%OptimizeFunctionOnNextCall(foo);"
14508 "bar();");
14509 CHECK(value->IsNumber());
14510 CHECK_EQ(9801.0, v8::Number::Cast(*value)->Value());
14511
14512 env->Exit();
14513}
14514
14515
14516void SetFunctionEntryHookTest::RunTest() {
14517 // Work in a new isolate throughout.
14518 v8::Isolate::CreateParams create_params;
14519 create_params.entry_hook = EntryHook;
14520 create_params.code_event_handler = JitEvent;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014521 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014522 v8::Isolate* isolate = v8::Isolate::New(create_params);
14523
14524 {
14525 v8::Isolate::Scope scope(isolate);
14526
14527 RunLoopInNewEnv(isolate);
14528
Ben Murdochc5610432016-08-08 18:44:38 +010014529 // Check the expected invocation counts.
14530 if (!i::FLAG_ignition) {
14531 CHECK_EQ(2, CountInvocations(NULL, "bar"));
14532 CHECK_EQ(200, CountInvocations("bar", "foo"));
14533 CHECK_EQ(200, CountInvocations(NULL, "foo"));
14534 } else {
14535 // For ignition we don't see the actual functions being called, instead
14536 // we see the IterpreterEntryTrampoline at least 102 times
14537 // (100 unoptimized calls to foo, and 2 calls to bar).
14538 CHECK_LE(102, CountInvocations(NULL, "InterpreterEntryTrampoline"));
14539 // We should also see the calls to the optimized function foo.
14540 CHECK_EQ(100, CountInvocations(NULL, "foo"));
14541 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014542
14543 // Verify that we have an entry hook on some specific stubs.
14544 CHECK_NE(0, CountInvocations(NULL, "CEntryStub"));
14545 CHECK_NE(0, CountInvocations(NULL, "JSEntryStub"));
14546 CHECK_NE(0, CountInvocations(NULL, "JSEntryTrampoline"));
14547 }
14548 isolate->Dispose();
14549
14550 Reset();
14551
14552 // Make sure a second isolate is unaffected by the previous entry hook.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014553 create_params = v8::Isolate::CreateParams();
14554 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
14555 isolate = v8::Isolate::New(create_params);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014556 {
14557 v8::Isolate::Scope scope(isolate);
14558
14559 // Reset the entry count to zero and set the entry hook.
14560 RunLoopInNewEnv(isolate);
14561
14562 // We should record no invocations in this isolate.
14563 CHECK_EQ(0, static_cast<int>(invocations_.size()));
14564 }
14565
14566 isolate->Dispose();
14567}
14568
14569
14570TEST(SetFunctionEntryHook) {
14571 // FunctionEntryHook does not work well with experimental natives.
14572 // Experimental natives are compiled during snapshot deserialization.
14573 // This test breaks because InstallGetter (function from snapshot that
14574 // only gets called from experimental natives) is compiled with entry hooks.
14575 i::FLAG_allow_natives_syntax = true;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014576 i::FLAG_turbo_inlining = false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014577 i::FLAG_use_inlining = false;
14578
14579 SetFunctionEntryHookTest test;
14580 test.RunTest();
14581}
14582
Ben Murdoch61f157c2016-09-16 13:49:30 +010014583static v8::base::HashMap* code_map = NULL;
14584static v8::base::HashMap* jitcode_line_info = NULL;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014585static int saw_bar = 0;
14586static int move_events = 0;
14587
14588
14589static bool FunctionNameIs(const char* expected,
14590 const v8::JitCodeEvent* event) {
14591 // Log lines for functions are of the general form:
Ben Murdochda12d292016-06-02 14:46:10 +010014592 // "LazyCompile:<type><function_name>" or Function:<type><function_name>,
14593 // where the type is one of "*", "~" or "".
14594 static const char* kPreamble;
14595 if (!i::FLAG_lazy || (i::FLAG_ignition && i::FLAG_ignition_eager)) {
14596 kPreamble = "Function:";
14597 } else {
14598 kPreamble = "LazyCompile:";
14599 }
14600 static size_t kPreambleLen = strlen(kPreamble);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014601
Ben Murdochda12d292016-06-02 14:46:10 +010014602 if (event->name.len < kPreambleLen ||
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014603 strncmp(kPreamble, event->name.str, kPreambleLen) != 0) {
14604 return false;
14605 }
14606
14607 const char* tail = event->name.str + kPreambleLen;
14608 size_t tail_len = event->name.len - kPreambleLen;
14609 size_t expected_len = strlen(expected);
14610 if (tail_len > 1 && (*tail == '*' || *tail == '~')) {
14611 --tail_len;
14612 ++tail;
14613 }
14614
14615 // Check for tails like 'bar :1'.
14616 if (tail_len > expected_len + 2 &&
14617 tail[expected_len] == ' ' &&
14618 tail[expected_len + 1] == ':' &&
14619 tail[expected_len + 2] &&
14620 !strncmp(tail, expected, expected_len)) {
14621 return true;
14622 }
14623
14624 if (tail_len != expected_len)
14625 return false;
14626
14627 return strncmp(tail, expected, expected_len) == 0;
14628}
14629
14630
14631static void event_handler(const v8::JitCodeEvent* event) {
14632 CHECK(event != NULL);
14633 CHECK(code_map != NULL);
14634 CHECK(jitcode_line_info != NULL);
14635
14636 class DummyJitCodeLineInfo {
14637 };
14638
14639 switch (event->type) {
14640 case v8::JitCodeEvent::CODE_ADDED: {
14641 CHECK(event->code_start != NULL);
14642 CHECK_NE(0, static_cast<int>(event->code_len));
14643 CHECK(event->name.str != NULL);
Ben Murdoch61f157c2016-09-16 13:49:30 +010014644 v8::base::HashMap::Entry* entry = code_map->LookupOrInsert(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014645 event->code_start, i::ComputePointerHash(event->code_start));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014646 entry->value = reinterpret_cast<void*>(event->code_len);
14647
14648 if (FunctionNameIs("bar", event)) {
14649 ++saw_bar;
14650 }
14651 }
14652 break;
14653
14654 case v8::JitCodeEvent::CODE_MOVED: {
14655 uint32_t hash = i::ComputePointerHash(event->code_start);
14656 // We would like to never see code move that we haven't seen before,
14657 // but the code creation event does not happen until the line endings
14658 // have been calculated (this is so that we can report the line in the
14659 // script at which the function source is found, see
14660 // Compiler::RecordFunctionCompilation) and the line endings
14661 // calculations can cause a GC, which can move the newly created code
14662 // before its existence can be logged.
Ben Murdoch61f157c2016-09-16 13:49:30 +010014663 v8::base::HashMap::Entry* entry =
14664 code_map->Lookup(event->code_start, hash);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014665 if (entry != NULL) {
14666 ++move_events;
14667
14668 CHECK_EQ(reinterpret_cast<void*>(event->code_len), entry->value);
14669 code_map->Remove(event->code_start, hash);
14670
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014671 entry = code_map->LookupOrInsert(
14672 event->new_code_start,
14673 i::ComputePointerHash(event->new_code_start));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014674 entry->value = reinterpret_cast<void*>(event->code_len);
14675 }
14676 }
14677 break;
14678
14679 case v8::JitCodeEvent::CODE_REMOVED:
14680 // Object/code removal events are currently not dispatched from the GC.
14681 CHECK(false);
14682 break;
14683
14684 // For CODE_START_LINE_INFO_RECORDING event, we will create one
14685 // DummyJitCodeLineInfo data structure pointed by event->user_dat. We
14686 // record it in jitcode_line_info.
14687 case v8::JitCodeEvent::CODE_START_LINE_INFO_RECORDING: {
14688 DummyJitCodeLineInfo* line_info = new DummyJitCodeLineInfo();
14689 v8::JitCodeEvent* temp_event = const_cast<v8::JitCodeEvent*>(event);
14690 temp_event->user_data = line_info;
Ben Murdoch61f157c2016-09-16 13:49:30 +010014691 v8::base::HashMap::Entry* entry = jitcode_line_info->LookupOrInsert(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014692 line_info, i::ComputePointerHash(line_info));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014693 entry->value = reinterpret_cast<void*>(line_info);
14694 }
14695 break;
14696 // For these two events, we will check whether the event->user_data
14697 // data structure is created before during CODE_START_LINE_INFO_RECORDING
14698 // event. And delete it in CODE_END_LINE_INFO_RECORDING event handling.
14699 case v8::JitCodeEvent::CODE_END_LINE_INFO_RECORDING: {
14700 CHECK(event->user_data != NULL);
14701 uint32_t hash = i::ComputePointerHash(event->user_data);
Ben Murdoch61f157c2016-09-16 13:49:30 +010014702 v8::base::HashMap::Entry* entry =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014703 jitcode_line_info->Lookup(event->user_data, hash);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014704 CHECK(entry != NULL);
14705 delete reinterpret_cast<DummyJitCodeLineInfo*>(event->user_data);
14706 }
14707 break;
14708
14709 case v8::JitCodeEvent::CODE_ADD_LINE_POS_INFO: {
14710 CHECK(event->user_data != NULL);
14711 uint32_t hash = i::ComputePointerHash(event->user_data);
Ben Murdoch61f157c2016-09-16 13:49:30 +010014712 v8::base::HashMap::Entry* entry =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014713 jitcode_line_info->Lookup(event->user_data, hash);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014714 CHECK(entry != NULL);
14715 }
14716 break;
14717
14718 default:
14719 // Impossible event.
14720 CHECK(false);
14721 break;
14722 }
14723}
14724
14725
14726UNINITIALIZED_TEST(SetJitCodeEventHandler) {
14727 i::FLAG_stress_compaction = true;
14728 i::FLAG_incremental_marking = false;
14729 if (i::FLAG_never_compact) return;
14730 const char* script =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014731 "function bar() {"
14732 " var sum = 0;"
14733 " for (i = 0; i < 10; ++i)"
14734 " sum = foo(i);"
14735 " return sum;"
14736 "}"
14737 "function foo(i) { return i; };"
14738 "bar();";
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014739
14740 // Run this test in a new isolate to make sure we don't
14741 // have remnants of state from other code.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014742 v8::Isolate::CreateParams create_params;
14743 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
14744 v8::Isolate* isolate = v8::Isolate::New(create_params);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014745 isolate->Enter();
14746 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
14747 i::Heap* heap = i_isolate->heap();
14748
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014749 // Start with a clean slate.
14750 heap->CollectAllAvailableGarbage("TestSetJitCodeEventHandler_Prepare");
14751
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014752 {
14753 v8::HandleScope scope(isolate);
Ben Murdoch61f157c2016-09-16 13:49:30 +010014754 v8::base::HashMap code(MatchPointers);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014755 code_map = &code;
14756
Ben Murdoch61f157c2016-09-16 13:49:30 +010014757 v8::base::HashMap lineinfo(MatchPointers);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014758 jitcode_line_info = &lineinfo;
14759
14760 saw_bar = 0;
14761 move_events = 0;
14762
14763 isolate->SetJitCodeEventHandler(v8::kJitCodeEventDefault, event_handler);
14764
14765 // Generate new code objects sparsely distributed across several
14766 // different fragmented code-space pages.
14767 const int kIterations = 10;
14768 for (int i = 0; i < kIterations; ++i) {
14769 LocalContext env(isolate);
14770 i::AlwaysAllocateScope always_allocate(i_isolate);
Ben Murdoch61f157c2016-09-16 13:49:30 +010014771 i::heap::SimulateFullSpace(i::FLAG_ignition ? heap->old_space()
14772 : heap->code_space());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014773 CompileRun(script);
14774
14775 // Keep a strong reference to the code object in the handle scope.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014776 i::Handle<i::Code> bar_code(
14777 i::Handle<i::JSFunction>::cast(
14778 v8::Utils::OpenHandle(*env->Global()
14779 ->Get(env.local(), v8_str("bar"))
14780 .ToLocalChecked()))
14781 ->code());
14782 i::Handle<i::Code> foo_code(
14783 i::Handle<i::JSFunction>::cast(
14784 v8::Utils::OpenHandle(*env->Global()
14785 ->Get(env.local(), v8_str("foo"))
14786 .ToLocalChecked()))
14787 ->code());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014788
14789 // Clear the compilation cache to get more wastage.
14790 reinterpret_cast<i::Isolate*>(isolate)->compilation_cache()->Clear();
14791 }
14792
14793 // Force code movement.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014794 heap->CollectAllAvailableGarbage("TestSetJitCodeEventHandler_Move");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014795
14796 isolate->SetJitCodeEventHandler(v8::kJitCodeEventDefault, NULL);
14797
14798 CHECK_LE(kIterations, saw_bar);
14799 CHECK_LT(0, move_events);
14800
14801 code_map = NULL;
14802 jitcode_line_info = NULL;
14803 }
14804
14805 isolate->Exit();
14806 isolate->Dispose();
14807
14808 // Do this in a new isolate.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014809 isolate = v8::Isolate::New(create_params);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014810 isolate->Enter();
14811
14812 // Verify that we get callbacks for existing code objects when we
14813 // request enumeration of existing code.
14814 {
14815 v8::HandleScope scope(isolate);
14816 LocalContext env(isolate);
14817 CompileRun(script);
14818
14819 // Now get code through initial iteration.
Ben Murdoch61f157c2016-09-16 13:49:30 +010014820 v8::base::HashMap code(MatchPointers);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014821 code_map = &code;
14822
Ben Murdoch61f157c2016-09-16 13:49:30 +010014823 v8::base::HashMap lineinfo(MatchPointers);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014824 jitcode_line_info = &lineinfo;
14825
14826 isolate->SetJitCodeEventHandler(v8::kJitCodeEventEnumExisting,
14827 event_handler);
14828 isolate->SetJitCodeEventHandler(v8::kJitCodeEventDefault, NULL);
14829
14830 jitcode_line_info = NULL;
14831 // We expect that we got some events. Note that if we could get code removal
14832 // notifications, we could compare two collections, one created by listening
14833 // from the time of creation of an isolate, and the other by subscribing
14834 // with EnumExisting.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014835 CHECK_LT(0u, code.occupancy());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014836
14837 code_map = NULL;
14838 }
14839
14840 isolate->Exit();
14841 isolate->Dispose();
Steve Blocka7e24c12009-10-30 11:49:00 +000014842}
14843
14844
14845THREADED_TEST(ExternalAllocatedMemory) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014846 v8::Isolate* isolate = CcTest::isolate();
14847 v8::HandleScope outer(isolate);
14848 v8::Local<Context> env(Context::New(isolate));
Ben Murdoch3ef787d2012-04-12 10:51:47 +010014849 CHECK(!env.IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014850 const int64_t kSize = 1024*1024;
14851 int64_t baseline = isolate->AdjustAmountOfExternalAllocatedMemory(0);
14852 CHECK_EQ(baseline + kSize,
14853 isolate->AdjustAmountOfExternalAllocatedMemory(kSize));
14854 CHECK_EQ(baseline,
14855 isolate->AdjustAmountOfExternalAllocatedMemory(-kSize));
Ben Murdoch61f157c2016-09-16 13:49:30 +010014856 const int64_t kTriggerGCSize = i::kExternalAllocationLimit + 1;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014857 CHECK_EQ(baseline + kTriggerGCSize,
14858 isolate->AdjustAmountOfExternalAllocatedMemory(kTriggerGCSize));
14859 CHECK_EQ(baseline,
14860 isolate->AdjustAmountOfExternalAllocatedMemory(-kTriggerGCSize));
14861}
14862
14863
14864TEST(Regress51719) {
14865 i::FLAG_incremental_marking = false;
14866 CcTest::InitializeVM();
14867
Ben Murdoch61f157c2016-09-16 13:49:30 +010014868 const int64_t kTriggerGCSize = i::kExternalAllocationLimit + 1;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014869 v8::Isolate* isolate = CcTest::isolate();
14870 isolate->AdjustAmountOfExternalAllocatedMemory(kTriggerGCSize);
Steve Blocka7e24c12009-10-30 11:49:00 +000014871}
14872
14873
14874// Regression test for issue 54, object templates with internal fields
14875// but no accessors or interceptors did not get their internal field
14876// count set on instances.
14877THREADED_TEST(Regress54) {
Steve Blocka7e24c12009-10-30 11:49:00 +000014878 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014879 v8::Isolate* isolate = context->GetIsolate();
14880 v8::HandleScope outer(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000014881 static v8::Persistent<v8::ObjectTemplate> templ;
14882 if (templ.IsEmpty()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014883 v8::EscapableHandleScope inner(isolate);
14884 v8::Local<v8::ObjectTemplate> local = v8::ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000014885 local->SetInternalFieldCount(1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014886 templ.Reset(isolate, inner.Escape(local));
Steve Blocka7e24c12009-10-30 11:49:00 +000014887 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014888 v8::Local<v8::Object> result =
14889 v8::Local<v8::ObjectTemplate>::New(isolate, templ)
14890 ->NewInstance(context.local())
14891 .ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000014892 CHECK_EQ(1, result->InternalFieldCount());
14893}
14894
14895
14896// If part of the threaded tests, this test makes ThreadingTest fail
14897// on mac.
14898TEST(CatchStackOverflow) {
Steve Blocka7e24c12009-10-30 11:49:00 +000014899 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014900 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014901 v8::TryCatch try_catch(context->GetIsolate());
14902 v8::Local<v8::Value> result = CompileRun(
14903 "function f() {"
14904 " return f();"
14905 "}"
14906 ""
14907 "f();");
Steve Blocka7e24c12009-10-30 11:49:00 +000014908 CHECK(result.IsEmpty());
14909}
14910
14911
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014912static void CheckTryCatchSourceInfo(v8::Local<v8::Script> script,
Steve Blocka7e24c12009-10-30 11:49:00 +000014913 const char* resource_name,
14914 int line_offset) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014915 v8::HandleScope scope(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014916 v8::TryCatch try_catch(CcTest::isolate());
14917 v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
14918 CHECK(script->Run(context).IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +000014919 CHECK(try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014920 v8::Local<v8::Message> message = try_catch.Message();
Steve Blocka7e24c12009-10-30 11:49:00 +000014921 CHECK(!message.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014922 CHECK_EQ(10 + line_offset, message->GetLineNumber(context).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000014923 CHECK_EQ(91, message->GetStartPosition());
14924 CHECK_EQ(92, message->GetEndPosition());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014925 CHECK_EQ(2, message->GetStartColumn(context).FromJust());
14926 CHECK_EQ(3, message->GetEndColumn(context).FromJust());
14927 v8::String::Utf8Value line(message->GetSourceLine(context).ToLocalChecked());
14928 CHECK_EQ(0, strcmp(" throw 'nirk';", *line));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014929 v8::String::Utf8Value name(message->GetScriptOrigin().ResourceName());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014930 CHECK_EQ(0, strcmp(resource_name, *name));
Steve Blocka7e24c12009-10-30 11:49:00 +000014931}
14932
14933
14934THREADED_TEST(TryCatchSourceInfo) {
Steve Blocka7e24c12009-10-30 11:49:00 +000014935 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014936 v8::HandleScope scope(context->GetIsolate());
14937 v8::Local<v8::String> source = v8_str(
Steve Blocka7e24c12009-10-30 11:49:00 +000014938 "function Foo() {\n"
14939 " return Bar();\n"
14940 "}\n"
14941 "\n"
14942 "function Bar() {\n"
14943 " return Baz();\n"
14944 "}\n"
14945 "\n"
14946 "function Baz() {\n"
14947 " throw 'nirk';\n"
14948 "}\n"
14949 "\n"
14950 "Foo();\n");
14951
14952 const char* resource_name;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014953 v8::Local<v8::Script> script;
Steve Blocka7e24c12009-10-30 11:49:00 +000014954 resource_name = "test.js";
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014955 script = CompileWithOrigin(source, resource_name);
Steve Blocka7e24c12009-10-30 11:49:00 +000014956 CheckTryCatchSourceInfo(script, resource_name, 0);
14957
14958 resource_name = "test1.js";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014959 v8::ScriptOrigin origin1(v8_str(resource_name));
14960 script =
14961 v8::Script::Compile(context.local(), source, &origin1).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000014962 CheckTryCatchSourceInfo(script, resource_name, 0);
14963
14964 resource_name = "test2.js";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014965 v8::ScriptOrigin origin2(v8_str(resource_name),
14966 v8::Integer::New(context->GetIsolate(), 7));
14967 script =
14968 v8::Script::Compile(context.local(), source, &origin2).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000014969 CheckTryCatchSourceInfo(script, resource_name, 7);
14970}
14971
14972
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014973THREADED_TEST(TryCatchSourceInfoForEOSError) {
14974 LocalContext context;
14975 v8::HandleScope scope(context->GetIsolate());
14976 v8::TryCatch try_catch(context->GetIsolate());
14977 CHECK(v8::Script::Compile(context.local(), v8_str("!\n")).IsEmpty());
14978 CHECK(try_catch.HasCaught());
14979 v8::Local<v8::Message> message = try_catch.Message();
14980 CHECK_EQ(1, message->GetLineNumber(context.local()).FromJust());
14981 CHECK_EQ(0, message->GetStartColumn(context.local()).FromJust());
14982}
14983
14984
Steve Blocka7e24c12009-10-30 11:49:00 +000014985THREADED_TEST(CompilationCache) {
Steve Blocka7e24c12009-10-30 11:49:00 +000014986 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000014987 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014988 v8::Local<v8::String> source0 = v8_str("1234");
14989 v8::Local<v8::String> source1 = v8_str("1234");
14990 v8::Local<v8::Script> script0 = CompileWithOrigin(source0, "test.js");
14991 v8::Local<v8::Script> script1 = CompileWithOrigin(source1, "test.js");
14992 v8::Local<v8::Script> script2 = v8::Script::Compile(context.local(), source0)
14993 .ToLocalChecked(); // different origin
14994 CHECK_EQ(1234, script0->Run(context.local())
14995 .ToLocalChecked()
14996 ->Int32Value(context.local())
14997 .FromJust());
14998 CHECK_EQ(1234, script1->Run(context.local())
14999 .ToLocalChecked()
15000 ->Int32Value(context.local())
15001 .FromJust());
15002 CHECK_EQ(1234, script2->Run(context.local())
15003 .ToLocalChecked()
15004 ->Int32Value(context.local())
15005 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000015006}
15007
15008
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015009static void FunctionNameCallback(
15010 const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Blocka7e24c12009-10-30 11:49:00 +000015011 ApiTestFuzzer::Fuzz();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015012 args.GetReturnValue().Set(v8_num(42));
Steve Blocka7e24c12009-10-30 11:49:00 +000015013}
15014
15015
15016THREADED_TEST(CallbackFunctionName) {
Steve Blocka7e24c12009-10-30 11:49:00 +000015017 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015018 v8::Isolate* isolate = context->GetIsolate();
15019 v8::HandleScope scope(isolate);
15020 Local<ObjectTemplate> t = ObjectTemplate::New(isolate);
15021 t->Set(v8_str("asdf"),
15022 v8::FunctionTemplate::New(isolate, FunctionNameCallback));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015023 CHECK(context->Global()
15024 ->Set(context.local(), v8_str("obj"),
15025 t->NewInstance(context.local()).ToLocalChecked())
15026 .FromJust());
15027 v8::Local<v8::Value> value = CompileRun("obj.asdf.name");
Steve Blocka7e24c12009-10-30 11:49:00 +000015028 CHECK(value->IsString());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015029 v8::String::Utf8Value name(value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015030 CHECK_EQ(0, strcmp("asdf", *name));
Steve Blocka7e24c12009-10-30 11:49:00 +000015031}
15032
15033
15034THREADED_TEST(DateAccess) {
Steve Blocka7e24c12009-10-30 11:49:00 +000015035 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015036 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015037 v8::Local<v8::Value> date =
15038 v8::Date::New(context.local(), 1224744689038.0).ToLocalChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +000015039 CHECK(date->IsDate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015040 CHECK_EQ(1224744689038.0, date.As<v8::Date>()->ValueOf());
Steve Blocka7e24c12009-10-30 11:49:00 +000015041}
15042
Ben Murdoch61f157c2016-09-16 13:49:30 +010015043void CheckIsSymbolAt(v8::Isolate* isolate, v8::Local<v8::Array> properties,
15044 unsigned index, const char* name) {
15045 v8::Local<v8::Context> context = isolate->GetCurrentContext();
15046 v8::Local<v8::Value> value =
15047 properties->Get(context, v8::Integer::New(isolate, index))
15048 .ToLocalChecked();
15049 CHECK(value->IsSymbol());
15050 v8::String::Utf8Value symbol_name(Local<Symbol>::Cast(value)->Name());
15051 CHECK_EQ(0, strcmp(name, *symbol_name));
15052}
15053
15054void CheckStringArray(v8::Isolate* isolate, v8::Local<v8::Array> properties,
15055 unsigned length, const char* names[]) {
15056 v8::Local<v8::Context> context = isolate->GetCurrentContext();
15057 CHECK_EQ(length, properties->Length());
15058 for (unsigned i = 0; i < length; i++) {
15059 v8::Local<v8::Value> value =
15060 properties->Get(context, v8::Integer::New(isolate, i)).ToLocalChecked();
15061 if (names[i] == nullptr) {
15062 DCHECK(value->IsSymbol());
15063 } else {
15064 v8::String::Utf8Value elm(value);
15065 CHECK_EQ(0, strcmp(names[i], *elm));
15066 }
15067 }
15068}
Steve Blocka7e24c12009-10-30 11:49:00 +000015069
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015070void CheckProperties(v8::Isolate* isolate, v8::Local<v8::Value> val,
Ben Murdoch61f157c2016-09-16 13:49:30 +010015071 unsigned length, const char* names[]) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015072 v8::Local<v8::Context> context = isolate->GetCurrentContext();
15073 v8::Local<v8::Object> obj = val.As<v8::Object>();
15074 v8::Local<v8::Array> props = obj->GetPropertyNames(context).ToLocalChecked();
Ben Murdoch61f157c2016-09-16 13:49:30 +010015075 CheckStringArray(isolate, props, length, names);
Steve Blocka7e24c12009-10-30 11:49:00 +000015076}
15077
15078
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015079void CheckOwnProperties(v8::Isolate* isolate, v8::Local<v8::Value> val,
15080 unsigned elmc, const char* elmv[]) {
15081 v8::Local<v8::Context> context = isolate->GetCurrentContext();
15082 v8::Local<v8::Object> obj = val.As<v8::Object>();
15083 v8::Local<v8::Array> props =
15084 obj->GetOwnPropertyNames(context).ToLocalChecked();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000015085 CHECK_EQ(elmc, props->Length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015086 for (unsigned i = 0; i < elmc; i++) {
15087 v8::String::Utf8Value elm(
15088 props->Get(context, v8::Integer::New(isolate, i)).ToLocalChecked());
15089 CHECK_EQ(0, strcmp(elmv[i], *elm));
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000015090 }
15091}
15092
15093
Steve Blocka7e24c12009-10-30 11:49:00 +000015094THREADED_TEST(PropertyEnumeration) {
Steve Blocka7e24c12009-10-30 11:49:00 +000015095 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015096 v8::Isolate* isolate = context->GetIsolate();
15097 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015098 v8::Local<v8::Value> obj = CompileRun(
Steve Blocka7e24c12009-10-30 11:49:00 +000015099 "var result = [];"
15100 "result[0] = {};"
15101 "result[1] = {a: 1, b: 2};"
15102 "result[2] = [1, 2, 3];"
15103 "var proto = {x: 1, y: 2, z: 3};"
15104 "var x = { __proto__: proto, w: 0, z: 1 };"
15105 "result[3] = x;"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015106 "result;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015107 v8::Local<v8::Array> elms = obj.As<v8::Array>();
15108 CHECK_EQ(4u, elms->Length());
Steve Blocka7e24c12009-10-30 11:49:00 +000015109 int elmc0 = 0;
15110 const char** elmv0 = NULL;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015111 CheckProperties(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015112 isolate,
15113 elms->Get(context.local(), v8::Integer::New(isolate, 0)).ToLocalChecked(),
15114 elmc0, elmv0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015115 CheckOwnProperties(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015116 isolate,
15117 elms->Get(context.local(), v8::Integer::New(isolate, 0)).ToLocalChecked(),
15118 elmc0, elmv0);
Steve Blocka7e24c12009-10-30 11:49:00 +000015119 int elmc1 = 2;
15120 const char* elmv1[] = {"a", "b"};
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015121 CheckProperties(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015122 isolate,
15123 elms->Get(context.local(), v8::Integer::New(isolate, 1)).ToLocalChecked(),
15124 elmc1, elmv1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015125 CheckOwnProperties(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015126 isolate,
15127 elms->Get(context.local(), v8::Integer::New(isolate, 1)).ToLocalChecked(),
15128 elmc1, elmv1);
Steve Blocka7e24c12009-10-30 11:49:00 +000015129 int elmc2 = 3;
15130 const char* elmv2[] = {"0", "1", "2"};
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015131 CheckProperties(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015132 isolate,
15133 elms->Get(context.local(), v8::Integer::New(isolate, 2)).ToLocalChecked(),
15134 elmc2, elmv2);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015135 CheckOwnProperties(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015136 isolate,
15137 elms->Get(context.local(), v8::Integer::New(isolate, 2)).ToLocalChecked(),
15138 elmc2, elmv2);
Steve Blocka7e24c12009-10-30 11:49:00 +000015139 int elmc3 = 4;
15140 const char* elmv3[] = {"w", "z", "x", "y"};
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015141 CheckProperties(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015142 isolate,
15143 elms->Get(context.local(), v8::Integer::New(isolate, 3)).ToLocalChecked(),
15144 elmc3, elmv3);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000015145 int elmc4 = 2;
15146 const char* elmv4[] = {"w", "z"};
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015147 CheckOwnProperties(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015148 isolate,
15149 elms->Get(context.local(), v8::Integer::New(isolate, 3)).ToLocalChecked(),
15150 elmc4, elmv4);
Steve Blocka7e24c12009-10-30 11:49:00 +000015151}
15152
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015153
Steve Block44f0eee2011-05-26 01:26:41 +010015154THREADED_TEST(PropertyEnumeration2) {
Steve Block44f0eee2011-05-26 01:26:41 +010015155 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015156 v8::Isolate* isolate = context->GetIsolate();
15157 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015158 v8::Local<v8::Value> obj = CompileRun(
Steve Block44f0eee2011-05-26 01:26:41 +010015159 "var result = [];"
15160 "result[0] = {};"
15161 "result[1] = {a: 1, b: 2};"
15162 "result[2] = [1, 2, 3];"
15163 "var proto = {x: 1, y: 2, z: 3};"
15164 "var x = { __proto__: proto, w: 0, z: 1 };"
15165 "result[3] = x;"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015166 "result;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015167 v8::Local<v8::Array> elms = obj.As<v8::Array>();
15168 CHECK_EQ(4u, elms->Length());
Steve Block44f0eee2011-05-26 01:26:41 +010015169 int elmc0 = 0;
15170 const char** elmv0 = NULL;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015171 CheckProperties(
15172 isolate,
15173 elms->Get(context.local(), v8::Integer::New(isolate, 0)).ToLocalChecked(),
15174 elmc0, elmv0);
Steve Block44f0eee2011-05-26 01:26:41 +010015175
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015176 v8::Local<v8::Value> val =
15177 elms->Get(context.local(), v8::Integer::New(isolate, 0)).ToLocalChecked();
15178 v8::Local<v8::Array> props =
15179 val.As<v8::Object>()->GetPropertyNames(context.local()).ToLocalChecked();
15180 CHECK_EQ(0u, props->Length());
Steve Block44f0eee2011-05-26 01:26:41 +010015181 for (uint32_t i = 0; i < props->Length(); i++) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040015182 printf("p[%u]\n", i);
Steve Block44f0eee2011-05-26 01:26:41 +010015183 }
15184}
Steve Blocka7e24c12009-10-30 11:49:00 +000015185
Ben Murdoch61f157c2016-09-16 13:49:30 +010015186THREADED_TEST(PropertyNames) {
15187 LocalContext context;
15188 v8::Isolate* isolate = context->GetIsolate();
15189 v8::HandleScope scope(isolate);
15190 v8::Local<v8::Value> result = CompileRun(
15191 "var result = {0: 0, 1: 1, a: 2, b: 3};"
15192 "result[Symbol('symbol')] = true;"
15193 "result.__proto__ = {2: 4, 3: 5, c: 6, d: 7};"
15194 "result;");
15195 v8::Local<v8::Object> object = result.As<v8::Object>();
15196 v8::PropertyFilter default_filter =
15197 static_cast<v8::PropertyFilter>(v8::ONLY_ENUMERABLE | v8::SKIP_SYMBOLS);
15198 v8::PropertyFilter include_symbols_filter = v8::ONLY_ENUMERABLE;
15199
15200 v8::Local<v8::Array> properties =
15201 object->GetPropertyNames(context.local()).ToLocalChecked();
15202 const char* expected_properties1[] = {"0", "1", "a", "b", "2", "3", "c", "d"};
15203 CheckStringArray(isolate, properties, 8, expected_properties1);
15204
15205 properties =
15206 object
15207 ->GetPropertyNames(context.local(),
15208 v8::KeyCollectionMode::kIncludePrototypes,
15209 default_filter, v8::IndexFilter::kIncludeIndices)
15210 .ToLocalChecked();
15211 CheckStringArray(isolate, properties, 8, expected_properties1);
15212
15213 properties = object
15214 ->GetPropertyNames(context.local(),
15215 v8::KeyCollectionMode::kIncludePrototypes,
15216 include_symbols_filter,
15217 v8::IndexFilter::kIncludeIndices)
15218 .ToLocalChecked();
15219 const char* expected_properties1_1[] = {"0", "1", "a", "b", nullptr,
15220 "2", "3", "c", "d"};
15221 CheckStringArray(isolate, properties, 9, expected_properties1_1);
15222 CheckIsSymbolAt(isolate, properties, 4, "symbol");
15223
15224 properties =
15225 object
15226 ->GetPropertyNames(context.local(),
15227 v8::KeyCollectionMode::kIncludePrototypes,
15228 default_filter, v8::IndexFilter::kSkipIndices)
15229 .ToLocalChecked();
15230 const char* expected_properties2[] = {"a", "b", "c", "d"};
15231 CheckStringArray(isolate, properties, 4, expected_properties2);
15232
15233 properties = object
15234 ->GetPropertyNames(context.local(),
15235 v8::KeyCollectionMode::kIncludePrototypes,
15236 include_symbols_filter,
15237 v8::IndexFilter::kSkipIndices)
15238 .ToLocalChecked();
15239 const char* expected_properties2_1[] = {"a", "b", nullptr, "c", "d"};
15240 CheckStringArray(isolate, properties, 5, expected_properties2_1);
15241 CheckIsSymbolAt(isolate, properties, 2, "symbol");
15242
15243 properties =
15244 object
15245 ->GetPropertyNames(context.local(), v8::KeyCollectionMode::kOwnOnly,
15246 default_filter, v8::IndexFilter::kIncludeIndices)
15247 .ToLocalChecked();
15248 const char* expected_properties3[] = {"0", "1", "a", "b"};
15249 CheckStringArray(isolate, properties, 4, expected_properties3);
15250
15251 properties = object
15252 ->GetPropertyNames(
15253 context.local(), v8::KeyCollectionMode::kOwnOnly,
15254 include_symbols_filter, v8::IndexFilter::kIncludeIndices)
15255 .ToLocalChecked();
15256 const char* expected_properties3_1[] = {"0", "1", "a", "b", nullptr};
15257 CheckStringArray(isolate, properties, 5, expected_properties3_1);
15258 CheckIsSymbolAt(isolate, properties, 4, "symbol");
15259
15260 properties =
15261 object
15262 ->GetPropertyNames(context.local(), v8::KeyCollectionMode::kOwnOnly,
15263 default_filter, v8::IndexFilter::kSkipIndices)
15264 .ToLocalChecked();
15265 const char* expected_properties4[] = {"a", "b"};
15266 CheckStringArray(isolate, properties, 2, expected_properties4);
15267
15268 properties = object
15269 ->GetPropertyNames(
15270 context.local(), v8::KeyCollectionMode::kOwnOnly,
15271 include_symbols_filter, v8::IndexFilter::kSkipIndices)
15272 .ToLocalChecked();
15273 const char* expected_properties4_1[] = {"a", "b", nullptr};
15274 CheckStringArray(isolate, properties, 3, expected_properties4_1);
15275 CheckIsSymbolAt(isolate, properties, 2, "symbol");
15276}
Steve Blocka7e24c12009-10-30 11:49:00 +000015277
15278THREADED_TEST(AccessChecksReenabledCorrectly) {
Steve Blocka7e24c12009-10-30 11:49:00 +000015279 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015280 v8::Isolate* isolate = context->GetIsolate();
15281 v8::HandleScope scope(isolate);
15282 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015283 templ->SetAccessCheckCallback(AccessAlwaysBlocked);
Steve Blocka7e24c12009-10-30 11:49:00 +000015284 templ->Set(v8_str("a"), v8_str("a"));
15285 // Add more than 8 (see kMaxFastProperties) properties
15286 // so that the constructor will force copying map.
15287 // Cannot sprintf, gcc complains unsafety.
15288 char buf[4];
15289 for (char i = '0'; i <= '9' ; i++) {
15290 buf[0] = i;
15291 for (char j = '0'; j <= '9'; j++) {
15292 buf[1] = j;
15293 for (char k = '0'; k <= '9'; k++) {
15294 buf[2] = k;
15295 buf[3] = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015296 templ->Set(v8_str(buf), v8::Number::New(isolate, k));
Steve Blocka7e24c12009-10-30 11:49:00 +000015297 }
15298 }
15299 }
15300
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015301 Local<v8::Object> instance_1 =
15302 templ->NewInstance(context.local()).ToLocalChecked();
15303 CHECK(context->Global()
15304 ->Set(context.local(), v8_str("obj_1"), instance_1)
15305 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000015306
15307 Local<Value> value_1 = CompileRun("obj_1.a");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015308 CHECK(value_1.IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +000015309
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015310 Local<v8::Object> instance_2 =
15311 templ->NewInstance(context.local()).ToLocalChecked();
15312 CHECK(context->Global()
15313 ->Set(context.local(), v8_str("obj_2"), instance_2)
15314 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000015315
15316 Local<Value> value_2 = CompileRun("obj_2.a");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015317 CHECK(value_2.IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +000015318}
15319
15320
Leon Clarkef7060e22010-06-03 12:02:55 +010015321// Tests that ScriptData can be serialized and deserialized.
15322TEST(PreCompileSerialization) {
Ben Murdochda12d292016-06-02 14:46:10 +010015323 // Producing cached parser data while parsing eagerly is not supported.
15324 if (!i::FLAG_lazy || (i::FLAG_ignition && i::FLAG_ignition_eager)) return;
15325
Leon Clarkef7060e22010-06-03 12:02:55 +010015326 v8::V8::Initialize();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015327 LocalContext env;
15328 v8::Isolate* isolate = env->GetIsolate();
15329 HandleScope handle_scope(isolate);
Leon Clarkef7060e22010-06-03 12:02:55 +010015330
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015331 i::FLAG_min_preparse_length = 0;
15332 const char* script = "function foo(a) { return a+1; }";
15333 v8::ScriptCompiler::Source source(v8_str(script));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015334 v8::ScriptCompiler::Compile(env.local(), &source,
15335 v8::ScriptCompiler::kProduceParserCache)
15336 .ToLocalChecked();
Leon Clarkef7060e22010-06-03 12:02:55 +010015337 // Serialize.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015338 const v8::ScriptCompiler::CachedData* cd = source.GetCachedData();
15339 i::byte* serialized_data = i::NewArray<i::byte>(cd->length);
15340 i::MemCopy(serialized_data, cd->data, cd->length);
Leon Clarkef7060e22010-06-03 12:02:55 +010015341
15342 // Deserialize.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015343 i::ScriptData* deserialized = new i::ScriptData(serialized_data, cd->length);
Leon Clarkef7060e22010-06-03 12:02:55 +010015344
15345 // Verify that the original is the same as the deserialized.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015346 CHECK_EQ(cd->length, deserialized->length());
15347 CHECK_EQ(0, memcmp(cd->data, deserialized->data(), cd->length));
Leon Clarkef7060e22010-06-03 12:02:55 +010015348
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015349 delete deserialized;
15350 i::DeleteArray(serialized_data);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +010015351}
15352
15353
Steve Blocka7e24c12009-10-30 11:49:00 +000015354// This tests that we do not allow dictionary load/call inline caches
15355// to use functions that have not yet been compiled. The potential
15356// problem of loading a function that has not yet been compiled can
15357// arise because we share code between contexts via the compilation
15358// cache.
15359THREADED_TEST(DictionaryICLoadedFunction) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015360 v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000015361 // Test LoadIC.
15362 for (int i = 0; i < 2; i++) {
15363 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015364 CHECK(context->Global()
15365 ->Set(context.local(), v8_str("tmp"), v8::True(CcTest::isolate()))
15366 .FromJust());
15367 context->Global()->Delete(context.local(), v8_str("tmp")).FromJust();
Steve Blocka7e24c12009-10-30 11:49:00 +000015368 CompileRun("for (var j = 0; j < 10; j++) new RegExp('');");
15369 }
15370 // Test CallIC.
15371 for (int i = 0; i < 2; i++) {
15372 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015373 CHECK(context->Global()
15374 ->Set(context.local(), v8_str("tmp"), v8::True(CcTest::isolate()))
15375 .FromJust());
15376 context->Global()->Delete(context.local(), v8_str("tmp")).FromJust();
Steve Blocka7e24c12009-10-30 11:49:00 +000015377 CompileRun("for (var j = 0; j < 10; j++) RegExp('')");
15378 }
15379}
15380
15381
15382// Test that cross-context new calls use the context of the callee to
15383// create the new JavaScript object.
15384THREADED_TEST(CrossContextNew) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015385 v8::Isolate* isolate = CcTest::isolate();
15386 v8::HandleScope scope(isolate);
15387 v8::Local<Context> context0 = Context::New(isolate);
15388 v8::Local<Context> context1 = Context::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000015389
15390 // Allow cross-domain access.
15391 Local<String> token = v8_str("<security token>");
15392 context0->SetSecurityToken(token);
15393 context1->SetSecurityToken(token);
15394
15395 // Set an 'x' property on the Object prototype and define a
15396 // constructor function in context0.
15397 context0->Enter();
15398 CompileRun("Object.prototype.x = 42; function C() {};");
15399 context0->Exit();
15400
15401 // Call the constructor function from context0 and check that the
15402 // result has the 'x' property.
15403 context1->Enter();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015404 CHECK(context1->Global()
15405 ->Set(context1, v8_str("other"), context0->Global())
15406 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000015407 Local<Value> value = CompileRun("var instance = new other.C(); instance.x");
15408 CHECK(value->IsInt32());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015409 CHECK_EQ(42, value->Int32Value(context1).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000015410 context1->Exit();
Steve Blocka7e24c12009-10-30 11:49:00 +000015411}
15412
15413
15414// Verify that we can clone an object
15415TEST(ObjectClone) {
Steve Blocka7e24c12009-10-30 11:49:00 +000015416 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015417 v8::Isolate* isolate = env->GetIsolate();
15418 v8::HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000015419
15420 const char* sample =
15421 "var rv = {};" \
15422 "rv.alpha = 'hello';" \
15423 "rv.beta = 123;" \
15424 "rv;";
15425
15426 // Create an object, verify basics.
15427 Local<Value> val = CompileRun(sample);
15428 CHECK(val->IsObject());
Steve Block6ded16b2010-05-10 14:33:55 +010015429 Local<v8::Object> obj = val.As<v8::Object>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015430 obj->Set(env.local(), v8_str("gamma"), v8_str("cloneme")).FromJust();
Steve Blocka7e24c12009-10-30 11:49:00 +000015431
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015432 CHECK(v8_str("hello")
15433 ->Equals(env.local(),
15434 obj->Get(env.local(), v8_str("alpha")).ToLocalChecked())
15435 .FromJust());
15436 CHECK(v8::Integer::New(isolate, 123)
15437 ->Equals(env.local(),
15438 obj->Get(env.local(), v8_str("beta")).ToLocalChecked())
15439 .FromJust());
15440 CHECK(v8_str("cloneme")
15441 ->Equals(env.local(),
15442 obj->Get(env.local(), v8_str("gamma")).ToLocalChecked())
15443 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000015444
15445 // Clone it.
15446 Local<v8::Object> clone = obj->Clone();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015447 CHECK(v8_str("hello")
15448 ->Equals(env.local(),
15449 clone->Get(env.local(), v8_str("alpha")).ToLocalChecked())
15450 .FromJust());
15451 CHECK(v8::Integer::New(isolate, 123)
15452 ->Equals(env.local(),
15453 clone->Get(env.local(), v8_str("beta")).ToLocalChecked())
15454 .FromJust());
15455 CHECK(v8_str("cloneme")
15456 ->Equals(env.local(),
15457 clone->Get(env.local(), v8_str("gamma")).ToLocalChecked())
15458 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000015459
15460 // Set a property on the clone, verify each object.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015461 CHECK(clone->Set(env.local(), v8_str("beta"), v8::Integer::New(isolate, 456))
15462 .FromJust());
15463 CHECK(v8::Integer::New(isolate, 123)
15464 ->Equals(env.local(),
15465 obj->Get(env.local(), v8_str("beta")).ToLocalChecked())
15466 .FromJust());
15467 CHECK(v8::Integer::New(isolate, 456)
15468 ->Equals(env.local(),
15469 clone->Get(env.local(), v8_str("beta")).ToLocalChecked())
15470 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000015471}
15472
15473
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015474class OneByteVectorResource : public v8::String::ExternalOneByteStringResource {
Steve Blocka7e24c12009-10-30 11:49:00 +000015475 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015476 explicit OneByteVectorResource(i::Vector<const char> vector)
Steve Blocka7e24c12009-10-30 11:49:00 +000015477 : data_(vector) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015478 virtual ~OneByteVectorResource() {}
Steve Blocka7e24c12009-10-30 11:49:00 +000015479 virtual size_t length() const { return data_.length(); }
15480 virtual const char* data() const { return data_.start(); }
15481 private:
15482 i::Vector<const char> data_;
15483};
15484
15485
15486class UC16VectorResource : public v8::String::ExternalStringResource {
15487 public:
15488 explicit UC16VectorResource(i::Vector<const i::uc16> vector)
15489 : data_(vector) {}
15490 virtual ~UC16VectorResource() {}
15491 virtual size_t length() const { return data_.length(); }
15492 virtual const i::uc16* data() const { return data_.start(); }
15493 private:
15494 i::Vector<const i::uc16> data_;
15495};
15496
15497
15498static void MorphAString(i::String* string,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015499 OneByteVectorResource* one_byte_resource,
Steve Blocka7e24c12009-10-30 11:49:00 +000015500 UC16VectorResource* uc16_resource) {
15501 CHECK(i::StringShape(string).IsExternal());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015502 if (string->IsOneByteRepresentation()) {
15503 // Check old map is not internalized or long.
15504 CHECK(string->map() == CcTest::heap()->external_one_byte_string_map());
Steve Blocka7e24c12009-10-30 11:49:00 +000015505 // Morph external string to be TwoByte string.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015506 string->set_map(CcTest::heap()->external_string_map());
Steve Blocka7e24c12009-10-30 11:49:00 +000015507 i::ExternalTwoByteString* morphed =
15508 i::ExternalTwoByteString::cast(string);
15509 morphed->set_resource(uc16_resource);
15510 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015511 // Check old map is not internalized or long.
15512 CHECK(string->map() == CcTest::heap()->external_string_map());
15513 // Morph external string to be one-byte string.
15514 string->set_map(CcTest::heap()->external_one_byte_string_map());
15515 i::ExternalOneByteString* morphed = i::ExternalOneByteString::cast(string);
15516 morphed->set_resource(one_byte_resource);
Steve Blocka7e24c12009-10-30 11:49:00 +000015517 }
15518}
15519
15520
15521// Test that we can still flatten a string if the components it is built up
15522// from have been turned into 16 bit strings in the mean time.
15523THREADED_TEST(MorphCompositeStringTest) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010015524 char utf_buffer[129];
Steve Blocka7e24c12009-10-30 11:49:00 +000015525 const char* c_string = "Now is the time for all good men"
15526 " to come to the aid of the party";
15527 uint16_t* two_byte_string = AsciiToTwoByteString(c_string);
15528 {
Steve Blocka7e24c12009-10-30 11:49:00 +000015529 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015530 i::Factory* factory = CcTest::i_isolate()->factory();
15531 v8::HandleScope scope(env->GetIsolate());
15532 OneByteVectorResource one_byte_resource(
Steve Blockd0582a62009-12-15 09:54:21 +000015533 i::Vector<const char>(c_string, i::StrLength(c_string)));
Steve Blocka7e24c12009-10-30 11:49:00 +000015534 UC16VectorResource uc16_resource(
Steve Blockd0582a62009-12-15 09:54:21 +000015535 i::Vector<const uint16_t>(two_byte_string,
15536 i::StrLength(c_string)));
Steve Blocka7e24c12009-10-30 11:49:00 +000015537
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015538 Local<String> lhs(
15539 v8::Utils::ToLocal(factory->NewExternalStringFromOneByte(
15540 &one_byte_resource).ToHandleChecked()));
15541 Local<String> rhs(
15542 v8::Utils::ToLocal(factory->NewExternalStringFromOneByte(
15543 &one_byte_resource).ToHandleChecked()));
Steve Blocka7e24c12009-10-30 11:49:00 +000015544
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015545 CHECK(env->Global()->Set(env.local(), v8_str("lhs"), lhs).FromJust());
15546 CHECK(env->Global()->Set(env.local(), v8_str("rhs"), rhs).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000015547
15548 CompileRun(
15549 "var cons = lhs + rhs;"
15550 "var slice = lhs.substring(1, lhs.length - 1);"
15551 "var slice_on_cons = (lhs + rhs).substring(1, lhs.length *2 - 1);");
15552
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015553 CHECK(lhs->IsOneByte());
15554 CHECK(rhs->IsOneByte());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010015555
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015556 MorphAString(*v8::Utils::OpenHandle(*lhs), &one_byte_resource,
15557 &uc16_resource);
15558 MorphAString(*v8::Utils::OpenHandle(*rhs), &one_byte_resource,
15559 &uc16_resource);
Steve Blocka7e24c12009-10-30 11:49:00 +000015560
Ben Murdoch3ef787d2012-04-12 10:51:47 +010015561 // This should UTF-8 without flattening, since everything is ASCII.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015562 Local<String> cons =
15563 v8_compile("cons")->Run(env.local()).ToLocalChecked().As<String>();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010015564 CHECK_EQ(128, cons->Utf8Length());
15565 int nchars = -1;
15566 CHECK_EQ(129, cons->WriteUtf8(utf_buffer, -1, &nchars));
15567 CHECK_EQ(128, nchars);
15568 CHECK_EQ(0, strcmp(
15569 utf_buffer,
15570 "Now is the time for all good men to come to the aid of the party"
15571 "Now is the time for all good men to come to the aid of the party"));
15572
Steve Blocka7e24c12009-10-30 11:49:00 +000015573 // Now do some stuff to make sure the strings are flattened, etc.
15574 CompileRun(
15575 "/[^a-z]/.test(cons);"
15576 "/[^a-z]/.test(slice);"
15577 "/[^a-z]/.test(slice_on_cons);");
15578 const char* expected_cons =
15579 "Now is the time for all good men to come to the aid of the party"
15580 "Now is the time for all good men to come to the aid of the party";
15581 const char* expected_slice =
15582 "ow is the time for all good men to come to the aid of the part";
15583 const char* expected_slice_on_cons =
15584 "ow is the time for all good men to come to the aid of the party"
15585 "Now is the time for all good men to come to the aid of the part";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015586 CHECK(v8_str(expected_cons)
15587 ->Equals(env.local(), env->Global()
15588 ->Get(env.local(), v8_str("cons"))
15589 .ToLocalChecked())
15590 .FromJust());
15591 CHECK(v8_str(expected_slice)
15592 ->Equals(env.local(), env->Global()
15593 ->Get(env.local(), v8_str("slice"))
15594 .ToLocalChecked())
15595 .FromJust());
15596 CHECK(v8_str(expected_slice_on_cons)
15597 ->Equals(env.local(),
15598 env->Global()
15599 ->Get(env.local(), v8_str("slice_on_cons"))
15600 .ToLocalChecked())
15601 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000015602 }
Ben Murdoch3bec4d22010-07-22 14:51:16 +010015603 i::DeleteArray(two_byte_string);
Steve Blocka7e24c12009-10-30 11:49:00 +000015604}
15605
15606
15607TEST(CompileExternalTwoByteSource) {
Steve Blocka7e24c12009-10-30 11:49:00 +000015608 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015609 v8::HandleScope scope(context->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000015610
15611 // This is a very short list of sources, which currently is to check for a
15612 // regression caused by r2703.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015613 const char* one_byte_sources[] = {
15614 "0.5",
15615 "-0.5", // This mainly testes PushBack in the Scanner.
15616 "--0.5", // This mainly testes PushBack in the Scanner.
15617 NULL};
Steve Blocka7e24c12009-10-30 11:49:00 +000015618
15619 // Compile the sources as external two byte strings.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015620 for (int i = 0; one_byte_sources[i] != NULL; i++) {
15621 uint16_t* two_byte_string = AsciiToTwoByteString(one_byte_sources[i]);
15622 TestResource* uc16_resource = new TestResource(two_byte_string);
15623 v8::Local<v8::String> source =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015624 v8::String::NewExternalTwoByte(context->GetIsolate(), uc16_resource)
15625 .ToLocalChecked();
15626 v8::Script::Compile(context.local(), source).FromMaybe(Local<Script>());
Steve Blocka7e24c12009-10-30 11:49:00 +000015627 }
15628}
15629
15630
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015631#ifndef V8_INTERPRETED_REGEXP
15632
15633struct RegExpInterruptionData {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040015634 v8::base::Atomic32 loop_count;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015635 UC16VectorResource* string_resource;
15636 v8::Persistent<v8::String> string;
15637} regexp_interruption_data;
15638
15639
15640class RegExpInterruptionThread : public v8::base::Thread {
Steve Blocka7e24c12009-10-30 11:49:00 +000015641 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015642 explicit RegExpInterruptionThread(v8::Isolate* isolate)
15643 : Thread(Options("TimeoutThread")), isolate_(isolate) {}
Steve Blocka7e24c12009-10-30 11:49:00 +000015644
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015645 virtual void Run() {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040015646 for (v8::base::NoBarrier_Store(&regexp_interruption_data.loop_count, 0);
15647 v8::base::NoBarrier_Load(&regexp_interruption_data.loop_count) < 7;
15648 v8::base::NoBarrier_AtomicIncrement(
15649 &regexp_interruption_data.loop_count, 1)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015650 // Wait a bit before requesting GC.
15651 v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(50));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015652 reinterpret_cast<i::Isolate*>(isolate_)->stack_guard()->RequestGC();
Steve Blocka7e24c12009-10-30 11:49:00 +000015653 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015654 // Wait a bit before terminating.
15655 v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(50));
15656 isolate_->TerminateExecution();
Steve Blocka7e24c12009-10-30 11:49:00 +000015657 }
Steve Blocka7e24c12009-10-30 11:49:00 +000015658
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000015659 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015660 v8::Isolate* isolate_;
Steve Blocka7e24c12009-10-30 11:49:00 +000015661};
15662
15663
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015664void RunBeforeGC(v8::Isolate* isolate, v8::GCType type,
15665 v8::GCCallbackFlags flags) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040015666 if (v8::base::NoBarrier_Load(&regexp_interruption_data.loop_count) != 2) {
15667 return;
15668 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015669 v8::HandleScope scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015670 v8::Local<v8::String> string = v8::Local<v8::String>::New(
15671 CcTest::isolate(), regexp_interruption_data.string);
15672 string->MakeExternal(regexp_interruption_data.string_resource);
Steve Blocka7e24c12009-10-30 11:49:00 +000015673}
15674
15675
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015676// Test that RegExp execution can be interrupted. Specifically, we test
15677// * interrupting with GC
15678// * turn the subject string from one-byte internal to two-byte external string
15679// * force termination
15680TEST(RegExpInterruption) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015681 LocalContext env;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015682 v8::HandleScope scope(env->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015683
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015684 RegExpInterruptionThread timeout_thread(env->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015685
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015686 env->GetIsolate()->AddGCPrologueCallback(RunBeforeGC);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015687 static const char* one_byte_content = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
15688 i::uc16* uc16_content = AsciiToTwoByteString(one_byte_content);
15689 v8::Local<v8::String> string = v8_str(one_byte_content);
15690
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015691 env->Global()->Set(env.local(), v8_str("a"), string).FromJust();
15692 regexp_interruption_data.string.Reset(env->GetIsolate(), string);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015693 regexp_interruption_data.string_resource = new UC16VectorResource(
15694 i::Vector<const i::uc16>(uc16_content, i::StrLength(one_byte_content)));
15695
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015696 v8::TryCatch try_catch(env->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015697 timeout_thread.Start();
15698
15699 CompileRun("/((a*)*)*b/.exec(a)");
15700 CHECK(try_catch.HasTerminated());
15701
15702 timeout_thread.Join();
15703
15704 regexp_interruption_data.string.Reset();
15705 i::DeleteArray(uc16_content);
15706}
15707
15708#endif // V8_INTERPRETED_REGEXP
15709
15710
15711// Test that we cannot set a property on the global object if there
Steve Blocka7e24c12009-10-30 11:49:00 +000015712// is a read-only property in the prototype chain.
15713TEST(ReadOnlyPropertyInGlobalProto) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015714 v8::Isolate* isolate = CcTest::isolate();
15715 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015716 v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000015717 LocalContext context(0, templ);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015718 v8::Local<v8::Object> global = context->Global();
15719 v8::Local<v8::Object> global_proto = v8::Local<v8::Object>::Cast(
15720 global->Get(context.local(), v8_str("__proto__")).ToLocalChecked());
15721 global_proto->DefineOwnProperty(context.local(), v8_str("x"),
15722 v8::Integer::New(isolate, 0), v8::ReadOnly)
15723 .FromJust();
15724 global_proto->DefineOwnProperty(context.local(), v8_str("y"),
15725 v8::Integer::New(isolate, 0), v8::ReadOnly)
15726 .FromJust();
Steve Blocka7e24c12009-10-30 11:49:00 +000015727 // Check without 'eval' or 'with'.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015728 v8::Local<v8::Value> res =
Steve Blocka7e24c12009-10-30 11:49:00 +000015729 CompileRun("function f() { x = 42; return x; }; f()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015730 CHECK(v8::Integer::New(isolate, 0)->Equals(context.local(), res).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000015731 // Check with 'eval'.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015732 res = CompileRun("function f() { eval('1'); y = 43; return y; }; f()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015733 CHECK(v8::Integer::New(isolate, 0)->Equals(context.local(), res).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000015734 // Check with 'with'.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015735 res = CompileRun("function f() { with (this) { y = 44 }; return y; }; f()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015736 CHECK(v8::Integer::New(isolate, 0)->Equals(context.local(), res).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000015737}
15738
Steve Blocka7e24c12009-10-30 11:49:00 +000015739
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015740TEST(CreateDataProperty) {
15741 LocalContext env;
15742 v8::Isolate* isolate = env->GetIsolate();
15743 v8::HandleScope handle_scope(isolate);
15744
15745 CompileRun(
15746 "var a = {};"
15747 "var b = [];"
15748 "Object.defineProperty(a, 'foo', {value: 23});"
15749 "Object.defineProperty(a, 'bar', {value: 23, configurable: true});");
15750
15751 v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(
15752 env->Global()->Get(env.local(), v8_str("a")).ToLocalChecked());
15753 v8::Local<v8::Array> arr = v8::Local<v8::Array>::Cast(
15754 env->Global()->Get(env.local(), v8_str("b")).ToLocalChecked());
15755 {
15756 // Can't change a non-configurable properties.
15757 v8::TryCatch try_catch(isolate);
15758 CHECK(!obj->CreateDataProperty(env.local(), v8_str("foo"),
15759 v8::Integer::New(isolate, 42)).FromJust());
15760 CHECK(!try_catch.HasCaught());
15761 CHECK(obj->CreateDataProperty(env.local(), v8_str("bar"),
15762 v8::Integer::New(isolate, 42)).FromJust());
15763 CHECK(!try_catch.HasCaught());
15764 v8::Local<v8::Value> val =
15765 obj->Get(env.local(), v8_str("bar")).ToLocalChecked();
15766 CHECK(val->IsNumber());
15767 CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000015768 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015769
15770 {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015771 // Set a regular property.
15772 v8::TryCatch try_catch(isolate);
15773 CHECK(obj->CreateDataProperty(env.local(), v8_str("blub"),
15774 v8::Integer::New(isolate, 42)).FromJust());
15775 CHECK(!try_catch.HasCaught());
15776 v8::Local<v8::Value> val =
15777 obj->Get(env.local(), v8_str("blub")).ToLocalChecked();
15778 CHECK(val->IsNumber());
15779 CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
15780 }
15781
15782 {
15783 // Set an indexed property.
15784 v8::TryCatch try_catch(isolate);
15785 CHECK(obj->CreateDataProperty(env.local(), v8_str("1"),
15786 v8::Integer::New(isolate, 42)).FromJust());
15787 CHECK(!try_catch.HasCaught());
15788 v8::Local<v8::Value> val = obj->Get(env.local(), 1).ToLocalChecked();
15789 CHECK(val->IsNumber());
15790 CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
15791 }
15792
15793 {
15794 // Special cases for arrays.
15795 v8::TryCatch try_catch(isolate);
15796 CHECK(!arr->CreateDataProperty(env.local(), v8_str("length"),
15797 v8::Integer::New(isolate, 1)).FromJust());
15798 CHECK(!try_catch.HasCaught());
15799 }
15800 {
15801 // Special cases for arrays: index exceeds the array's length
15802 v8::TryCatch try_catch(isolate);
15803 CHECK(arr->CreateDataProperty(env.local(), 1, v8::Integer::New(isolate, 23))
15804 .FromJust());
15805 CHECK(!try_catch.HasCaught());
15806 CHECK_EQ(2U, arr->Length());
15807 v8::Local<v8::Value> val = arr->Get(env.local(), 1).ToLocalChecked();
15808 CHECK(val->IsNumber());
15809 CHECK_EQ(23.0, val->NumberValue(env.local()).FromJust());
15810
15811 // Set an existing entry.
15812 CHECK(arr->CreateDataProperty(env.local(), 0, v8::Integer::New(isolate, 42))
15813 .FromJust());
15814 CHECK(!try_catch.HasCaught());
15815 val = arr->Get(env.local(), 0).ToLocalChecked();
15816 CHECK(val->IsNumber());
15817 CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
15818 }
15819
15820 CompileRun("Object.freeze(a);");
15821 {
15822 // Can't change non-extensible objects.
15823 v8::TryCatch try_catch(isolate);
15824 CHECK(!obj->CreateDataProperty(env.local(), v8_str("baz"),
15825 v8::Integer::New(isolate, 42)).FromJust());
15826 CHECK(!try_catch.HasCaught());
15827 }
15828
15829 v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
15830 templ->SetAccessCheckCallback(AccessAlwaysBlocked);
15831 v8::Local<v8::Object> access_checked =
15832 templ->NewInstance(env.local()).ToLocalChecked();
15833 {
15834 v8::TryCatch try_catch(isolate);
15835 CHECK(access_checked->CreateDataProperty(env.local(), v8_str("foo"),
15836 v8::Integer::New(isolate, 42))
15837 .IsNothing());
15838 CHECK(try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015839 }
15840}
15841
15842
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015843TEST(DefineOwnProperty) {
15844 LocalContext env;
15845 v8::Isolate* isolate = env->GetIsolate();
15846 v8::HandleScope handle_scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000015847
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015848 CompileRun(
15849 "var a = {};"
15850 "var b = [];"
15851 "Object.defineProperty(a, 'foo', {value: 23});"
15852 "Object.defineProperty(a, 'bar', {value: 23, configurable: true});");
Steve Blocka7e24c12009-10-30 11:49:00 +000015853
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015854 v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(
15855 env->Global()->Get(env.local(), v8_str("a")).ToLocalChecked());
15856 v8::Local<v8::Array> arr = v8::Local<v8::Array>::Cast(
15857 env->Global()->Get(env.local(), v8_str("b")).ToLocalChecked());
15858 {
15859 // Can't change a non-configurable properties.
15860 v8::TryCatch try_catch(isolate);
15861 CHECK(!obj->DefineOwnProperty(env.local(), v8_str("foo"),
15862 v8::Integer::New(isolate, 42)).FromJust());
15863 CHECK(!try_catch.HasCaught());
15864 CHECK(obj->DefineOwnProperty(env.local(), v8_str("bar"),
15865 v8::Integer::New(isolate, 42)).FromJust());
15866 CHECK(!try_catch.HasCaught());
15867 v8::Local<v8::Value> val =
15868 obj->Get(env.local(), v8_str("bar")).ToLocalChecked();
15869 CHECK(val->IsNumber());
15870 CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
15871 }
15872
15873 {
15874 // Set a regular property.
15875 v8::TryCatch try_catch(isolate);
15876 CHECK(obj->DefineOwnProperty(env.local(), v8_str("blub"),
15877 v8::Integer::New(isolate, 42)).FromJust());
15878 CHECK(!try_catch.HasCaught());
15879 v8::Local<v8::Value> val =
15880 obj->Get(env.local(), v8_str("blub")).ToLocalChecked();
15881 CHECK(val->IsNumber());
15882 CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
15883 }
15884
15885 {
15886 // Set an indexed property.
15887 v8::TryCatch try_catch(isolate);
15888 CHECK(obj->DefineOwnProperty(env.local(), v8_str("1"),
15889 v8::Integer::New(isolate, 42)).FromJust());
15890 CHECK(!try_catch.HasCaught());
15891 v8::Local<v8::Value> val = obj->Get(env.local(), 1).ToLocalChecked();
15892 CHECK(val->IsNumber());
15893 CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
15894 }
15895
15896 {
15897 // Special cases for arrays.
15898 v8::TryCatch try_catch(isolate);
15899 CHECK(!arr->DefineOwnProperty(env.local(), v8_str("length"),
15900 v8::Integer::New(isolate, 1)).FromJust());
15901 CHECK(!try_catch.HasCaught());
15902 }
15903 {
15904 // Special cases for arrays: index exceeds the array's length
15905 v8::TryCatch try_catch(isolate);
15906 CHECK(arr->DefineOwnProperty(env.local(), v8_str("1"),
15907 v8::Integer::New(isolate, 23)).FromJust());
15908 CHECK(!try_catch.HasCaught());
15909 CHECK_EQ(2U, arr->Length());
15910 v8::Local<v8::Value> val = arr->Get(env.local(), 1).ToLocalChecked();
15911 CHECK(val->IsNumber());
15912 CHECK_EQ(23.0, val->NumberValue(env.local()).FromJust());
15913
15914 // Set an existing entry.
15915 CHECK(arr->DefineOwnProperty(env.local(), v8_str("0"),
15916 v8::Integer::New(isolate, 42)).FromJust());
15917 CHECK(!try_catch.HasCaught());
15918 val = arr->Get(env.local(), 0).ToLocalChecked();
15919 CHECK(val->IsNumber());
15920 CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
15921 }
15922
15923 {
15924 // Set a non-writable property.
15925 v8::TryCatch try_catch(isolate);
15926 CHECK(obj->DefineOwnProperty(env.local(), v8_str("lala"),
15927 v8::Integer::New(isolate, 42),
15928 v8::ReadOnly).FromJust());
15929 CHECK(!try_catch.HasCaught());
15930 v8::Local<v8::Value> val =
15931 obj->Get(env.local(), v8_str("lala")).ToLocalChecked();
15932 CHECK(val->IsNumber());
15933 CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
15934 CHECK_EQ(v8::ReadOnly, obj->GetPropertyAttributes(
15935 env.local(), v8_str("lala")).FromJust());
15936 CHECK(!try_catch.HasCaught());
15937 }
15938
15939 CompileRun("Object.freeze(a);");
15940 {
15941 // Can't change non-extensible objects.
15942 v8::TryCatch try_catch(isolate);
15943 CHECK(!obj->DefineOwnProperty(env.local(), v8_str("baz"),
15944 v8::Integer::New(isolate, 42)).FromJust());
15945 CHECK(!try_catch.HasCaught());
15946 }
15947
15948 v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
15949 templ->SetAccessCheckCallback(AccessAlwaysBlocked);
15950 v8::Local<v8::Object> access_checked =
15951 templ->NewInstance(env.local()).ToLocalChecked();
15952 {
15953 v8::TryCatch try_catch(isolate);
15954 CHECK(access_checked->DefineOwnProperty(env.local(), v8_str("foo"),
15955 v8::Integer::New(isolate, 42))
15956 .IsNothing());
15957 CHECK(try_catch.HasCaught());
15958 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015959}
15960
15961
15962THREADED_TEST(GetCurrentContextWhenNotInContext) {
15963 i::Isolate* isolate = CcTest::i_isolate();
15964 CHECK(isolate != NULL);
15965 CHECK(isolate->context() == NULL);
15966 v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
15967 v8::HandleScope scope(v8_isolate);
15968 // The following should not crash, but return an empty handle.
15969 v8::Local<v8::Context> current = v8_isolate->GetCurrentContext();
15970 CHECK(current.IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +000015971}
15972
15973
Steve Blocka7e24c12009-10-30 11:49:00 +000015974// Check that a variable declaration with no explicit initialization
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015975// value does shadow an existing property in the prototype chain.
Steve Blocka7e24c12009-10-30 11:49:00 +000015976THREADED_TEST(InitGlobalVarInProtoChain) {
Steve Blocka7e24c12009-10-30 11:49:00 +000015977 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015978 v8::HandleScope scope(context->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000015979 // Introduce a variable in the prototype chain.
15980 CompileRun("__proto__.x = 42");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015981 v8::Local<v8::Value> result = CompileRun("var x = 43; x");
Steve Blocka7e24c12009-10-30 11:49:00 +000015982 CHECK(!result->IsUndefined());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015983 CHECK_EQ(43, result->Int32Value(context.local()).FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000015984}
15985
15986
15987// Regression test for issue 398.
15988// If a function is added to an object, creating a constant function
15989// field, and the result is cloned, replacing the constant function on the
15990// original should not affect the clone.
15991// See http://code.google.com/p/v8/issues/detail?id=398
15992THREADED_TEST(ReplaceConstantFunction) {
Steve Blocka7e24c12009-10-30 11:49:00 +000015993 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015994 v8::Isolate* isolate = context->GetIsolate();
15995 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015996 v8::Local<v8::Object> obj = v8::Object::New(isolate);
15997 v8::Local<v8::FunctionTemplate> func_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015998 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015999 v8::Local<v8::String> foo_string = v8_str("foo");
16000 obj->Set(context.local(), foo_string,
16001 func_templ->GetFunction(context.local()).ToLocalChecked())
16002 .FromJust();
16003 v8::Local<v8::Object> obj_clone = obj->Clone();
16004 obj_clone->Set(context.local(), foo_string, v8_str("Hello")).FromJust();
16005 CHECK(!obj->Get(context.local(), foo_string).ToLocalChecked()->IsUndefined());
Steve Blocka7e24c12009-10-30 11:49:00 +000016006}
16007
16008
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016009static void CheckElementValue(i::Isolate* isolate,
16010 int expected,
16011 i::Handle<i::Object> obj,
16012 int offset) {
16013 i::Object* element =
16014 *i::Object::GetElement(isolate, obj, offset).ToHandleChecked();
16015 CHECK_EQ(expected, i::Smi::cast(element)->value());
Steve Blocka7e24c12009-10-30 11:49:00 +000016016}
16017
16018
Steve Block3ce2e202009-11-05 08:53:23 +000016019template <class ExternalArrayClass, class ElementType>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016020static void ObjectWithExternalArrayTestHelper(Local<Context> context,
16021 v8::Local<Object> obj,
16022 int element_count,
16023 i::ExternalArrayType array_type,
16024 int64_t low, int64_t high) {
16025 i::Handle<i::JSReceiver> jsobj = v8::Utils::OpenHandle(*obj);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016026 i::Isolate* isolate = jsobj->GetIsolate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016027 obj->Set(context, v8_str("field"),
16028 v8::Int32::New(reinterpret_cast<v8::Isolate*>(isolate), 1503))
16029 .FromJust();
16030 CHECK(context->Global()->Set(context, v8_str("ext_array"), obj).FromJust());
16031 v8::Local<v8::Value> result = CompileRun("ext_array.field");
16032 CHECK_EQ(1503, result->Int32Value(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000016033 result = CompileRun("ext_array[1]");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016034 CHECK_EQ(1, result->Int32Value(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000016035
Steve Block3ce2e202009-11-05 08:53:23 +000016036 // Check assigned smis
16037 result = CompileRun("for (var i = 0; i < 8; i++) {"
16038 " ext_array[i] = i;"
16039 "}"
16040 "var sum = 0;"
16041 "for (var i = 0; i < 8; i++) {"
16042 " sum += ext_array[i];"
16043 "}"
16044 "sum;");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016045
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016046 CHECK_EQ(28, result->Int32Value(context).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016047 // Check pass through of assigned smis
16048 result = CompileRun("var sum = 0;"
16049 "for (var i = 0; i < 8; i++) {"
16050 " sum += ext_array[i] = ext_array[i] = -i;"
16051 "}"
16052 "sum;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016053 CHECK_EQ(-28, result->Int32Value(context).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016054
Steve Block3ce2e202009-11-05 08:53:23 +000016055
16056 // Check assigned smis in reverse order
16057 result = CompileRun("for (var i = 8; --i >= 0; ) {"
16058 " ext_array[i] = i;"
16059 "}"
16060 "var sum = 0;"
16061 "for (var i = 0; i < 8; i++) {"
16062 " sum += ext_array[i];"
16063 "}"
16064 "sum;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016065 CHECK_EQ(28, result->Int32Value(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000016066
16067 // Check pass through of assigned HeapNumbers
16068 result = CompileRun("var sum = 0;"
16069 "for (var i = 0; i < 16; i+=2) {"
16070 " sum += ext_array[i] = ext_array[i] = (-i * 0.5);"
16071 "}"
16072 "sum;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016073 CHECK_EQ(-28, result->Int32Value(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000016074
16075 // Check assigned HeapNumbers
16076 result = CompileRun("for (var i = 0; i < 16; i+=2) {"
16077 " ext_array[i] = (i * 0.5);"
16078 "}"
16079 "var sum = 0;"
16080 "for (var i = 0; i < 16; i+=2) {"
16081 " sum += ext_array[i];"
16082 "}"
16083 "sum;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016084 CHECK_EQ(28, result->Int32Value(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000016085
16086 // Check assigned HeapNumbers in reverse order
16087 result = CompileRun("for (var i = 14; i >= 0; i-=2) {"
16088 " ext_array[i] = (i * 0.5);"
16089 "}"
16090 "var sum = 0;"
16091 "for (var i = 0; i < 16; i+=2) {"
16092 " sum += ext_array[i];"
16093 "}"
16094 "sum;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016095 CHECK_EQ(28, result->Int32Value(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000016096
16097 i::ScopedVector<char> test_buf(1024);
16098
16099 // Check legal boundary conditions.
16100 // The repeated loads and stores ensure the ICs are exercised.
16101 const char* boundary_program =
16102 "var res = 0;"
16103 "for (var i = 0; i < 16; i++) {"
16104 " ext_array[i] = %lld;"
16105 " if (i > 8) {"
16106 " res = ext_array[i];"
16107 " }"
16108 "}"
16109 "res;";
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016110 i::SNPrintF(test_buf,
16111 boundary_program,
16112 low);
Steve Block3ce2e202009-11-05 08:53:23 +000016113 result = CompileRun(test_buf.start());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016114 CHECK_EQ(low, result->IntegerValue(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000016115
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016116 i::SNPrintF(test_buf,
16117 boundary_program,
16118 high);
Steve Block3ce2e202009-11-05 08:53:23 +000016119 result = CompileRun(test_buf.start());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016120 CHECK_EQ(high, result->IntegerValue(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000016121
16122 // Check misprediction of type in IC.
16123 result = CompileRun("var tmp_array = ext_array;"
16124 "var sum = 0;"
16125 "for (var i = 0; i < 8; i++) {"
16126 " tmp_array[i] = i;"
16127 " sum += tmp_array[i];"
16128 " if (i == 4) {"
16129 " tmp_array = {};"
16130 " }"
16131 "}"
16132 "sum;");
Ben Murdoch3ef787d2012-04-12 10:51:47 +010016133 // Force GC to trigger verification.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016134 CcTest::heap()->CollectAllGarbage();
16135 CHECK_EQ(28, result->Int32Value(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000016136
16137 // Make sure out-of-range loads do not throw.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016138 i::SNPrintF(test_buf,
16139 "var caught_exception = false;"
16140 "try {"
16141 " ext_array[%d];"
16142 "} catch (e) {"
16143 " caught_exception = true;"
16144 "}"
16145 "caught_exception;",
16146 element_count);
Steve Block3ce2e202009-11-05 08:53:23 +000016147 result = CompileRun(test_buf.start());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016148 CHECK_EQ(false, result->BooleanValue(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000016149
16150 // Make sure out-of-range stores do not throw.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016151 i::SNPrintF(test_buf,
16152 "var caught_exception = false;"
16153 "try {"
16154 " ext_array[%d] = 1;"
16155 "} catch (e) {"
16156 " caught_exception = true;"
16157 "}"
16158 "caught_exception;",
16159 element_count);
Steve Block3ce2e202009-11-05 08:53:23 +000016160 result = CompileRun(test_buf.start());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016161 CHECK_EQ(false, result->BooleanValue(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000016162
16163 // Check other boundary conditions, values and operations.
16164 result = CompileRun("for (var i = 0; i < 8; i++) {"
16165 " ext_array[7] = undefined;"
16166 "}"
16167 "ext_array[7];");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016168 CHECK_EQ(0, result->Int32Value(context).FromJust());
16169 if (array_type == i::kExternalFloat64Array ||
16170 array_type == i::kExternalFloat32Array) {
16171 CHECK(std::isnan(
16172 i::Object::GetElement(isolate, jsobj, 7).ToHandleChecked()->Number()));
Ben Murdoch3ef787d2012-04-12 10:51:47 +010016173 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016174 CheckElementValue(isolate, 0, jsobj, 7);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010016175 }
Steve Block3ce2e202009-11-05 08:53:23 +000016176
16177 result = CompileRun("for (var i = 0; i < 8; i++) {"
16178 " ext_array[6] = '2.3';"
16179 "}"
16180 "ext_array[6];");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016181 CHECK_EQ(2, result->Int32Value(context).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016182 CHECK_EQ(2,
16183 static_cast<int>(
16184 i::Object::GetElement(
16185 isolate, jsobj, 6).ToHandleChecked()->Number()));
Steve Block3ce2e202009-11-05 08:53:23 +000016186
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016187 if (array_type != i::kExternalFloat32Array &&
16188 array_type != i::kExternalFloat64Array) {
Steve Block3ce2e202009-11-05 08:53:23 +000016189 // Though the specification doesn't state it, be explicit about
16190 // converting NaNs and +/-Infinity to zero.
16191 result = CompileRun("for (var i = 0; i < 8; i++) {"
16192 " ext_array[i] = 5;"
16193 "}"
16194 "for (var i = 0; i < 8; i++) {"
16195 " ext_array[i] = NaN;"
16196 "}"
16197 "ext_array[5];");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016198 CHECK_EQ(0, result->Int32Value(context).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016199 CheckElementValue(isolate, 0, jsobj, 5);
Steve Block3ce2e202009-11-05 08:53:23 +000016200
16201 result = CompileRun("for (var i = 0; i < 8; i++) {"
16202 " ext_array[i] = 5;"
16203 "}"
16204 "for (var i = 0; i < 8; i++) {"
16205 " ext_array[i] = Infinity;"
16206 "}"
16207 "ext_array[5];");
Steve Block44f0eee2011-05-26 01:26:41 +010016208 int expected_value =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016209 (array_type == i::kExternalUint8ClampedArray) ? 255 : 0;
16210 CHECK_EQ(expected_value, result->Int32Value(context).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016211 CheckElementValue(isolate, expected_value, jsobj, 5);
Steve Block3ce2e202009-11-05 08:53:23 +000016212
16213 result = CompileRun("for (var i = 0; i < 8; i++) {"
16214 " ext_array[i] = 5;"
16215 "}"
16216 "for (var i = 0; i < 8; i++) {"
16217 " ext_array[i] = -Infinity;"
16218 "}"
16219 "ext_array[5];");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016220 CHECK_EQ(0, result->Int32Value(context).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016221 CheckElementValue(isolate, 0, jsobj, 5);
Steve Block1e0659c2011-05-24 12:43:12 +010016222
16223 // Check truncation behavior of integral arrays.
16224 const char* unsigned_data =
16225 "var source_data = [0.6, 10.6];"
16226 "var expected_results = [0, 10];";
16227 const char* signed_data =
16228 "var source_data = [0.6, 10.6, -0.6, -10.6];"
16229 "var expected_results = [0, 10, 0, -10];";
Steve Block44f0eee2011-05-26 01:26:41 +010016230 const char* pixel_data =
16231 "var source_data = [0.6, 10.6];"
16232 "var expected_results = [1, 11];";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016233 bool is_unsigned = (array_type == i::kExternalUint8Array ||
16234 array_type == i::kExternalUint16Array ||
16235 array_type == i::kExternalUint32Array);
16236 bool is_pixel_data = array_type == i::kExternalUint8ClampedArray;
Steve Block1e0659c2011-05-24 12:43:12 +010016237
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016238 i::SNPrintF(test_buf,
16239 "%s"
16240 "var all_passed = true;"
16241 "for (var i = 0; i < source_data.length; i++) {"
16242 " for (var j = 0; j < 8; j++) {"
16243 " ext_array[j] = source_data[i];"
16244 " }"
16245 " all_passed = all_passed &&"
16246 " (ext_array[5] == expected_results[i]);"
16247 "}"
16248 "all_passed;",
16249 (is_unsigned ?
16250 unsigned_data :
16251 (is_pixel_data ? pixel_data : signed_data)));
Steve Block1e0659c2011-05-24 12:43:12 +010016252 result = CompileRun(test_buf.start());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016253 CHECK_EQ(true, result->BooleanValue(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000016254 }
16255
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016256 i::Handle<ExternalArrayClass> array(ExternalArrayClass::cast(
16257 i::Handle<i::JSObject>::cast(jsobj)->elements()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016258 for (int i = 0; i < element_count; i++) {
Ben Murdoch8b112d22011-06-08 16:22:53 +010016259 array->set(i, static_cast<ElementType>(i));
16260 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016261
Ben Murdoch8b112d22011-06-08 16:22:53 +010016262 // Test complex assignments
16263 result = CompileRun("function ee_op_test_complex_func(sum) {"
16264 " for (var i = 0; i < 40; ++i) {"
16265 " sum += (ext_array[i] += 1);"
16266 " sum += (ext_array[i] -= 1);"
16267 " } "
16268 " return sum;"
16269 "}"
16270 "sum=0;"
16271 "for (var i=0;i<10000;++i) {"
16272 " sum=ee_op_test_complex_func(sum);"
16273 "}"
16274 "sum;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016275 CHECK_EQ(16000000, result->Int32Value(context).FromJust());
Ben Murdoch8b112d22011-06-08 16:22:53 +010016276
16277 // Test count operations
16278 result = CompileRun("function ee_op_test_count_func(sum) {"
16279 " for (var i = 0; i < 40; ++i) {"
16280 " sum += (++ext_array[i]);"
16281 " sum += (--ext_array[i]);"
16282 " } "
16283 " return sum;"
16284 "}"
16285 "sum=0;"
16286 "for (var i=0;i<10000;++i) {"
16287 " sum=ee_op_test_count_func(sum);"
16288 "}"
16289 "sum;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016290 CHECK_EQ(16000000, result->Int32Value(context).FromJust());
Ben Murdoch8b112d22011-06-08 16:22:53 +010016291
Steve Block3ce2e202009-11-05 08:53:23 +000016292 result = CompileRun("ext_array[3] = 33;"
16293 "delete ext_array[3];"
16294 "ext_array[3];");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016295 CHECK_EQ(33, result->Int32Value(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000016296
16297 result = CompileRun("ext_array[0] = 10; ext_array[1] = 11;"
16298 "ext_array[2] = 12; ext_array[3] = 13;"
16299 "ext_array.__defineGetter__('2',"
16300 "function() { return 120; });"
16301 "ext_array[2];");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016302 CHECK_EQ(12, result->Int32Value(context).FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000016303
16304 result = CompileRun("var js_array = new Array(40);"
16305 "js_array[0] = 77;"
16306 "js_array;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016307 CHECK_EQ(77, v8::Object::Cast(*result)
16308 ->Get(context, v8_str("0"))
16309 .ToLocalChecked()
16310 ->Int32Value(context)
16311 .FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000016312
16313 result = CompileRun("ext_array[1] = 23;"
16314 "ext_array.__proto__ = [];"
16315 "js_array.__proto__ = ext_array;"
16316 "js_array.concat(ext_array);");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016317 CHECK_EQ(77, v8::Object::Cast(*result)
16318 ->Get(context, v8_str("0"))
16319 .ToLocalChecked()
16320 ->Int32Value(context)
16321 .FromJust());
16322 CHECK_EQ(23, v8::Object::Cast(*result)
16323 ->Get(context, v8_str("1"))
16324 .ToLocalChecked()
16325 ->Int32Value(context)
16326 .FromJust());
Steve Block3ce2e202009-11-05 08:53:23 +000016327
16328 result = CompileRun("ext_array[1] = 23;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016329 CHECK_EQ(23, result->Int32Value(context).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016330}
16331
16332
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016333template <class FixedTypedArrayClass, i::ElementsKind elements_kind,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016334 class ElementType>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016335static void FixedTypedArrayTestHelper(i::ExternalArrayType array_type,
16336 ElementType low, ElementType high) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016337 i::FLAG_allow_natives_syntax = true;
16338 LocalContext context;
16339 i::Isolate* isolate = CcTest::i_isolate();
16340 i::Factory* factory = isolate->factory();
16341 v8::HandleScope scope(context->GetIsolate());
16342 const int kElementCount = 260;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016343 i::Handle<i::JSTypedArray> jsobj =
16344 factory->NewJSTypedArray(elements_kind, kElementCount);
16345 i::Handle<FixedTypedArrayClass> fixed_array(
16346 FixedTypedArrayClass::cast(jsobj->elements()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016347 CHECK_EQ(FixedTypedArrayClass::kInstanceType,
16348 fixed_array->map()->instance_type());
16349 CHECK_EQ(kElementCount, fixed_array->length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016350 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016351 for (int i = 0; i < kElementCount; i++) {
16352 fixed_array->set(i, static_cast<ElementType>(i));
16353 }
16354 // Force GC to trigger verification.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016355 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016356 for (int i = 0; i < kElementCount; i++) {
16357 CHECK_EQ(static_cast<int64_t>(static_cast<ElementType>(i)),
16358 static_cast<int64_t>(fixed_array->get_scalar(i)));
16359 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016360 v8::Local<v8::Object> obj = v8::Utils::ToLocal(jsobj);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016361
16362 ObjectWithExternalArrayTestHelper<FixedTypedArrayClass, ElementType>(
16363 context.local(), obj, kElementCount, array_type,
16364 static_cast<int64_t>(low),
16365 static_cast<int64_t>(high));
16366}
16367
16368
16369THREADED_TEST(FixedUint8Array) {
16370 FixedTypedArrayTestHelper<i::FixedUint8Array, i::UINT8_ELEMENTS, uint8_t>(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016371 i::kExternalUint8Array, 0x0, 0xFF);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016372}
16373
16374
16375THREADED_TEST(FixedUint8ClampedArray) {
16376 FixedTypedArrayTestHelper<i::FixedUint8ClampedArray,
16377 i::UINT8_CLAMPED_ELEMENTS, uint8_t>(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016378 i::kExternalUint8ClampedArray, 0x0, 0xFF);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016379}
16380
16381
16382THREADED_TEST(FixedInt8Array) {
16383 FixedTypedArrayTestHelper<i::FixedInt8Array, i::INT8_ELEMENTS, int8_t>(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016384 i::kExternalInt8Array, -0x80, 0x7F);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016385}
16386
16387
16388THREADED_TEST(FixedUint16Array) {
16389 FixedTypedArrayTestHelper<i::FixedUint16Array, i::UINT16_ELEMENTS, uint16_t>(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016390 i::kExternalUint16Array, 0x0, 0xFFFF);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016391}
16392
16393
16394THREADED_TEST(FixedInt16Array) {
16395 FixedTypedArrayTestHelper<i::FixedInt16Array, i::INT16_ELEMENTS, int16_t>(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016396 i::kExternalInt16Array, -0x8000, 0x7FFF);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016397}
16398
16399
16400THREADED_TEST(FixedUint32Array) {
16401 FixedTypedArrayTestHelper<i::FixedUint32Array, i::UINT32_ELEMENTS, uint32_t>(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016402 i::kExternalUint32Array, 0x0, UINT_MAX);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016403}
16404
16405
16406THREADED_TEST(FixedInt32Array) {
16407 FixedTypedArrayTestHelper<i::FixedInt32Array, i::INT32_ELEMENTS, int32_t>(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016408 i::kExternalInt32Array, INT_MIN, INT_MAX);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016409}
16410
16411
16412THREADED_TEST(FixedFloat32Array) {
16413 FixedTypedArrayTestHelper<i::FixedFloat32Array, i::FLOAT32_ELEMENTS, float>(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016414 i::kExternalFloat32Array, -500, 500);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016415}
16416
16417
16418THREADED_TEST(FixedFloat64Array) {
16419 FixedTypedArrayTestHelper<i::FixedFloat64Array, i::FLOAT64_ELEMENTS, float>(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016420 i::kExternalFloat64Array, -500, 500);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016421}
16422
16423
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016424template <typename ElementType, typename TypedArray, class ExternalArrayClass,
16425 class ArrayBufferType>
16426void TypedArrayTestHelper(i::ExternalArrayType array_type, int64_t low,
16427 int64_t high) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016428 const int kElementCount = 50;
16429
16430 i::ScopedVector<ElementType> backing_store(kElementCount+2);
16431
16432 LocalContext env;
16433 v8::Isolate* isolate = env->GetIsolate();
16434 v8::HandleScope handle_scope(isolate);
16435
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016436 Local<ArrayBufferType> ab =
16437 ArrayBufferType::New(isolate, backing_store.start(),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016438 (kElementCount + 2) * sizeof(ElementType));
16439 Local<TypedArray> ta =
16440 TypedArray::New(ab, 2*sizeof(ElementType), kElementCount);
16441 CheckInternalFieldsAreZero<v8::ArrayBufferView>(ta);
16442 CHECK_EQ(kElementCount, static_cast<int>(ta->Length()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016443 CHECK_EQ(2 * sizeof(ElementType), ta->ByteOffset());
16444 CHECK_EQ(kElementCount * sizeof(ElementType), ta->ByteLength());
16445 CHECK(ab->Equals(env.local(), ta->Buffer()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016446
16447 ElementType* data = backing_store.start() + 2;
16448 for (int i = 0; i < kElementCount; i++) {
16449 data[i] = static_cast<ElementType>(i);
16450 }
16451
16452 ObjectWithExternalArrayTestHelper<ExternalArrayClass, ElementType>(
16453 env.local(), ta, kElementCount, array_type, low, high);
16454}
16455
16456
16457THREADED_TEST(Uint8Array) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016458 TypedArrayTestHelper<uint8_t, v8::Uint8Array, i::FixedUint8Array,
16459 v8::ArrayBuffer>(i::kExternalUint8Array, 0, 0xFF);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016460}
16461
16462
16463THREADED_TEST(Int8Array) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016464 TypedArrayTestHelper<int8_t, v8::Int8Array, i::FixedInt8Array,
16465 v8::ArrayBuffer>(i::kExternalInt8Array, -0x80, 0x7F);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016466}
16467
16468
16469THREADED_TEST(Uint16Array) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016470 TypedArrayTestHelper<uint16_t, v8::Uint16Array, i::FixedUint16Array,
16471 v8::ArrayBuffer>(i::kExternalUint16Array, 0, 0xFFFF);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016472}
16473
16474
16475THREADED_TEST(Int16Array) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016476 TypedArrayTestHelper<int16_t, v8::Int16Array, i::FixedInt16Array,
16477 v8::ArrayBuffer>(i::kExternalInt16Array, -0x8000,
16478 0x7FFF);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016479}
16480
16481
16482THREADED_TEST(Uint32Array) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016483 TypedArrayTestHelper<uint32_t, v8::Uint32Array, i::FixedUint32Array,
16484 v8::ArrayBuffer>(i::kExternalUint32Array, 0, UINT_MAX);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016485}
16486
16487
16488THREADED_TEST(Int32Array) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016489 TypedArrayTestHelper<int32_t, v8::Int32Array, i::FixedInt32Array,
16490 v8::ArrayBuffer>(i::kExternalInt32Array, INT_MIN,
16491 INT_MAX);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016492}
16493
16494
16495THREADED_TEST(Float32Array) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016496 TypedArrayTestHelper<float, v8::Float32Array, i::FixedFloat32Array,
16497 v8::ArrayBuffer>(i::kExternalFloat32Array, -500, 500);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016498}
16499
16500
16501THREADED_TEST(Float64Array) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016502 TypedArrayTestHelper<double, v8::Float64Array, i::FixedFloat64Array,
16503 v8::ArrayBuffer>(i::kExternalFloat64Array, -500, 500);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016504}
16505
16506
16507THREADED_TEST(Uint8ClampedArray) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016508 TypedArrayTestHelper<uint8_t, v8::Uint8ClampedArray,
16509 i::FixedUint8ClampedArray, v8::ArrayBuffer>(
16510 i::kExternalUint8ClampedArray, 0, 0xFF);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016511}
16512
16513
16514THREADED_TEST(DataView) {
16515 const int kSize = 50;
16516
16517 i::ScopedVector<uint8_t> backing_store(kSize+2);
16518
16519 LocalContext env;
16520 v8::Isolate* isolate = env->GetIsolate();
16521 v8::HandleScope handle_scope(isolate);
16522
16523 Local<v8::ArrayBuffer> ab =
16524 v8::ArrayBuffer::New(isolate, backing_store.start(), 2 + kSize);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016525 Local<v8::DataView> dv = v8::DataView::New(ab, 2, kSize);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016526 CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016527 CHECK_EQ(2u, dv->ByteOffset());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016528 CHECK_EQ(kSize, static_cast<int>(dv->ByteLength()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016529 CHECK(ab->Equals(env.local(), dv->Buffer()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016530}
16531
16532
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016533THREADED_TEST(SkipArrayBufferBackingStoreDuringGC) {
16534 LocalContext env;
16535 v8::Isolate* isolate = env->GetIsolate();
16536 v8::HandleScope handle_scope(isolate);
16537
16538 // Make sure the pointer looks like a heap object
16539 uint8_t* store_ptr = reinterpret_cast<uint8_t*>(i::kHeapObjectTag);
16540
16541 // Create ArrayBuffer with pointer-that-cannot-be-visited in the backing store
16542 Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, store_ptr, 8);
16543
16544 // Should not crash
16545 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
16546 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
16547 CcTest::heap()->CollectAllGarbage();
16548 CcTest::heap()->CollectAllGarbage();
16549
16550 // Should not move the pointer
16551 CHECK_EQ(ab->GetContents().Data(), store_ptr);
16552}
16553
16554
16555THREADED_TEST(SkipArrayBufferDuringScavenge) {
16556 LocalContext env;
16557 v8::Isolate* isolate = env->GetIsolate();
16558 v8::HandleScope handle_scope(isolate);
16559
16560 // Make sure the pointer looks like a heap object
16561 Local<v8::Object> tmp = v8::Object::New(isolate);
16562 uint8_t* store_ptr =
16563 reinterpret_cast<uint8_t*>(*reinterpret_cast<uintptr_t*>(*tmp));
16564
16565 // Make `store_ptr` point to from space
16566 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
16567
16568 // Create ArrayBuffer with pointer-that-cannot-be-visited in the backing store
16569 Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, store_ptr, 8);
16570
16571 // Should not crash,
16572 // i.e. backing store pointer should not be treated as a heap object pointer
16573 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
16574 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
16575
16576 // Use `ab` to silence compiler warning
16577 CHECK_EQ(ab->GetContents().Data(), store_ptr);
16578}
16579
16580
16581THREADED_TEST(SharedUint8Array) {
16582 i::FLAG_harmony_sharedarraybuffer = true;
16583 TypedArrayTestHelper<uint8_t, v8::Uint8Array, i::FixedUint8Array,
16584 v8::SharedArrayBuffer>(i::kExternalUint8Array, 0, 0xFF);
16585}
16586
16587
16588THREADED_TEST(SharedInt8Array) {
16589 i::FLAG_harmony_sharedarraybuffer = true;
16590 TypedArrayTestHelper<int8_t, v8::Int8Array, i::FixedInt8Array,
16591 v8::SharedArrayBuffer>(i::kExternalInt8Array, -0x80,
16592 0x7F);
16593}
16594
16595
16596THREADED_TEST(SharedUint16Array) {
16597 i::FLAG_harmony_sharedarraybuffer = true;
16598 TypedArrayTestHelper<uint16_t, v8::Uint16Array, i::FixedUint16Array,
16599 v8::SharedArrayBuffer>(i::kExternalUint16Array, 0,
16600 0xFFFF);
16601}
16602
16603
16604THREADED_TEST(SharedInt16Array) {
16605 i::FLAG_harmony_sharedarraybuffer = true;
16606 TypedArrayTestHelper<int16_t, v8::Int16Array, i::FixedInt16Array,
16607 v8::SharedArrayBuffer>(i::kExternalInt16Array, -0x8000,
16608 0x7FFF);
16609}
16610
16611
16612THREADED_TEST(SharedUint32Array) {
16613 i::FLAG_harmony_sharedarraybuffer = true;
16614 TypedArrayTestHelper<uint32_t, v8::Uint32Array, i::FixedUint32Array,
16615 v8::SharedArrayBuffer>(i::kExternalUint32Array, 0,
16616 UINT_MAX);
16617}
16618
16619
16620THREADED_TEST(SharedInt32Array) {
16621 i::FLAG_harmony_sharedarraybuffer = true;
16622 TypedArrayTestHelper<int32_t, v8::Int32Array, i::FixedInt32Array,
16623 v8::SharedArrayBuffer>(i::kExternalInt32Array, INT_MIN,
16624 INT_MAX);
16625}
16626
16627
16628THREADED_TEST(SharedFloat32Array) {
16629 i::FLAG_harmony_sharedarraybuffer = true;
16630 TypedArrayTestHelper<float, v8::Float32Array, i::FixedFloat32Array,
16631 v8::SharedArrayBuffer>(i::kExternalFloat32Array, -500,
16632 500);
16633}
16634
16635
16636THREADED_TEST(SharedFloat64Array) {
16637 i::FLAG_harmony_sharedarraybuffer = true;
16638 TypedArrayTestHelper<double, v8::Float64Array, i::FixedFloat64Array,
16639 v8::SharedArrayBuffer>(i::kExternalFloat64Array, -500,
16640 500);
16641}
16642
16643
16644THREADED_TEST(SharedUint8ClampedArray) {
16645 i::FLAG_harmony_sharedarraybuffer = true;
16646 TypedArrayTestHelper<uint8_t, v8::Uint8ClampedArray,
16647 i::FixedUint8ClampedArray, v8::SharedArrayBuffer>(
16648 i::kExternalUint8ClampedArray, 0, 0xFF);
16649}
16650
16651
16652THREADED_TEST(SharedDataView) {
16653 i::FLAG_harmony_sharedarraybuffer = true;
16654 const int kSize = 50;
16655
16656 i::ScopedVector<uint8_t> backing_store(kSize + 2);
16657
16658 LocalContext env;
16659 v8::Isolate* isolate = env->GetIsolate();
16660 v8::HandleScope handle_scope(isolate);
16661
16662 Local<v8::SharedArrayBuffer> ab =
16663 v8::SharedArrayBuffer::New(isolate, backing_store.start(), 2 + kSize);
16664 Local<v8::DataView> dv =
16665 v8::DataView::New(ab, 2, kSize);
16666 CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
16667 CHECK_EQ(2u, dv->ByteOffset());
16668 CHECK_EQ(kSize, static_cast<int>(dv->ByteLength()));
16669 CHECK(ab->Equals(env.local(), dv->Buffer()).FromJust());
16670}
16671
16672
16673#define IS_ARRAY_BUFFER_VIEW_TEST(View) \
16674 THREADED_TEST(Is##View) { \
16675 LocalContext env; \
16676 v8::Isolate* isolate = env->GetIsolate(); \
16677 v8::HandleScope handle_scope(isolate); \
16678 \
16679 Local<Value> result = CompileRun( \
16680 "var ab = new ArrayBuffer(128);" \
16681 "new " #View "(ab)"); \
16682 CHECK(result->IsArrayBufferView()); \
16683 CHECK(result->Is##View()); \
16684 CheckInternalFieldsAreZero<v8::ArrayBufferView>(result.As<v8::View>()); \
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016685 }
16686
16687IS_ARRAY_BUFFER_VIEW_TEST(Uint8Array)
16688IS_ARRAY_BUFFER_VIEW_TEST(Int8Array)
16689IS_ARRAY_BUFFER_VIEW_TEST(Uint16Array)
16690IS_ARRAY_BUFFER_VIEW_TEST(Int16Array)
16691IS_ARRAY_BUFFER_VIEW_TEST(Uint32Array)
16692IS_ARRAY_BUFFER_VIEW_TEST(Int32Array)
16693IS_ARRAY_BUFFER_VIEW_TEST(Float32Array)
16694IS_ARRAY_BUFFER_VIEW_TEST(Float64Array)
16695IS_ARRAY_BUFFER_VIEW_TEST(Uint8ClampedArray)
16696IS_ARRAY_BUFFER_VIEW_TEST(DataView)
16697
16698#undef IS_ARRAY_BUFFER_VIEW_TEST
16699
16700
16701
Steve Blocka7e24c12009-10-30 11:49:00 +000016702THREADED_TEST(ScriptContextDependence) {
Steve Blocka7e24c12009-10-30 11:49:00 +000016703 LocalContext c1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016704 v8::HandleScope scope(c1->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000016705 const char *source = "foo";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016706 v8::Local<v8::Script> dep = v8_compile(source);
16707 v8::ScriptCompiler::Source script_source(
16708 v8::String::NewFromUtf8(c1->GetIsolate(), source,
16709 v8::NewStringType::kNormal)
16710 .ToLocalChecked());
16711 v8::Local<v8::UnboundScript> indep =
16712 v8::ScriptCompiler::CompileUnboundScript(c1->GetIsolate(), &script_source)
16713 .ToLocalChecked();
16714 c1->Global()
16715 ->Set(c1.local(), v8::String::NewFromUtf8(c1->GetIsolate(), "foo",
16716 v8::NewStringType::kNormal)
16717 .ToLocalChecked(),
16718 v8::Integer::New(c1->GetIsolate(), 100))
16719 .FromJust();
16720 CHECK_EQ(
16721 dep->Run(c1.local()).ToLocalChecked()->Int32Value(c1.local()).FromJust(),
16722 100);
16723 CHECK_EQ(indep->BindToCurrentContext()
16724 ->Run(c1.local())
16725 .ToLocalChecked()
16726 ->Int32Value(c1.local())
16727 .FromJust(),
16728 100);
Steve Blocka7e24c12009-10-30 11:49:00 +000016729 LocalContext c2;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016730 c2->Global()
16731 ->Set(c2.local(), v8::String::NewFromUtf8(c2->GetIsolate(), "foo",
16732 v8::NewStringType::kNormal)
16733 .ToLocalChecked(),
16734 v8::Integer::New(c2->GetIsolate(), 101))
16735 .FromJust();
16736 CHECK_EQ(
16737 dep->Run(c2.local()).ToLocalChecked()->Int32Value(c2.local()).FromJust(),
16738 100);
16739 CHECK_EQ(indep->BindToCurrentContext()
16740 ->Run(c2.local())
16741 .ToLocalChecked()
16742 ->Int32Value(c2.local())
16743 .FromJust(),
16744 101);
Steve Blocka7e24c12009-10-30 11:49:00 +000016745}
16746
16747
16748THREADED_TEST(StackTrace) {
Steve Blocka7e24c12009-10-30 11:49:00 +000016749 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016750 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016751 v8::TryCatch try_catch(context->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000016752 const char *source = "function foo() { FAIL.FAIL; }; foo();";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016753 v8::Local<v8::String> src = v8_str(source);
16754 v8::Local<v8::String> origin = v8_str("stack-trace-test");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016755 v8::ScriptCompiler::Source script_source(src, v8::ScriptOrigin(origin));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016756 CHECK(v8::ScriptCompiler::CompileUnboundScript(context->GetIsolate(),
16757 &script_source)
16758 .ToLocalChecked()
16759 ->BindToCurrentContext()
16760 ->Run(context.local())
16761 .IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +000016762 CHECK(try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016763 v8::String::Utf8Value stack(
16764 try_catch.StackTrace(context.local()).ToLocalChecked());
Steve Blocka7e24c12009-10-30 11:49:00 +000016765 CHECK(strstr(*stack, "at foo (stack-trace-test") != NULL);
16766}
16767
16768
Kristian Monsen25f61362010-05-21 11:50:48 +010016769// Checks that a StackFrame has certain expected values.
16770void checkStackFrame(const char* expected_script_name,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016771 const char* expected_func_name, int expected_line_number,
16772 int expected_column, bool is_eval, bool is_constructor,
16773 v8::Local<v8::StackFrame> frame) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016774 v8::HandleScope scope(CcTest::isolate());
Kristian Monsen25f61362010-05-21 11:50:48 +010016775 v8::String::Utf8Value func_name(frame->GetFunctionName());
16776 v8::String::Utf8Value script_name(frame->GetScriptName());
16777 if (*script_name == NULL) {
16778 // The situation where there is no associated script, like for evals.
16779 CHECK(expected_script_name == NULL);
16780 } else {
16781 CHECK(strstr(*script_name, expected_script_name) != NULL);
16782 }
16783 CHECK(strstr(*func_name, expected_func_name) != NULL);
16784 CHECK_EQ(expected_line_number, frame->GetLineNumber());
16785 CHECK_EQ(expected_column, frame->GetColumn());
16786 CHECK_EQ(is_eval, frame->IsEval());
16787 CHECK_EQ(is_constructor, frame->IsConstructor());
16788}
16789
16790
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016791void AnalyzeStackInNativeCode(const v8::FunctionCallbackInfo<v8::Value>& args) {
16792 v8::HandleScope scope(args.GetIsolate());
Kristian Monsen25f61362010-05-21 11:50:48 +010016793 const char* origin = "capture-stack-trace-test";
16794 const int kOverviewTest = 1;
16795 const int kDetailedTest = 2;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016796 const int kFunctionName = 3;
16797 const int kDisplayName = 4;
16798 const int kFunctionNameAndDisplayName = 5;
16799 const int kDisplayNameIsNotString = 6;
16800 const int kFunctionNameIsNotString = 7;
Kristian Monsen25f61362010-05-21 11:50:48 +010016801
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016802 CHECK(args.Length() == 1);
Kristian Monsen25f61362010-05-21 11:50:48 +010016803
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016804 v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
16805 int testGroup = args[0]->Int32Value(context).FromJust();
Kristian Monsen25f61362010-05-21 11:50:48 +010016806 if (testGroup == kOverviewTest) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016807 v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016808 args.GetIsolate(), 10, v8::StackTrace::kOverview);
Kristian Monsen25f61362010-05-21 11:50:48 +010016809 CHECK_EQ(4, stackTrace->GetFrameCount());
16810 checkStackFrame(origin, "bar", 2, 10, false, false,
16811 stackTrace->GetFrame(0));
16812 checkStackFrame(origin, "foo", 6, 3, false, false,
16813 stackTrace->GetFrame(1));
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000016814 // This is the source string inside the eval which has the call to foo.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016815 checkStackFrame(NULL, "", 1, 1, false, false, stackTrace->GetFrame(2));
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000016816 // The last frame is an anonymous function which has the initial eval call.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016817 checkStackFrame(origin, "", 8, 7, false, false, stackTrace->GetFrame(3));
Kristian Monsen25f61362010-05-21 11:50:48 +010016818
16819 CHECK(stackTrace->AsArray()->IsArray());
16820 } else if (testGroup == kDetailedTest) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016821 v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016822 args.GetIsolate(), 10, v8::StackTrace::kDetailed);
Kristian Monsen25f61362010-05-21 11:50:48 +010016823 CHECK_EQ(4, stackTrace->GetFrameCount());
16824 checkStackFrame(origin, "bat", 4, 22, false, false,
16825 stackTrace->GetFrame(0));
16826 checkStackFrame(origin, "baz", 8, 3, false, true,
16827 stackTrace->GetFrame(1));
Kristian Monsen9dcf7e22010-06-28 14:14:28 +010016828 bool is_eval = true;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000016829 // This is the source string inside the eval which has the call to baz.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016830 checkStackFrame(NULL, "", 1, 1, is_eval, false, stackTrace->GetFrame(2));
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000016831 // The last frame is an anonymous function which has the initial eval call.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016832 checkStackFrame(origin, "", 10, 1, false, false, stackTrace->GetFrame(3));
Kristian Monsen25f61362010-05-21 11:50:48 +010016833
16834 CHECK(stackTrace->AsArray()->IsArray());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016835 } else if (testGroup == kFunctionName) {
16836 v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
16837 args.GetIsolate(), 5, v8::StackTrace::kOverview);
16838 CHECK_EQ(3, stackTrace->GetFrameCount());
16839 checkStackFrame(origin, "function.name", 2, 24, false, false,
16840 stackTrace->GetFrame(0));
16841 } else if (testGroup == kDisplayName) {
16842 v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
16843 args.GetIsolate(), 5, v8::StackTrace::kOverview);
16844 CHECK_EQ(3, stackTrace->GetFrameCount());
16845 checkStackFrame(origin, "function.displayName", 2, 24, false, false,
16846 stackTrace->GetFrame(0));
16847 } else if (testGroup == kFunctionNameAndDisplayName) {
16848 v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
16849 args.GetIsolate(), 5, v8::StackTrace::kOverview);
16850 CHECK_EQ(3, stackTrace->GetFrameCount());
16851 checkStackFrame(origin, "function.displayName", 2, 24, false, false,
16852 stackTrace->GetFrame(0));
16853 } else if (testGroup == kDisplayNameIsNotString) {
16854 v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
16855 args.GetIsolate(), 5, v8::StackTrace::kOverview);
16856 CHECK_EQ(3, stackTrace->GetFrameCount());
16857 checkStackFrame(origin, "function.name", 2, 24, false, false,
16858 stackTrace->GetFrame(0));
16859 } else if (testGroup == kFunctionNameIsNotString) {
16860 v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
16861 args.GetIsolate(), 5, v8::StackTrace::kOverview);
16862 CHECK_EQ(3, stackTrace->GetFrameCount());
16863 checkStackFrame(origin, "f", 2, 24, false, false, stackTrace->GetFrame(0));
Kristian Monsen25f61362010-05-21 11:50:48 +010016864 }
Kristian Monsen25f61362010-05-21 11:50:48 +010016865}
16866
16867
16868// Tests the C++ StackTrace API.
Ben Murdochb0fe1622011-05-05 13:52:32 +010016869// TODO(3074796): Reenable this as a THREADED_TEST once it passes.
16870// THREADED_TEST(CaptureStackTrace) {
16871TEST(CaptureStackTrace) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016872 v8::Isolate* isolate = CcTest::isolate();
16873 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016874 v8::Local<v8::String> origin = v8_str("capture-stack-trace-test");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016875 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Kristian Monsen25f61362010-05-21 11:50:48 +010016876 templ->Set(v8_str("AnalyzeStackInNativeCode"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016877 v8::FunctionTemplate::New(isolate, AnalyzeStackInNativeCode));
Kristian Monsen25f61362010-05-21 11:50:48 +010016878 LocalContext context(0, templ);
16879
16880 // Test getting OVERVIEW information. Should ignore information that is not
16881 // script name, function name, line number, and column offset.
16882 const char *overview_source =
16883 "function bar() {\n"
16884 " var y; AnalyzeStackInNativeCode(1);\n"
16885 "}\n"
16886 "function foo() {\n"
16887 "\n"
16888 " bar();\n"
16889 "}\n"
16890 "var x;eval('new foo();');";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016891 v8::Local<v8::String> overview_src = v8_str(overview_source);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016892 v8::ScriptCompiler::Source script_source(overview_src,
16893 v8::ScriptOrigin(origin));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016894 v8::Local<Value> overview_result(
16895 v8::ScriptCompiler::CompileUnboundScript(isolate, &script_source)
16896 .ToLocalChecked()
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016897 ->BindToCurrentContext()
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016898 ->Run(context.local())
16899 .ToLocalChecked());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010016900 CHECK(!overview_result.IsEmpty());
16901 CHECK(overview_result->IsObject());
Kristian Monsen25f61362010-05-21 11:50:48 +010016902
16903 // Test getting DETAILED information.
16904 const char *detailed_source =
16905 "function bat() {AnalyzeStackInNativeCode(2);\n"
16906 "}\n"
16907 "\n"
16908 "function baz() {\n"
16909 " bat();\n"
16910 "}\n"
16911 "eval('new baz();');";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016912 v8::Local<v8::String> detailed_src = v8_str(detailed_source);
Kristian Monsen25f61362010-05-21 11:50:48 +010016913 // Make the script using a non-zero line and column offset.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016914 v8::Local<v8::Integer> line_offset = v8::Integer::New(isolate, 3);
16915 v8::Local<v8::Integer> column_offset = v8::Integer::New(isolate, 5);
Kristian Monsen25f61362010-05-21 11:50:48 +010016916 v8::ScriptOrigin detailed_origin(origin, line_offset, column_offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016917 v8::ScriptCompiler::Source script_source2(detailed_src, detailed_origin);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016918 v8::Local<v8::UnboundScript> detailed_script(
16919 v8::ScriptCompiler::CompileUnboundScript(isolate, &script_source2)
16920 .ToLocalChecked());
16921 v8::Local<Value> detailed_result(detailed_script->BindToCurrentContext()
16922 ->Run(context.local())
16923 .ToLocalChecked());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010016924 CHECK(!detailed_result.IsEmpty());
16925 CHECK(detailed_result->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016926
16927 // Test using function.name and function.displayName in stack trace
16928 const char* function_name_source =
16929 "function bar(function_name, display_name, testGroup) {\n"
16930 " var f = function() { AnalyzeStackInNativeCode(testGroup); };\n"
16931 " if (function_name) {\n"
16932 " Object.defineProperty(f, 'name', { value: function_name });\n"
16933 " }\n"
16934 " if (display_name) {\n"
16935 " f.displayName = display_name;"
16936 " }\n"
16937 " f()\n"
16938 "}\n"
16939 "bar('function.name', undefined, 3);\n"
16940 "bar(undefined, 'function.displayName', 4);\n"
16941 "bar('function.name', 'function.displayName', 5);\n"
16942 "bar('function.name', 239, 6);\n"
16943 "bar(239, undefined, 7);\n";
16944 v8::Local<v8::String> function_name_src =
16945 v8::String::NewFromUtf8(isolate, function_name_source,
16946 v8::NewStringType::kNormal)
16947 .ToLocalChecked();
16948 v8::ScriptCompiler::Source script_source3(function_name_src,
16949 v8::ScriptOrigin(origin));
16950 v8::Local<Value> function_name_result(
16951 v8::ScriptCompiler::CompileUnboundScript(isolate, &script_source3)
16952 .ToLocalChecked()
16953 ->BindToCurrentContext()
16954 ->Run(context.local())
16955 .ToLocalChecked());
16956 CHECK(!function_name_result.IsEmpty());
Kristian Monsen25f61362010-05-21 11:50:48 +010016957}
16958
16959
Ben Murdoch3bec4d22010-07-22 14:51:16 +010016960static void StackTraceForUncaughtExceptionListener(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016961 v8::Local<v8::Message> message, v8::Local<Value>) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040016962 report_count++;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016963 v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
Ben Murdoch3bec4d22010-07-22 14:51:16 +010016964 CHECK_EQ(2, stack_trace->GetFrameCount());
16965 checkStackFrame("origin", "foo", 2, 3, false, false,
16966 stack_trace->GetFrame(0));
16967 checkStackFrame("origin", "bar", 5, 3, false, false,
16968 stack_trace->GetFrame(1));
16969}
16970
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016971
Ben Murdoch3bec4d22010-07-22 14:51:16 +010016972TEST(CaptureStackTraceForUncaughtException) {
16973 report_count = 0;
Ben Murdoch3bec4d22010-07-22 14:51:16 +010016974 LocalContext env;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016975 v8::Isolate* isolate = env->GetIsolate();
16976 v8::HandleScope scope(isolate);
16977 isolate->AddMessageListener(StackTraceForUncaughtExceptionListener);
16978 isolate->SetCaptureStackTraceForUncaughtExceptions(true);
Ben Murdoch3bec4d22010-07-22 14:51:16 +010016979
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016980 CompileRunWithOrigin(
16981 "function foo() {\n"
16982 " throw 1;\n"
16983 "};\n"
16984 "function bar() {\n"
16985 " foo();\n"
16986 "};",
16987 "origin");
Ben Murdoch3bec4d22010-07-22 14:51:16 +010016988 v8::Local<v8::Object> global = env->Global();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016989 Local<Value> trouble =
16990 global->Get(env.local(), v8_str("bar")).ToLocalChecked();
Ben Murdoch3bec4d22010-07-22 14:51:16 +010016991 CHECK(trouble->IsFunction());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016992 CHECK(Function::Cast(*trouble)->Call(env.local(), global, 0, NULL).IsEmpty());
16993 isolate->SetCaptureStackTraceForUncaughtExceptions(false);
16994 isolate->RemoveMessageListeners(StackTraceForUncaughtExceptionListener);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040016995 CHECK_EQ(1, report_count);
16996}
16997
16998
16999TEST(GetStackTraceForUncaughtExceptionFromSimpleStackTrace) {
17000 report_count = 0;
17001 LocalContext env;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017002 v8::Isolate* isolate = env->GetIsolate();
17003 v8::HandleScope scope(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017004
17005 // Create an Error object first.
17006 CompileRunWithOrigin(
17007 "function foo() {\n"
17008 "e=new Error('err');\n"
17009 "};\n"
17010 "function bar() {\n"
17011 " foo();\n"
17012 "};\n"
17013 "var e;",
17014 "origin");
17015 v8::Local<v8::Object> global = env->Global();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017016 Local<Value> trouble =
17017 global->Get(env.local(), v8_str("bar")).ToLocalChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017018 CHECK(trouble->IsFunction());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017019 Function::Cast(*trouble)->Call(env.local(), global, 0, NULL).ToLocalChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017020
17021 // Enable capturing detailed stack trace late, and throw the exception.
17022 // The detailed stack trace should be extracted from the simple stack.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017023 isolate->AddMessageListener(StackTraceForUncaughtExceptionListener);
17024 isolate->SetCaptureStackTraceForUncaughtExceptions(true);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017025 CompileRunWithOrigin("throw e", "origin");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017026 isolate->SetCaptureStackTraceForUncaughtExceptions(false);
17027 isolate->RemoveMessageListeners(StackTraceForUncaughtExceptionListener);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017028 CHECK_EQ(1, report_count);
Ben Murdoch3bec4d22010-07-22 14:51:16 +010017029}
17030
17031
Steve Block1e0659c2011-05-24 12:43:12 +010017032TEST(CaptureStackTraceForUncaughtExceptionAndSetters) {
Steve Block1e0659c2011-05-24 12:43:12 +010017033 LocalContext env;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017034 v8::Isolate* isolate = env->GetIsolate();
17035 v8::HandleScope scope(isolate);
17036 isolate->SetCaptureStackTraceForUncaughtExceptions(true, 1024,
17037 v8::StackTrace::kDetailed);
Steve Block1e0659c2011-05-24 12:43:12 +010017038
17039 CompileRun(
17040 "var setters = ['column', 'lineNumber', 'scriptName',\n"
17041 " 'scriptNameOrSourceURL', 'functionName', 'isEval',\n"
17042 " 'isConstructor'];\n"
17043 "for (var i = 0; i < setters.length; i++) {\n"
17044 " var prop = setters[i];\n"
17045 " Object.prototype.__defineSetter__(prop, function() { throw prop; });\n"
17046 "}\n");
17047 CompileRun("throw 'exception';");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017048 isolate->SetCaptureStackTraceForUncaughtExceptions(false);
Steve Block1e0659c2011-05-24 12:43:12 +010017049}
17050
17051
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017052static void StackTraceFunctionNameListener(v8::Local<v8::Message> message,
17053 v8::Local<Value>) {
17054 v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
17055 CHECK_EQ(5, stack_trace->GetFrameCount());
17056 checkStackFrame("origin", "foo:0", 4, 7, false, false,
17057 stack_trace->GetFrame(0));
17058 checkStackFrame("origin", "foo:1", 5, 27, false, false,
17059 stack_trace->GetFrame(1));
17060 checkStackFrame("origin", "foo", 5, 27, false, false,
17061 stack_trace->GetFrame(2));
17062 checkStackFrame("origin", "foo", 5, 27, false, false,
17063 stack_trace->GetFrame(3));
17064 checkStackFrame("origin", "", 1, 14, false, false, stack_trace->GetFrame(4));
17065}
17066
17067
17068TEST(GetStackTraceContainsFunctionsWithFunctionName) {
17069 LocalContext env;
17070 v8::Isolate* isolate = env->GetIsolate();
17071 v8::HandleScope scope(isolate);
17072
17073 CompileRunWithOrigin(
17074 "function gen(name, counter) {\n"
17075 " var f = function foo() {\n"
17076 " if (counter === 0)\n"
17077 " throw 1;\n"
17078 " gen(name, counter - 1)();\n"
17079 " };\n"
17080 " if (counter == 3) {\n"
17081 " Object.defineProperty(f, 'name', {get: function(){ throw 239; }});\n"
17082 " } else {\n"
17083 " Object.defineProperty(f, 'name', {writable:true});\n"
17084 " if (counter == 2)\n"
17085 " f.name = 42;\n"
17086 " else\n"
17087 " f.name = name + ':' + counter;\n"
17088 " }\n"
17089 " return f;\n"
17090 "};",
17091 "origin");
17092
17093 isolate->AddMessageListener(StackTraceFunctionNameListener);
17094 isolate->SetCaptureStackTraceForUncaughtExceptions(true);
17095 CompileRunWithOrigin("gen('foo', 3)();", "origin");
17096 isolate->SetCaptureStackTraceForUncaughtExceptions(false);
17097 isolate->RemoveMessageListeners(StackTraceFunctionNameListener);
17098}
17099
17100
17101static void RethrowStackTraceHandler(v8::Local<v8::Message> message,
17102 v8::Local<v8::Value> data) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017103 // Use the frame where JavaScript is called from.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017104 v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017105 CHECK(!stack_trace.IsEmpty());
17106 int frame_count = stack_trace->GetFrameCount();
17107 CHECK_EQ(3, frame_count);
17108 int line_number[] = {1, 2, 5};
17109 for (int i = 0; i < frame_count; i++) {
17110 CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber());
17111 }
17112}
17113
17114
17115// Test that we only return the stack trace at the site where the exception
17116// is first thrown (not where it is rethrown).
17117TEST(RethrowStackTrace) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017118 LocalContext env;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017119 v8::Isolate* isolate = env->GetIsolate();
17120 v8::HandleScope scope(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017121 // We make sure that
17122 // - the stack trace of the ReferenceError in g() is reported.
17123 // - the stack trace is not overwritten when e1 is rethrown by t().
17124 // - the stack trace of e2 does not overwrite that of e1.
17125 const char* source =
17126 "function g() { error; } \n"
17127 "function f() { g(); } \n"
17128 "function t(e) { throw e; } \n"
17129 "try { \n"
17130 " f(); \n"
17131 "} catch (e1) { \n"
17132 " try { \n"
17133 " error; \n"
17134 " } catch (e2) { \n"
17135 " t(e1); \n"
17136 " } \n"
17137 "} \n";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017138 isolate->AddMessageListener(RethrowStackTraceHandler);
17139 isolate->SetCaptureStackTraceForUncaughtExceptions(true);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017140 CompileRun(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017141 isolate->SetCaptureStackTraceForUncaughtExceptions(false);
17142 isolate->RemoveMessageListeners(RethrowStackTraceHandler);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017143}
17144
17145
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017146static void RethrowPrimitiveStackTraceHandler(v8::Local<v8::Message> message,
17147 v8::Local<v8::Value> data) {
17148 v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017149 CHECK(!stack_trace.IsEmpty());
17150 int frame_count = stack_trace->GetFrameCount();
17151 CHECK_EQ(2, frame_count);
17152 int line_number[] = {3, 7};
17153 for (int i = 0; i < frame_count; i++) {
17154 CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber());
17155 }
17156}
17157
17158
17159// Test that we do not recognize identity for primitive exceptions.
17160TEST(RethrowPrimitiveStackTrace) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017161 LocalContext env;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017162 v8::Isolate* isolate = env->GetIsolate();
17163 v8::HandleScope scope(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017164 // We do not capture stack trace for non Error objects on creation time.
17165 // Instead, we capture the stack trace on last throw.
17166 const char* source =
17167 "function g() { throw 404; } \n"
17168 "function f() { g(); } \n"
17169 "function t(e) { throw e; } \n"
17170 "try { \n"
17171 " f(); \n"
17172 "} catch (e1) { \n"
17173 " t(e1) \n"
17174 "} \n";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017175 isolate->AddMessageListener(RethrowPrimitiveStackTraceHandler);
17176 isolate->SetCaptureStackTraceForUncaughtExceptions(true);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017177 CompileRun(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017178 isolate->SetCaptureStackTraceForUncaughtExceptions(false);
17179 isolate->RemoveMessageListeners(RethrowPrimitiveStackTraceHandler);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017180}
17181
17182
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017183static void RethrowExistingStackTraceHandler(v8::Local<v8::Message> message,
17184 v8::Local<v8::Value> data) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017185 // Use the frame where JavaScript is called from.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017186 v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017187 CHECK(!stack_trace.IsEmpty());
17188 CHECK_EQ(1, stack_trace->GetFrameCount());
17189 CHECK_EQ(1, stack_trace->GetFrame(0)->GetLineNumber());
17190}
17191
17192
17193// Test that the stack trace is captured when the error object is created and
17194// not where it is thrown.
17195TEST(RethrowExistingStackTrace) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017196 LocalContext env;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017197 v8::Isolate* isolate = env->GetIsolate();
17198 v8::HandleScope scope(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017199 const char* source =
17200 "var e = new Error(); \n"
17201 "throw e; \n";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017202 isolate->AddMessageListener(RethrowExistingStackTraceHandler);
17203 isolate->SetCaptureStackTraceForUncaughtExceptions(true);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017204 CompileRun(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017205 isolate->SetCaptureStackTraceForUncaughtExceptions(false);
17206 isolate->RemoveMessageListeners(RethrowExistingStackTraceHandler);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017207}
17208
17209
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017210static void RethrowBogusErrorStackTraceHandler(v8::Local<v8::Message> message,
17211 v8::Local<v8::Value> data) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017212 // Use the frame where JavaScript is called from.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017213 v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017214 CHECK(!stack_trace.IsEmpty());
17215 CHECK_EQ(1, stack_trace->GetFrameCount());
17216 CHECK_EQ(2, stack_trace->GetFrame(0)->GetLineNumber());
17217}
17218
17219
17220// Test that the stack trace is captured where the bogus Error object is thrown.
17221TEST(RethrowBogusErrorStackTrace) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017222 LocalContext env;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017223 v8::Isolate* isolate = env->GetIsolate();
17224 v8::HandleScope scope(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017225 const char* source =
17226 "var e = {__proto__: new Error()} \n"
17227 "throw e; \n";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017228 isolate->AddMessageListener(RethrowBogusErrorStackTraceHandler);
17229 isolate->SetCaptureStackTraceForUncaughtExceptions(true);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017230 CompileRun(source);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017231 isolate->SetCaptureStackTraceForUncaughtExceptions(false);
17232 isolate->RemoveMessageListeners(RethrowBogusErrorStackTraceHandler);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017233}
17234
17235
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017236v8::PromiseRejectEvent reject_event = v8::kPromiseRejectWithNoHandler;
17237int promise_reject_counter = 0;
17238int promise_revoke_counter = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017239int promise_reject_msg_line_number = -1;
17240int promise_reject_msg_column_number = -1;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017241int promise_reject_line_number = -1;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017242int promise_reject_column_number = -1;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017243int promise_reject_frame_count = -1;
17244
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017245void PromiseRejectCallback(v8::PromiseRejectMessage reject_message) {
17246 v8::Local<v8::Object> global = CcTest::global();
17247 v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
17248 if (reject_message.GetEvent() == v8::kPromiseRejectWithNoHandler) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017249 promise_reject_counter++;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017250 global->Set(context, v8_str("rejected"), reject_message.GetPromise())
17251 .FromJust();
17252 global->Set(context, v8_str("value"), reject_message.GetValue()).FromJust();
17253 v8::Local<v8::Message> message = v8::Exception::CreateMessage(
17254 CcTest::isolate(), reject_message.GetValue());
17255 v8::Local<v8::StackTrace> stack_trace = message->GetStackTrace();
17256
17257 promise_reject_msg_line_number = message->GetLineNumber(context).FromJust();
17258 promise_reject_msg_column_number =
17259 message->GetStartColumn(context).FromJust() + 1;
17260
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017261 if (!stack_trace.IsEmpty()) {
17262 promise_reject_frame_count = stack_trace->GetFrameCount();
17263 if (promise_reject_frame_count > 0) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017264 CHECK(stack_trace->GetFrame(0)
17265 ->GetScriptName()
17266 ->Equals(context, v8_str("pro"))
17267 .FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017268 promise_reject_line_number = stack_trace->GetFrame(0)->GetLineNumber();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017269 promise_reject_column_number = stack_trace->GetFrame(0)->GetColumn();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017270 } else {
17271 promise_reject_line_number = -1;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017272 promise_reject_column_number = -1;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017273 }
17274 }
17275 } else {
17276 promise_revoke_counter++;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017277 global->Set(context, v8_str("revoked"), reject_message.GetPromise())
17278 .FromJust();
17279 CHECK(reject_message.GetValue().IsEmpty());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017280 }
17281}
17282
17283
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017284v8::Local<v8::Promise> GetPromise(const char* name) {
17285 return v8::Local<v8::Promise>::Cast(
17286 CcTest::global()
17287 ->Get(CcTest::isolate()->GetCurrentContext(), v8_str(name))
17288 .ToLocalChecked());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017289}
17290
17291
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017292v8::Local<v8::Value> RejectValue() {
17293 return CcTest::global()
17294 ->Get(CcTest::isolate()->GetCurrentContext(), v8_str("value"))
17295 .ToLocalChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017296}
17297
17298
17299void ResetPromiseStates() {
17300 promise_reject_counter = 0;
17301 promise_revoke_counter = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017302 promise_reject_msg_line_number = -1;
17303 promise_reject_msg_column_number = -1;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017304 promise_reject_line_number = -1;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017305 promise_reject_column_number = -1;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017306 promise_reject_frame_count = -1;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017307
17308 v8::Local<v8::Object> global = CcTest::global();
17309 v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
17310 global->Set(context, v8_str("rejected"), v8_str("")).FromJust();
17311 global->Set(context, v8_str("value"), v8_str("")).FromJust();
17312 global->Set(context, v8_str("revoked"), v8_str("")).FromJust();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017313}
17314
17315
17316TEST(PromiseRejectCallback) {
17317 LocalContext env;
17318 v8::Isolate* isolate = env->GetIsolate();
17319 v8::HandleScope scope(isolate);
17320
17321 isolate->SetPromiseRejectCallback(PromiseRejectCallback);
17322
17323 ResetPromiseStates();
17324
17325 // Create promise p0.
17326 CompileRun(
17327 "var reject; \n"
17328 "var p0 = new Promise( \n"
17329 " function(res, rej) { \n"
17330 " reject = rej; \n"
17331 " } \n"
17332 "); \n");
17333 CHECK(!GetPromise("p0")->HasHandler());
17334 CHECK_EQ(0, promise_reject_counter);
17335 CHECK_EQ(0, promise_revoke_counter);
17336
17337 // Add resolve handler (and default reject handler) to p0.
17338 CompileRun("var p1 = p0.then(function(){});");
17339 CHECK(GetPromise("p0")->HasHandler());
17340 CHECK(!GetPromise("p1")->HasHandler());
17341 CHECK_EQ(0, promise_reject_counter);
17342 CHECK_EQ(0, promise_revoke_counter);
17343
17344 // Reject p0.
17345 CompileRun("reject('ppp');");
17346 CHECK(GetPromise("p0")->HasHandler());
17347 CHECK(!GetPromise("p1")->HasHandler());
17348 CHECK_EQ(1, promise_reject_counter);
17349 CHECK_EQ(0, promise_revoke_counter);
17350 CHECK_EQ(v8::kPromiseRejectWithNoHandler, reject_event);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017351 CHECK(
17352 GetPromise("rejected")->Equals(env.local(), GetPromise("p1")).FromJust());
17353 CHECK(RejectValue()->Equals(env.local(), v8_str("ppp")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017354
17355 // Reject p0 again. Callback is not triggered again.
17356 CompileRun("reject();");
17357 CHECK(GetPromise("p0")->HasHandler());
17358 CHECK(!GetPromise("p1")->HasHandler());
17359 CHECK_EQ(1, promise_reject_counter);
17360 CHECK_EQ(0, promise_revoke_counter);
17361
17362 // Add resolve handler to p1.
17363 CompileRun("var p2 = p1.then(function(){});");
17364 CHECK(GetPromise("p0")->HasHandler());
17365 CHECK(GetPromise("p1")->HasHandler());
17366 CHECK(!GetPromise("p2")->HasHandler());
17367 CHECK_EQ(2, promise_reject_counter);
17368 CHECK_EQ(1, promise_revoke_counter);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017369 CHECK(
17370 GetPromise("rejected")->Equals(env.local(), GetPromise("p2")).FromJust());
17371 CHECK(RejectValue()->Equals(env.local(), v8_str("ppp")).FromJust());
17372 CHECK(
17373 GetPromise("revoked")->Equals(env.local(), GetPromise("p1")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017374
17375 ResetPromiseStates();
17376
17377 // Create promise q0.
17378 CompileRun(
17379 "var q0 = new Promise( \n"
17380 " function(res, rej) { \n"
17381 " reject = rej; \n"
17382 " } \n"
17383 "); \n");
17384 CHECK(!GetPromise("q0")->HasHandler());
17385 CHECK_EQ(0, promise_reject_counter);
17386 CHECK_EQ(0, promise_revoke_counter);
17387
17388 // Add reject handler to q0.
17389 CompileRun("var q1 = q0.catch(function() {});");
17390 CHECK(GetPromise("q0")->HasHandler());
17391 CHECK(!GetPromise("q1")->HasHandler());
17392 CHECK_EQ(0, promise_reject_counter);
17393 CHECK_EQ(0, promise_revoke_counter);
17394
17395 // Reject q0.
17396 CompileRun("reject('qq')");
17397 CHECK(GetPromise("q0")->HasHandler());
17398 CHECK(!GetPromise("q1")->HasHandler());
17399 CHECK_EQ(0, promise_reject_counter);
17400 CHECK_EQ(0, promise_revoke_counter);
17401
17402 // Add a new reject handler, which rejects by returning Promise.reject().
17403 // The returned promise q_ triggers a reject callback at first, only to
17404 // revoke it when returning it causes q2 to be rejected.
17405 CompileRun(
17406 "var q_;"
17407 "var q2 = q0.catch( \n"
17408 " function() { \n"
17409 " q_ = Promise.reject('qqq'); \n"
17410 " return q_; \n"
17411 " } \n"
17412 "); \n");
17413 CHECK(GetPromise("q0")->HasHandler());
17414 CHECK(!GetPromise("q1")->HasHandler());
17415 CHECK(!GetPromise("q2")->HasHandler());
17416 CHECK(GetPromise("q_")->HasHandler());
17417 CHECK_EQ(2, promise_reject_counter);
17418 CHECK_EQ(1, promise_revoke_counter);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017419 CHECK(
17420 GetPromise("rejected")->Equals(env.local(), GetPromise("q2")).FromJust());
17421 CHECK(
17422 GetPromise("revoked")->Equals(env.local(), GetPromise("q_")).FromJust());
17423 CHECK(RejectValue()->Equals(env.local(), v8_str("qqq")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017424
17425 // Add a reject handler to the resolved q1, which rejects by throwing.
17426 CompileRun(
17427 "var q3 = q1.then( \n"
17428 " function() { \n"
17429 " throw 'qqqq'; \n"
17430 " } \n"
17431 "); \n");
17432 CHECK(GetPromise("q0")->HasHandler());
17433 CHECK(GetPromise("q1")->HasHandler());
17434 CHECK(!GetPromise("q2")->HasHandler());
17435 CHECK(!GetPromise("q3")->HasHandler());
17436 CHECK_EQ(3, promise_reject_counter);
17437 CHECK_EQ(1, promise_revoke_counter);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017438 CHECK(
17439 GetPromise("rejected")->Equals(env.local(), GetPromise("q3")).FromJust());
17440 CHECK(RejectValue()->Equals(env.local(), v8_str("qqqq")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017441
17442 ResetPromiseStates();
17443
17444 // Create promise r0, which has three handlers, two of which handle rejects.
17445 CompileRun(
17446 "var r0 = new Promise( \n"
17447 " function(res, rej) { \n"
17448 " reject = rej; \n"
17449 " } \n"
17450 "); \n"
17451 "var r1 = r0.catch(function() {}); \n"
17452 "var r2 = r0.then(function() {}); \n"
17453 "var r3 = r0.then(function() {}, \n"
17454 " function() {}); \n");
17455 CHECK(GetPromise("r0")->HasHandler());
17456 CHECK(!GetPromise("r1")->HasHandler());
17457 CHECK(!GetPromise("r2")->HasHandler());
17458 CHECK(!GetPromise("r3")->HasHandler());
17459 CHECK_EQ(0, promise_reject_counter);
17460 CHECK_EQ(0, promise_revoke_counter);
17461
17462 // Reject r0.
17463 CompileRun("reject('rrr')");
17464 CHECK(GetPromise("r0")->HasHandler());
17465 CHECK(!GetPromise("r1")->HasHandler());
17466 CHECK(!GetPromise("r2")->HasHandler());
17467 CHECK(!GetPromise("r3")->HasHandler());
17468 CHECK_EQ(1, promise_reject_counter);
17469 CHECK_EQ(0, promise_revoke_counter);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017470 CHECK(
17471 GetPromise("rejected")->Equals(env.local(), GetPromise("r2")).FromJust());
17472 CHECK(RejectValue()->Equals(env.local(), v8_str("rrr")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017473
17474 // Add reject handler to r2.
17475 CompileRun("var r4 = r2.catch(function() {});");
17476 CHECK(GetPromise("r0")->HasHandler());
17477 CHECK(!GetPromise("r1")->HasHandler());
17478 CHECK(GetPromise("r2")->HasHandler());
17479 CHECK(!GetPromise("r3")->HasHandler());
17480 CHECK(!GetPromise("r4")->HasHandler());
17481 CHECK_EQ(1, promise_reject_counter);
17482 CHECK_EQ(1, promise_revoke_counter);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017483 CHECK(
17484 GetPromise("revoked")->Equals(env.local(), GetPromise("r2")).FromJust());
17485 CHECK(RejectValue()->Equals(env.local(), v8_str("rrr")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017486
17487 // Add reject handlers to r4.
17488 CompileRun("var r5 = r4.then(function() {}, function() {});");
17489 CHECK(GetPromise("r0")->HasHandler());
17490 CHECK(!GetPromise("r1")->HasHandler());
17491 CHECK(GetPromise("r2")->HasHandler());
17492 CHECK(!GetPromise("r3")->HasHandler());
17493 CHECK(GetPromise("r4")->HasHandler());
17494 CHECK(!GetPromise("r5")->HasHandler());
17495 CHECK_EQ(1, promise_reject_counter);
17496 CHECK_EQ(1, promise_revoke_counter);
17497
17498 ResetPromiseStates();
17499
17500 // Create promise s0, which has three handlers, none of which handle rejects.
17501 CompileRun(
17502 "var s0 = new Promise( \n"
17503 " function(res, rej) { \n"
17504 " reject = rej; \n"
17505 " } \n"
17506 "); \n"
17507 "var s1 = s0.then(function() {}); \n"
17508 "var s2 = s0.then(function() {}); \n"
17509 "var s3 = s0.then(function() {}); \n");
17510 CHECK(GetPromise("s0")->HasHandler());
17511 CHECK(!GetPromise("s1")->HasHandler());
17512 CHECK(!GetPromise("s2")->HasHandler());
17513 CHECK(!GetPromise("s3")->HasHandler());
17514 CHECK_EQ(0, promise_reject_counter);
17515 CHECK_EQ(0, promise_revoke_counter);
17516
17517 // Reject s0.
17518 CompileRun("reject('sss')");
17519 CHECK(GetPromise("s0")->HasHandler());
17520 CHECK(!GetPromise("s1")->HasHandler());
17521 CHECK(!GetPromise("s2")->HasHandler());
17522 CHECK(!GetPromise("s3")->HasHandler());
17523 CHECK_EQ(3, promise_reject_counter);
17524 CHECK_EQ(0, promise_revoke_counter);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017525 CHECK(RejectValue()->Equals(env.local(), v8_str("sss")).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017526
17527 // Test stack frames.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017528 env->GetIsolate()->SetCaptureStackTraceForUncaughtExceptions(true);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017529
17530 ResetPromiseStates();
17531
17532 // Create promise t0, which is rejected in the constructor with an error.
17533 CompileRunWithOrigin(
17534 "var t0 = new Promise( \n"
17535 " function(res, rej) { \n"
17536 " reference_error; \n"
17537 " } \n"
17538 "); \n",
17539 "pro", 0, 0);
17540 CHECK(!GetPromise("t0")->HasHandler());
17541 CHECK_EQ(1, promise_reject_counter);
17542 CHECK_EQ(0, promise_revoke_counter);
17543 CHECK_EQ(2, promise_reject_frame_count);
17544 CHECK_EQ(3, promise_reject_line_number);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017545 CHECK_EQ(5, promise_reject_column_number);
17546 CHECK_EQ(3, promise_reject_msg_line_number);
17547 CHECK_EQ(5, promise_reject_msg_column_number);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017548
17549 ResetPromiseStates();
17550
17551 // Create promise u0 and chain u1 to it, which is rejected via throw.
17552 CompileRunWithOrigin(
17553 "var u0 = Promise.resolve(); \n"
17554 "var u1 = u0.then( \n"
17555 " function() { \n"
17556 " (function() { \n"
17557 " throw new Error(); \n"
17558 " })(); \n"
17559 " } \n"
17560 " ); \n",
17561 "pro", 0, 0);
17562 CHECK(GetPromise("u0")->HasHandler());
17563 CHECK(!GetPromise("u1")->HasHandler());
17564 CHECK_EQ(1, promise_reject_counter);
17565 CHECK_EQ(0, promise_revoke_counter);
17566 CHECK_EQ(2, promise_reject_frame_count);
17567 CHECK_EQ(5, promise_reject_line_number);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017568 CHECK_EQ(23, promise_reject_column_number);
17569 CHECK_EQ(5, promise_reject_msg_line_number);
17570 CHECK_EQ(23, promise_reject_msg_column_number);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017571
17572 // Throw in u3, which handles u1's rejection.
17573 CompileRunWithOrigin(
17574 "function f() { \n"
17575 " return (function() { \n"
17576 " return new Error(); \n"
17577 " })(); \n"
17578 "} \n"
17579 "var u2 = Promise.reject(f()); \n"
17580 "var u3 = u1.catch( \n"
17581 " function() { \n"
17582 " return u2; \n"
17583 " } \n"
17584 " ); \n",
17585 "pro", 0, 0);
17586 CHECK(GetPromise("u0")->HasHandler());
17587 CHECK(GetPromise("u1")->HasHandler());
17588 CHECK(GetPromise("u2")->HasHandler());
17589 CHECK(!GetPromise("u3")->HasHandler());
17590 CHECK_EQ(3, promise_reject_counter);
17591 CHECK_EQ(2, promise_revoke_counter);
17592 CHECK_EQ(3, promise_reject_frame_count);
17593 CHECK_EQ(3, promise_reject_line_number);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017594 CHECK_EQ(12, promise_reject_column_number);
17595 CHECK_EQ(3, promise_reject_msg_line_number);
17596 CHECK_EQ(12, promise_reject_msg_column_number);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017597
17598 ResetPromiseStates();
17599
17600 // Create promise rejected promise v0, which is incorrectly handled by v1
17601 // via chaining cycle.
17602 CompileRunWithOrigin(
17603 "var v0 = Promise.reject(); \n"
17604 "var v1 = v0.catch( \n"
17605 " function() { \n"
17606 " return v1; \n"
17607 " } \n"
17608 " ); \n",
17609 "pro", 0, 0);
17610 CHECK(GetPromise("v0")->HasHandler());
17611 CHECK(!GetPromise("v1")->HasHandler());
17612 CHECK_EQ(2, promise_reject_counter);
17613 CHECK_EQ(1, promise_revoke_counter);
17614 CHECK_EQ(0, promise_reject_frame_count);
17615 CHECK_EQ(-1, promise_reject_line_number);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017616 CHECK_EQ(-1, promise_reject_column_number);
17617
17618 ResetPromiseStates();
17619
17620 // Create promise t1, which rejects by throwing syntax error from eval.
17621 CompileRunWithOrigin(
17622 "var t1 = new Promise( \n"
17623 " function(res, rej) { \n"
17624 " var content = '\\n\\\n"
17625 " }'; \n"
17626 " eval(content); \n"
17627 " } \n"
17628 "); \n",
17629 "pro", 0, 0);
17630 CHECK(!GetPromise("t1")->HasHandler());
17631 CHECK_EQ(1, promise_reject_counter);
17632 CHECK_EQ(0, promise_revoke_counter);
17633 CHECK_EQ(2, promise_reject_frame_count);
17634 CHECK_EQ(5, promise_reject_line_number);
17635 CHECK_EQ(10, promise_reject_column_number);
17636 CHECK_EQ(2, promise_reject_msg_line_number);
17637 CHECK_EQ(7, promise_reject_msg_column_number);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040017638}
17639
17640
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017641void AnalyzeStackOfEvalWithSourceURL(
17642 const v8::FunctionCallbackInfo<v8::Value>& args) {
17643 v8::HandleScope scope(args.GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017644 v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017645 args.GetIsolate(), 10, v8::StackTrace::kDetailed);
Ben Murdochf87a2032010-10-22 12:50:53 +010017646 CHECK_EQ(5, stackTrace->GetFrameCount());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017647 v8::Local<v8::String> url = v8_str("eval_url");
Ben Murdochf87a2032010-10-22 12:50:53 +010017648 for (int i = 0; i < 3; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017649 v8::Local<v8::String> name =
Ben Murdochf87a2032010-10-22 12:50:53 +010017650 stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
17651 CHECK(!name.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017652 CHECK(url->Equals(args.GetIsolate()->GetCurrentContext(), name).FromJust());
Ben Murdochf87a2032010-10-22 12:50:53 +010017653 }
Ben Murdochf87a2032010-10-22 12:50:53 +010017654}
17655
17656
17657TEST(SourceURLInStackTrace) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017658 v8::Isolate* isolate = CcTest::isolate();
17659 v8::HandleScope scope(isolate);
17660 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Ben Murdochf87a2032010-10-22 12:50:53 +010017661 templ->Set(v8_str("AnalyzeStackOfEvalWithSourceURL"),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017662 v8::FunctionTemplate::New(isolate,
17663 AnalyzeStackOfEvalWithSourceURL));
Ben Murdochf87a2032010-10-22 12:50:53 +010017664 LocalContext context(0, templ);
17665
17666 const char *source =
17667 "function outer() {\n"
17668 "function bar() {\n"
17669 " AnalyzeStackOfEvalWithSourceURL();\n"
17670 "}\n"
17671 "function foo() {\n"
17672 "\n"
17673 " bar();\n"
17674 "}\n"
17675 "foo();\n"
17676 "}\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017677 "eval('(' + outer +')()%s');";
17678
17679 i::ScopedVector<char> code(1024);
17680 i::SNPrintF(code, source, "//# sourceURL=eval_url");
17681 CHECK(CompileRun(code.start())->IsUndefined());
17682 i::SNPrintF(code, source, "//@ sourceURL=eval_url");
17683 CHECK(CompileRun(code.start())->IsUndefined());
17684}
17685
17686
17687static int scriptIdInStack[2];
17688
17689void AnalyzeScriptIdInStack(
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::kScriptId);
17694 CHECK_EQ(2, stackTrace->GetFrameCount());
17695 for (int i = 0; i < 2; i++) {
17696 scriptIdInStack[i] = stackTrace->GetFrame(i)->GetScriptId();
17697 }
17698}
17699
17700
17701TEST(ScriptIdInStackTrace) {
17702 v8::Isolate* isolate = CcTest::isolate();
17703 v8::HandleScope scope(isolate);
17704 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
17705 templ->Set(v8_str("AnalyzeScriptIdInStack"),
17706 v8::FunctionTemplate::New(isolate, AnalyzeScriptIdInStack));
17707 LocalContext context(0, templ);
17708
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017709 v8::Local<v8::String> scriptSource = v8_str(
17710 "function foo() {\n"
17711 " AnalyzeScriptIdInStack();"
17712 "}\n"
17713 "foo();\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017714 v8::Local<v8::Script> script = CompileWithOrigin(scriptSource, "test");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017715 script->Run(context.local()).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017716 for (int i = 0; i < 2; i++) {
17717 CHECK(scriptIdInStack[i] != v8::Message::kNoScriptIdInfo);
17718 CHECK_EQ(scriptIdInStack[i], script->GetUnboundScript()->GetId());
17719 }
17720}
17721
17722
17723void AnalyzeStackOfInlineScriptWithSourceURL(
17724 const v8::FunctionCallbackInfo<v8::Value>& args) {
17725 v8::HandleScope scope(args.GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017726 v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017727 args.GetIsolate(), 10, v8::StackTrace::kDetailed);
17728 CHECK_EQ(4, stackTrace->GetFrameCount());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017729 v8::Local<v8::String> url = v8_str("source_url");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017730 for (int i = 0; i < 3; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017731 v8::Local<v8::String> name =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017732 stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
17733 CHECK(!name.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017734 CHECK(url->Equals(args.GetIsolate()->GetCurrentContext(), name).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017735 }
17736}
17737
17738
17739TEST(InlineScriptWithSourceURLInStackTrace) {
17740 v8::Isolate* isolate = CcTest::isolate();
17741 v8::HandleScope scope(isolate);
17742 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
17743 templ->Set(v8_str("AnalyzeStackOfInlineScriptWithSourceURL"),
17744 v8::FunctionTemplate::New(
17745 CcTest::isolate(), AnalyzeStackOfInlineScriptWithSourceURL));
17746 LocalContext context(0, templ);
17747
17748 const char *source =
17749 "function outer() {\n"
17750 "function bar() {\n"
17751 " AnalyzeStackOfInlineScriptWithSourceURL();\n"
17752 "}\n"
17753 "function foo() {\n"
17754 "\n"
17755 " bar();\n"
17756 "}\n"
17757 "foo();\n"
17758 "}\n"
17759 "outer()\n%s";
17760
17761 i::ScopedVector<char> code(1024);
17762 i::SNPrintF(code, source, "//# sourceURL=source_url");
17763 CHECK(CompileRunWithOrigin(code.start(), "url", 0, 1)->IsUndefined());
17764 i::SNPrintF(code, source, "//@ sourceURL=source_url");
17765 CHECK(CompileRunWithOrigin(code.start(), "url", 0, 1)->IsUndefined());
17766}
17767
17768
17769void AnalyzeStackOfDynamicScriptWithSourceURL(
17770 const v8::FunctionCallbackInfo<v8::Value>& args) {
17771 v8::HandleScope scope(args.GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017772 v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017773 args.GetIsolate(), 10, v8::StackTrace::kDetailed);
17774 CHECK_EQ(4, stackTrace->GetFrameCount());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017775 v8::Local<v8::String> url = v8_str("source_url");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017776 for (int i = 0; i < 3; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017777 v8::Local<v8::String> name =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017778 stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
17779 CHECK(!name.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017780 CHECK(url->Equals(args.GetIsolate()->GetCurrentContext(), name).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017781 }
17782}
17783
17784
17785TEST(DynamicWithSourceURLInStackTrace) {
17786 v8::Isolate* isolate = CcTest::isolate();
17787 v8::HandleScope scope(isolate);
17788 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
17789 templ->Set(v8_str("AnalyzeStackOfDynamicScriptWithSourceURL"),
17790 v8::FunctionTemplate::New(
17791 CcTest::isolate(), AnalyzeStackOfDynamicScriptWithSourceURL));
17792 LocalContext context(0, templ);
17793
17794 const char *source =
17795 "function outer() {\n"
17796 "function bar() {\n"
17797 " AnalyzeStackOfDynamicScriptWithSourceURL();\n"
17798 "}\n"
17799 "function foo() {\n"
17800 "\n"
17801 " bar();\n"
17802 "}\n"
17803 "foo();\n"
17804 "}\n"
17805 "outer()\n%s";
17806
17807 i::ScopedVector<char> code(1024);
17808 i::SNPrintF(code, source, "//# sourceURL=source_url");
17809 CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined());
17810 i::SNPrintF(code, source, "//@ sourceURL=source_url");
17811 CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined());
17812}
17813
17814
17815TEST(DynamicWithSourceURLInStackTraceString) {
17816 LocalContext context;
17817 v8::HandleScope scope(context->GetIsolate());
17818
17819 const char *source =
17820 "function outer() {\n"
17821 " function foo() {\n"
17822 " FAIL.FAIL;\n"
17823 " }\n"
17824 " foo();\n"
17825 "}\n"
17826 "outer()\n%s";
17827
17828 i::ScopedVector<char> code(1024);
17829 i::SNPrintF(code, source, "//# sourceURL=source_url");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017830 v8::TryCatch try_catch(context->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017831 CompileRunWithOrigin(code.start(), "", 0, 0);
17832 CHECK(try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017833 v8::String::Utf8Value stack(
17834 try_catch.StackTrace(context.local()).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017835 CHECK(strstr(*stack, "at foo (source_url:3:5)") != NULL);
17836}
17837
17838
17839TEST(EvalWithSourceURLInMessageScriptResourceNameOrSourceURL) {
17840 LocalContext context;
17841 v8::HandleScope scope(context->GetIsolate());
17842
17843 const char *source =
17844 "function outer() {\n"
17845 " var scriptContents = \"function foo() { FAIL.FAIL; }\\\n"
17846 " //# sourceURL=source_url\";\n"
17847 " eval(scriptContents);\n"
17848 " foo(); }\n"
17849 "outer();\n"
17850 "//# sourceURL=outer_url";
17851
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017852 v8::TryCatch try_catch(context->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017853 CompileRun(source);
17854 CHECK(try_catch.HasCaught());
17855
17856 Local<v8::Message> message = try_catch.Message();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017857 Local<Value> sourceURL = message->GetScriptOrigin().ResourceName();
17858 CHECK_EQ(0, strcmp(*v8::String::Utf8Value(sourceURL), "source_url"));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017859}
17860
17861
17862TEST(RecursionWithSourceURLInMessageScriptResourceNameOrSourceURL) {
17863 LocalContext context;
17864 v8::HandleScope scope(context->GetIsolate());
17865
17866 const char *source =
17867 "function outer() {\n"
17868 " var scriptContents = \"function boo(){ boo(); }\\\n"
17869 " //# sourceURL=source_url\";\n"
17870 " eval(scriptContents);\n"
17871 " boo(); }\n"
17872 "outer();\n"
17873 "//# sourceURL=outer_url";
17874
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017875 v8::TryCatch try_catch(context->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017876 CompileRun(source);
17877 CHECK(try_catch.HasCaught());
17878
17879 Local<v8::Message> message = try_catch.Message();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017880 Local<Value> sourceURL = message->GetScriptOrigin().ResourceName();
17881 CHECK_EQ(0, strcmp(*v8::String::Utf8Value(sourceURL), "source_url"));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017882}
17883
17884
17885static void CreateGarbageInOldSpace() {
17886 i::Factory* factory = CcTest::i_isolate()->factory();
17887 v8::HandleScope scope(CcTest::isolate());
17888 i::AlwaysAllocateScope always_allocate(CcTest::i_isolate());
17889 for (int i = 0; i < 1000; i++) {
17890 factory->NewFixedArray(1000, i::TENURED);
17891 }
Ben Murdochf87a2032010-10-22 12:50:53 +010017892}
17893
17894
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017895// Test that idle notification can be handled and eventually collects garbage.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017896TEST(TestIdleNotification) {
17897 if (!i::FLAG_incremental_marking) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017898 const intptr_t MB = 1024 * 1024;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017899 const double IdlePauseInSeconds = 1.0;
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017900 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017901 v8::HandleScope scope(env->GetIsolate());
17902 intptr_t initial_size = CcTest::heap()->SizeOfObjects();
17903 CreateGarbageInOldSpace();
17904 intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
17905 CHECK_GT(size_with_garbage, initial_size + MB);
17906 bool finished = false;
17907 for (int i = 0; i < 200 && !finished; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017908 if (i < 10 && CcTest::heap()->incremental_marking()->IsStopped()) {
17909 CcTest::heap()->StartIdleIncrementalMarking();
17910 }
17911 finished = env->GetIsolate()->IdleNotificationDeadline(
17912 (v8::base::TimeTicks::HighResolutionNow().ToInternalValue() /
17913 static_cast<double>(v8::base::Time::kMicrosecondsPerSecond)) +
17914 IdlePauseInSeconds);
17915 if (CcTest::heap()->mark_compact_collector()->sweeping_in_progress()) {
17916 CcTest::heap()->mark_compact_collector()->EnsureSweepingCompleted();
17917 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +010017918 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017919 intptr_t final_size = CcTest::heap()->SizeOfObjects();
17920 CHECK(finished);
17921 CHECK_LT(final_size, initial_size + 1);
Ben Murdochc7cc0282012-03-05 14:35:55 +000017922}
17923
Steve Blocka7e24c12009-10-30 11:49:00 +000017924
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017925TEST(Regress2333) {
17926 LocalContext env;
17927 for (int i = 0; i < 3; i++) {
17928 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
17929 }
17930}
17931
Steve Blocka7e24c12009-10-30 11:49:00 +000017932static uint32_t* stack_limit;
17933
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017934static void GetStackLimitCallback(
17935 const v8::FunctionCallbackInfo<v8::Value>& args) {
Steve Block44f0eee2011-05-26 01:26:41 +010017936 stack_limit = reinterpret_cast<uint32_t*>(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017937 CcTest::i_isolate()->stack_guard()->real_climit());
Steve Blocka7e24c12009-10-30 11:49:00 +000017938}
17939
17940
17941// Uses the address of a local variable to determine the stack top now.
17942// Given a size, returns an address that is that far from the current
17943// top of stack.
17944static uint32_t* ComputeStackLimit(uint32_t size) {
17945 uint32_t* answer = &size - (size / sizeof(size));
17946 // If the size is very large and the stack is very near the bottom of
17947 // memory then the calculation above may wrap around and give an address
17948 // that is above the (downwards-growing) stack. In that case we return
17949 // a very low address.
17950 if (answer > &size) return reinterpret_cast<uint32_t*>(sizeof(size));
17951 return answer;
17952}
17953
17954
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017955// We need at least 165kB for an x64 debug build with clang and ASAN.
17956static const int stack_breathing_room = 256 * i::KB;
17957
17958
17959TEST(SetStackLimit) {
17960 uint32_t* set_limit = ComputeStackLimit(stack_breathing_room);
Steve Blocka7e24c12009-10-30 11:49:00 +000017961
17962 // Set stack limit.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017963 CcTest::isolate()->SetStackLimit(reinterpret_cast<uintptr_t>(set_limit));
Steve Blocka7e24c12009-10-30 11:49:00 +000017964
17965 // Execute a script.
Steve Blocka7e24c12009-10-30 11:49:00 +000017966 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017967 v8::HandleScope scope(env->GetIsolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000017968 Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017969 v8::FunctionTemplate::New(env->GetIsolate(), GetStackLimitCallback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017970 Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
17971 CHECK(env->Global()
17972 ->Set(env.local(), v8_str("get_stack_limit"), fun)
17973 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000017974 CompileRun("get_stack_limit();");
17975
17976 CHECK(stack_limit == set_limit);
17977}
17978
17979
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017980TEST(SetStackLimitInThread) {
Steve Blocka7e24c12009-10-30 11:49:00 +000017981 uint32_t* set_limit;
17982 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017983 v8::Locker locker(CcTest::isolate());
17984 set_limit = ComputeStackLimit(stack_breathing_room);
Steve Blocka7e24c12009-10-30 11:49:00 +000017985
17986 // Set stack limit.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017987 CcTest::isolate()->SetStackLimit(reinterpret_cast<uintptr_t>(set_limit));
Steve Blocka7e24c12009-10-30 11:49:00 +000017988
17989 // Execute a script.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017990 v8::HandleScope scope(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000017991 LocalContext env;
17992 Local<v8::FunctionTemplate> fun_templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017993 v8::FunctionTemplate::New(CcTest::isolate(), GetStackLimitCallback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017994 Local<Function> fun = fun_templ->GetFunction(env.local()).ToLocalChecked();
17995 CHECK(env->Global()
17996 ->Set(env.local(), v8_str("get_stack_limit"), fun)
17997 .FromJust());
Steve Blocka7e24c12009-10-30 11:49:00 +000017998 CompileRun("get_stack_limit();");
17999
18000 CHECK(stack_limit == set_limit);
18001 }
18002 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018003 v8::Locker locker(CcTest::isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000018004 CHECK(stack_limit == set_limit);
18005 }
18006}
Steve Block3ce2e202009-11-05 08:53:23 +000018007
18008
18009THREADED_TEST(GetHeapStatistics) {
Steve Block3ce2e202009-11-05 08:53:23 +000018010 LocalContext c1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018011 v8::HandleScope scope(c1->GetIsolate());
Steve Block3ce2e202009-11-05 08:53:23 +000018012 v8::HeapStatistics heap_statistics;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018013 CHECK_EQ(0u, heap_statistics.total_heap_size());
18014 CHECK_EQ(0u, heap_statistics.used_heap_size());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018015 c1->GetIsolate()->GetHeapStatistics(&heap_statistics);
Steve Blockd0582a62009-12-15 09:54:21 +000018016 CHECK_NE(static_cast<int>(heap_statistics.total_heap_size()), 0);
18017 CHECK_NE(static_cast<int>(heap_statistics.used_heap_size()), 0);
18018}
18019
18020
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018021class VisitorImpl : public v8::ExternalResourceVisitor {
18022 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018023 explicit VisitorImpl(TestResource** resource) {
18024 for (int i = 0; i < 4; i++) {
18025 resource_[i] = resource[i];
18026 found_resource_[i] = false;
18027 }
18028 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018029 virtual ~VisitorImpl() {}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018030 virtual void VisitExternalString(v8::Local<v8::String> string) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018031 if (!string->IsExternal()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018032 CHECK(string->IsExternalOneByte());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018033 return;
18034 }
18035 v8::String::ExternalStringResource* resource =
18036 string->GetExternalStringResource();
18037 CHECK(resource);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018038 for (int i = 0; i < 4; i++) {
18039 if (resource_[i] == resource) {
18040 CHECK(!found_resource_[i]);
18041 found_resource_[i] = true;
18042 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018043 }
18044 }
18045 void CheckVisitedResources() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018046 for (int i = 0; i < 4; i++) {
18047 CHECK(found_resource_[i]);
18048 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018049 }
18050
18051 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018052 v8::String::ExternalStringResource* resource_[4];
18053 bool found_resource_[4];
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018054};
18055
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018056
18057TEST(ExternalizeOldSpaceTwoByteCons) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040018058 v8::Isolate* isolate = CcTest::isolate();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018059 LocalContext env;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040018060 v8::HandleScope scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018061 v8::Local<v8::String> cons =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018062 CompileRun("'Romeo Montague ' + 'Juliet Capulet'")
18063 ->ToString(env.local())
18064 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018065 CHECK(v8::Utils::OpenHandle(*cons)->IsConsString());
18066 CcTest::heap()->CollectAllAvailableGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018067 CHECK(CcTest::heap()->old_space()->Contains(*v8::Utils::OpenHandle(*cons)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018068
18069 TestResource* resource = new TestResource(
18070 AsciiToTwoByteString("Romeo Montague Juliet Capulet"));
18071 cons->MakeExternal(resource);
18072
18073 CHECK(cons->IsExternal());
18074 CHECK_EQ(resource, cons->GetExternalStringResource());
18075 String::Encoding encoding;
18076 CHECK_EQ(resource, cons->GetExternalStringResourceBase(&encoding));
18077 CHECK_EQ(String::TWO_BYTE_ENCODING, encoding);
18078}
18079
18080
18081TEST(ExternalizeOldSpaceOneByteCons) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040018082 v8::Isolate* isolate = CcTest::isolate();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018083 LocalContext env;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040018084 v8::HandleScope scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018085 v8::Local<v8::String> cons =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018086 CompileRun("'Romeo Montague ' + 'Juliet Capulet'")
18087 ->ToString(env.local())
18088 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018089 CHECK(v8::Utils::OpenHandle(*cons)->IsConsString());
18090 CcTest::heap()->CollectAllAvailableGarbage();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018091 CHECK(CcTest::heap()->old_space()->Contains(*v8::Utils::OpenHandle(*cons)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018092
18093 TestOneByteResource* resource =
18094 new TestOneByteResource(i::StrDup("Romeo Montague Juliet Capulet"));
18095 cons->MakeExternal(resource);
18096
18097 CHECK(cons->IsExternalOneByte());
18098 CHECK_EQ(resource, cons->GetExternalOneByteStringResource());
18099 String::Encoding encoding;
18100 CHECK_EQ(resource, cons->GetExternalStringResourceBase(&encoding));
18101 CHECK_EQ(String::ONE_BYTE_ENCODING, encoding);
18102}
18103
18104
18105TEST(VisitExternalStrings) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040018106 v8::Isolate* isolate = CcTest::isolate();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018107 LocalContext env;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040018108 v8::HandleScope scope(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018109 const char* string = "Some string";
18110 uint16_t* two_byte_string = AsciiToTwoByteString(string);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018111 TestResource* resource[4];
18112 resource[0] = new TestResource(two_byte_string);
18113 v8::Local<v8::String> string0 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018114 v8::String::NewExternalTwoByte(env->GetIsolate(), resource[0])
18115 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018116 resource[1] = new TestResource(two_byte_string, NULL, false);
18117 v8::Local<v8::String> string1 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018118 v8::String::NewExternalTwoByte(env->GetIsolate(), resource[1])
18119 .ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018120
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018121 // Externalized symbol.
18122 resource[2] = new TestResource(two_byte_string, NULL, false);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018123 v8::Local<v8::String> string2 =
18124 v8::String::NewFromUtf8(env->GetIsolate(), string,
18125 v8::NewStringType::kInternalized)
18126 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018127 CHECK(string2->MakeExternal(resource[2]));
18128
18129 // Symbolized External.
18130 resource[3] = new TestResource(AsciiToTwoByteString("Some other string"));
18131 v8::Local<v8::String> string3 =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018132 v8::String::NewExternalTwoByte(env->GetIsolate(), resource[3])
18133 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018134 CcTest::heap()->CollectAllAvailableGarbage(); // Tenure string.
18135 // Turn into a symbol.
18136 i::Handle<i::String> string3_i = v8::Utils::OpenHandle(*string3);
18137 CHECK(!CcTest::i_isolate()->factory()->InternalizeString(
18138 string3_i).is_null());
18139 CHECK(string3_i->IsInternalizedString());
18140
18141 // We need to add usages for string* to avoid warnings in GCC 4.7
18142 CHECK(string0->IsExternal());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018143 CHECK(string1->IsExternal());
18144 CHECK(string2->IsExternal());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018145 CHECK(string3->IsExternal());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018146
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018147 VisitorImpl visitor(resource);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018148 isolate->VisitExternalResources(&visitor);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018149 visitor.CheckVisitedResources();
18150}
18151
18152
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018153TEST(ExternalStringCollectedAtTearDown) {
18154 int destroyed = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018155 v8::Isolate::CreateParams create_params;
18156 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
18157 v8::Isolate* isolate = v8::Isolate::New(create_params);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018158 { v8::Isolate::Scope isolate_scope(isolate);
18159 v8::HandleScope handle_scope(isolate);
18160 const char* s = "One string to test them all, one string to find them.";
18161 TestOneByteResource* inscription =
18162 new TestOneByteResource(i::StrDup(s), &destroyed);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018163 v8::Local<v8::String> ring =
18164 v8::String::NewExternalOneByte(isolate, inscription).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018165 // Ring is still alive. Orcs are roaming freely across our lands.
18166 CHECK_EQ(0, destroyed);
18167 USE(ring);
18168 }
18169
18170 isolate->Dispose();
18171 // Ring has been destroyed. Free Peoples of Middle-earth Rejoice.
18172 CHECK_EQ(1, destroyed);
18173}
18174
18175
18176TEST(ExternalInternalizedStringCollectedAtTearDown) {
18177 int destroyed = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018178 v8::Isolate::CreateParams create_params;
18179 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
18180 v8::Isolate* isolate = v8::Isolate::New(create_params);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018181 { v8::Isolate::Scope isolate_scope(isolate);
18182 LocalContext env(isolate);
18183 v8::HandleScope handle_scope(isolate);
18184 CompileRun("var ring = 'One string to test them all';");
18185 const char* s = "One string to test them all";
18186 TestOneByteResource* inscription =
18187 new TestOneByteResource(i::StrDup(s), &destroyed);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018188 v8::Local<v8::String> ring =
18189 CompileRun("ring")->ToString(env.local()).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018190 CHECK(v8::Utils::OpenHandle(*ring)->IsInternalizedString());
18191 ring->MakeExternal(inscription);
18192 // Ring is still alive. Orcs are roaming freely across our lands.
18193 CHECK_EQ(0, destroyed);
18194 USE(ring);
18195 }
18196
18197 isolate->Dispose();
18198 // Ring has been destroyed. Free Peoples of Middle-earth Rejoice.
18199 CHECK_EQ(1, destroyed);
18200}
18201
18202
18203TEST(ExternalInternalizedStringCollectedAtGC) {
18204 int destroyed = 0;
18205 { LocalContext env;
18206 v8::HandleScope handle_scope(env->GetIsolate());
18207 CompileRun("var ring = 'One string to test them all';");
18208 const char* s = "One string to test them all";
18209 TestOneByteResource* inscription =
18210 new TestOneByteResource(i::StrDup(s), &destroyed);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040018211 v8::Local<v8::String> ring = CompileRun("ring").As<v8::String>();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018212 CHECK(v8::Utils::OpenHandle(*ring)->IsInternalizedString());
18213 ring->MakeExternal(inscription);
18214 // Ring is still alive. Orcs are roaming freely across our lands.
18215 CHECK_EQ(0, destroyed);
18216 USE(ring);
18217 }
18218
18219 // Garbage collector deals swift blows to evil.
18220 CcTest::i_isolate()->compilation_cache()->Clear();
18221 CcTest::heap()->CollectAllAvailableGarbage();
18222
18223 // Ring has been destroyed. Free Peoples of Middle-earth Rejoice.
18224 CHECK_EQ(1, destroyed);
18225}
18226
18227
Steve Blockd0582a62009-12-15 09:54:21 +000018228static double DoubleFromBits(uint64_t value) {
18229 double target;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018230 i::MemCopy(&target, &value, sizeof(target));
Steve Blockd0582a62009-12-15 09:54:21 +000018231 return target;
18232}
18233
18234
18235static uint64_t DoubleToBits(double value) {
18236 uint64_t target;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018237 i::MemCopy(&target, &value, sizeof(target));
Steve Blockd0582a62009-12-15 09:54:21 +000018238 return target;
18239}
18240
18241
18242static double DoubleToDateTime(double input) {
18243 double date_limit = 864e13;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018244 if (std::isnan(input) || input < -date_limit || input > date_limit) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018245 return std::numeric_limits<double>::quiet_NaN();
Steve Blockd0582a62009-12-15 09:54:21 +000018246 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018247 return (input < 0) ? -(std::floor(-input)) : std::floor(input);
Steve Blockd0582a62009-12-15 09:54:21 +000018248}
18249
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018250
Steve Blockd0582a62009-12-15 09:54:21 +000018251// We don't have a consistent way to write 64-bit constants syntactically, so we
18252// split them into two 32-bit constants and combine them programmatically.
18253static double DoubleFromBits(uint32_t high_bits, uint32_t low_bits) {
18254 return DoubleFromBits((static_cast<uint64_t>(high_bits) << 32) | low_bits);
18255}
18256
18257
18258THREADED_TEST(QuietSignalingNaNs) {
Steve Blockd0582a62009-12-15 09:54:21 +000018259 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018260 v8::Isolate* isolate = context->GetIsolate();
18261 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018262 v8::TryCatch try_catch(isolate);
Steve Blockd0582a62009-12-15 09:54:21 +000018263
18264 // Special double values.
18265 double snan = DoubleFromBits(0x7ff00000, 0x00000001);
18266 double qnan = DoubleFromBits(0x7ff80000, 0x00000000);
18267 double infinity = DoubleFromBits(0x7ff00000, 0x00000000);
18268 double max_normal = DoubleFromBits(0x7fefffff, 0xffffffffu);
18269 double min_normal = DoubleFromBits(0x00100000, 0x00000000);
18270 double max_denormal = DoubleFromBits(0x000fffff, 0xffffffffu);
18271 double min_denormal = DoubleFromBits(0x00000000, 0x00000001);
18272
18273 // Date values are capped at +/-100000000 days (times 864e5 ms per day)
18274 // on either side of the epoch.
18275 double date_limit = 864e13;
18276
18277 double test_values[] = {
18278 snan,
18279 qnan,
18280 infinity,
18281 max_normal,
18282 date_limit + 1,
18283 date_limit,
18284 min_normal,
18285 max_denormal,
18286 min_denormal,
18287 0,
18288 -0,
18289 -min_denormal,
18290 -max_denormal,
18291 -min_normal,
18292 -date_limit,
18293 -date_limit - 1,
18294 -max_normal,
18295 -infinity,
18296 -qnan,
18297 -snan
18298 };
18299 int num_test_values = 20;
18300
18301 for (int i = 0; i < num_test_values; i++) {
18302 double test_value = test_values[i];
18303
18304 // Check that Number::New preserves non-NaNs and quiets SNaNs.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018305 v8::Local<v8::Value> number = v8::Number::New(isolate, test_value);
18306 double stored_number = number->NumberValue(context.local()).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018307 if (!std::isnan(test_value)) {
Steve Blockd0582a62009-12-15 09:54:21 +000018308 CHECK_EQ(test_value, stored_number);
18309 } else {
18310 uint64_t stored_bits = DoubleToBits(stored_number);
18311 // Check if quiet nan (bits 51..62 all set).
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018312#if (defined(V8_TARGET_ARCH_MIPS) || defined(V8_TARGET_ARCH_MIPS64)) && \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018313 !defined(_MIPS_ARCH_MIPS64R6) && !defined(_MIPS_ARCH_MIPS32R6) && \
18314 !defined(USE_SIMULATOR)
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018315 // Most significant fraction bit for quiet nan is set to 0
18316 // on MIPS architecture. Allowed by IEEE-754.
18317 CHECK_EQ(0xffe, static_cast<int>((stored_bits >> 51) & 0xfff));
18318#else
Steve Blockd0582a62009-12-15 09:54:21 +000018319 CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff));
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018320#endif
Steve Blockd0582a62009-12-15 09:54:21 +000018321 }
18322
18323 // Check that Date::New preserves non-NaNs in the date range and
18324 // quiets SNaNs.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018325 v8::Local<v8::Value> date =
18326 v8::Date::New(context.local(), test_value).ToLocalChecked();
Steve Blockd0582a62009-12-15 09:54:21 +000018327 double expected_stored_date = DoubleToDateTime(test_value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018328 double stored_date = date->NumberValue(context.local()).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018329 if (!std::isnan(expected_stored_date)) {
Steve Blockd0582a62009-12-15 09:54:21 +000018330 CHECK_EQ(expected_stored_date, stored_date);
18331 } else {
18332 uint64_t stored_bits = DoubleToBits(stored_date);
18333 // Check if quiet nan (bits 51..62 all set).
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018334#if (defined(V8_TARGET_ARCH_MIPS) || defined(V8_TARGET_ARCH_MIPS64)) && \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018335 !defined(_MIPS_ARCH_MIPS64R6) && !defined(_MIPS_ARCH_MIPS32R6) && \
18336 !defined(USE_SIMULATOR)
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018337 // Most significant fraction bit for quiet nan is set to 0
18338 // on MIPS architecture. Allowed by IEEE-754.
18339 CHECK_EQ(0xffe, static_cast<int>((stored_bits >> 51) & 0xfff));
18340#else
Steve Blockd0582a62009-12-15 09:54:21 +000018341 CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff));
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018342#endif
Steve Blockd0582a62009-12-15 09:54:21 +000018343 }
18344 }
18345}
18346
18347
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018348static void SpaghettiIncident(
18349 const v8::FunctionCallbackInfo<v8::Value>& args) {
18350 v8::HandleScope scope(args.GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018351 v8::TryCatch tc(args.GetIsolate());
18352 v8::MaybeLocal<v8::String> str(
18353 args[0]->ToString(args.GetIsolate()->GetCurrentContext()));
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018354 USE(str);
Steve Blockd0582a62009-12-15 09:54:21 +000018355 if (tc.HasCaught())
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018356 tc.ReThrow();
Steve Blockd0582a62009-12-15 09:54:21 +000018357}
18358
18359
18360// Test that an exception can be propagated down through a spaghetti
18361// stack using ReThrow.
18362THREADED_TEST(SpaghettiStackReThrow) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018363 v8::Isolate* isolate = CcTest::isolate();
18364 v8::HandleScope scope(isolate);
Steve Blockd0582a62009-12-15 09:54:21 +000018365 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018366 context->Global()
18367 ->Set(context.local(), v8_str("s"),
18368 v8::FunctionTemplate::New(isolate, SpaghettiIncident)
18369 ->GetFunction(context.local())
18370 .ToLocalChecked())
18371 .FromJust();
18372 v8::TryCatch try_catch(isolate);
Steve Blockd0582a62009-12-15 09:54:21 +000018373 CompileRun(
18374 "var i = 0;"
18375 "var o = {"
18376 " toString: function () {"
18377 " if (i == 10) {"
18378 " throw 'Hey!';"
18379 " } else {"
18380 " i++;"
18381 " return s(o);"
18382 " }"
18383 " }"
18384 "};"
18385 "s(o);");
18386 CHECK(try_catch.HasCaught());
18387 v8::String::Utf8Value value(try_catch.Exception());
18388 CHECK_EQ(0, strcmp(*value, "Hey!"));
18389}
18390
18391
Steve Blockd0582a62009-12-15 09:54:21 +000018392TEST(Regress528) {
18393 v8::V8::Initialize();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018394 v8::Isolate* isolate = CcTest::isolate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018395 i::FLAG_retain_maps_for_n_gc = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018396 v8::HandleScope scope(isolate);
18397 v8::Local<Context> other_context;
Steve Blockd0582a62009-12-15 09:54:21 +000018398 int gc_count;
18399
18400 // Create a context used to keep the code from aging in the compilation
18401 // cache.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018402 other_context = Context::New(isolate);
Steve Blockd0582a62009-12-15 09:54:21 +000018403
18404 // Context-dependent context data creates reference from the compilation
18405 // cache to the global object.
18406 const char* source_simple = "1";
Steve Blockd0582a62009-12-15 09:54:21 +000018407 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018408 v8::HandleScope scope(isolate);
18409 v8::Local<Context> context = Context::New(isolate);
Steve Blockd0582a62009-12-15 09:54:21 +000018410
18411 context->Enter();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018412 Local<v8::String> obj = v8_str("");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018413 context->SetEmbedderData(0, obj);
Steve Blockd0582a62009-12-15 09:54:21 +000018414 CompileRun(source_simple);
18415 context->Exit();
18416 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018417 isolate->ContextDisposedNotification();
Steve Blockd0582a62009-12-15 09:54:21 +000018418 for (gc_count = 1; gc_count < 10; gc_count++) {
18419 other_context->Enter();
18420 CompileRun(source_simple);
18421 other_context->Exit();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018422 CcTest::heap()->CollectAllGarbage();
Steve Blockd0582a62009-12-15 09:54:21 +000018423 if (GetGlobalObjectsCount() == 1) break;
18424 }
18425 CHECK_GE(2, gc_count);
18426 CHECK_EQ(1, GetGlobalObjectsCount());
18427
18428 // Eval in a function creates reference from the compilation cache to the
18429 // global object.
18430 const char* source_eval = "function f(){eval('1')}; f()";
Steve Blockd0582a62009-12-15 09:54:21 +000018431 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018432 v8::HandleScope scope(isolate);
18433 v8::Local<Context> context = Context::New(isolate);
Steve Blockd0582a62009-12-15 09:54:21 +000018434
18435 context->Enter();
18436 CompileRun(source_eval);
18437 context->Exit();
18438 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018439 isolate->ContextDisposedNotification();
Steve Blockd0582a62009-12-15 09:54:21 +000018440 for (gc_count = 1; gc_count < 10; gc_count++) {
18441 other_context->Enter();
18442 CompileRun(source_eval);
18443 other_context->Exit();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018444 CcTest::heap()->CollectAllGarbage();
Steve Blockd0582a62009-12-15 09:54:21 +000018445 if (GetGlobalObjectsCount() == 1) break;
18446 }
18447 CHECK_GE(2, gc_count);
18448 CHECK_EQ(1, GetGlobalObjectsCount());
18449
18450 // Looking up the line number for an exception creates reference from the
18451 // compilation cache to the global object.
18452 const char* source_exception = "function f(){throw 1;} f()";
Steve Blockd0582a62009-12-15 09:54:21 +000018453 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018454 v8::HandleScope scope(isolate);
18455 v8::Local<Context> context = Context::New(isolate);
Steve Blockd0582a62009-12-15 09:54:21 +000018456
18457 context->Enter();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018458 v8::TryCatch try_catch(isolate);
Steve Blockd0582a62009-12-15 09:54:21 +000018459 CompileRun(source_exception);
18460 CHECK(try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018461 v8::Local<v8::Message> message = try_catch.Message();
Steve Blockd0582a62009-12-15 09:54:21 +000018462 CHECK(!message.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018463 CHECK_EQ(1, message->GetLineNumber(context).FromJust());
Steve Blockd0582a62009-12-15 09:54:21 +000018464 context->Exit();
18465 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018466 isolate->ContextDisposedNotification();
Steve Blockd0582a62009-12-15 09:54:21 +000018467 for (gc_count = 1; gc_count < 10; gc_count++) {
18468 other_context->Enter();
18469 CompileRun(source_exception);
18470 other_context->Exit();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018471 CcTest::heap()->CollectAllGarbage();
Steve Blockd0582a62009-12-15 09:54:21 +000018472 if (GetGlobalObjectsCount() == 1) break;
18473 }
18474 CHECK_GE(2, gc_count);
18475 CHECK_EQ(1, GetGlobalObjectsCount());
18476
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018477 isolate->ContextDisposedNotification();
Steve Block3ce2e202009-11-05 08:53:23 +000018478}
Andrei Popescu402d9372010-02-26 13:31:12 +000018479
18480
18481THREADED_TEST(ScriptOrigin) {
Andrei Popescu402d9372010-02-26 13:31:12 +000018482 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018483 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018484 v8::ScriptOrigin origin = v8::ScriptOrigin(
18485 v8_str("test"), v8::Integer::New(env->GetIsolate(), 1),
18486 v8::Integer::New(env->GetIsolate(), 1), v8::True(env->GetIsolate()),
18487 v8::Local<v8::Integer>(), v8::True(env->GetIsolate()),
18488 v8_str("http://sourceMapUrl"), v8::True(env->GetIsolate()));
18489 v8::Local<v8::String> script = v8_str("function f() {}\n\nfunction g() {}");
18490 v8::Script::Compile(env.local(), script, &origin)
18491 .ToLocalChecked()
18492 ->Run(env.local())
18493 .ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000018494 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018495 env->Global()->Get(env.local(), v8_str("f")).ToLocalChecked());
Andrei Popescu402d9372010-02-26 13:31:12 +000018496 v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018497 env->Global()->Get(env.local(), v8_str("g")).ToLocalChecked());
Andrei Popescu402d9372010-02-26 13:31:12 +000018498
18499 v8::ScriptOrigin script_origin_f = f->GetScriptOrigin();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018500 CHECK_EQ(0, strcmp("test",
18501 *v8::String::Utf8Value(script_origin_f.ResourceName())));
18502 CHECK_EQ(
18503 1,
18504 script_origin_f.ResourceLineOffset()->Int32Value(env.local()).FromJust());
18505 CHECK(script_origin_f.Options().IsSharedCrossOrigin());
18506 CHECK(script_origin_f.Options().IsEmbedderDebugScript());
18507 CHECK(script_origin_f.Options().IsOpaque());
18508 printf("is name = %d\n", script_origin_f.SourceMapUrl()->IsUndefined());
18509
18510 CHECK_EQ(0, strcmp("http://sourceMapUrl",
18511 *v8::String::Utf8Value(script_origin_f.SourceMapUrl())));
Andrei Popescu402d9372010-02-26 13:31:12 +000018512
18513 v8::ScriptOrigin script_origin_g = g->GetScriptOrigin();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018514 CHECK_EQ(0, strcmp("test",
18515 *v8::String::Utf8Value(script_origin_g.ResourceName())));
18516 CHECK_EQ(
18517 1,
18518 script_origin_g.ResourceLineOffset()->Int32Value(env.local()).FromJust());
18519 CHECK(script_origin_g.Options().IsSharedCrossOrigin());
18520 CHECK(script_origin_g.Options().IsEmbedderDebugScript());
18521 CHECK(script_origin_g.Options().IsOpaque());
18522 CHECK_EQ(0, strcmp("http://sourceMapUrl",
18523 *v8::String::Utf8Value(script_origin_g.SourceMapUrl())));
Andrei Popescu402d9372010-02-26 13:31:12 +000018524}
18525
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018526
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018527THREADED_TEST(FunctionGetInferredName) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018528 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018529 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018530 v8::ScriptOrigin origin = v8::ScriptOrigin(v8_str("test"));
18531 v8::Local<v8::String> script =
18532 v8_str("var foo = { bar : { baz : function() {}}}; var f = foo.bar.baz;");
18533 v8::Script::Compile(env.local(), script, &origin)
18534 .ToLocalChecked()
18535 ->Run(env.local())
18536 .ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018537 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018538 env->Global()->Get(env.local(), v8_str("f")).ToLocalChecked());
18539 CHECK_EQ(0,
18540 strcmp("foo.bar.baz", *v8::String::Utf8Value(f->GetInferredName())));
18541}
18542
18543
18544THREADED_TEST(FunctionGetDebugName) {
18545 LocalContext env;
18546 v8::HandleScope scope(env->GetIsolate());
18547 const char* code =
18548 "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';"
18579 "}; g();"
18580 "var h = function() {};"
18581 "h.displayName = 'displayName';"
18582 "Object.defineProperty(h, 'name', { value: 'function.name' });"
18583 "var i = function() {};"
18584 "i.displayName = 239;"
18585 "Object.defineProperty(i, 'name', { value: 'function.name' });"
18586 "var j = function() {};"
18587 "Object.defineProperty(j, 'name', { value: 'function.name' });"
Ben Murdochda12d292016-06-02 14:46:10 +010018588 "var foo = { bar : { baz : (0, function() {})}}; var k = foo.bar.baz;"
18589 "var foo = { bar : { baz : function() {} }}; var l = foo.bar.baz;";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018590 v8::ScriptOrigin origin = v8::ScriptOrigin(v8_str("test"));
18591 v8::Script::Compile(env.local(), v8_str(code), &origin)
18592 .ToLocalChecked()
18593 ->Run(env.local())
18594 .ToLocalChecked();
18595 v8::Local<v8::Value> error =
18596 env->Global()->Get(env.local(), v8_str("error")).ToLocalChecked();
18597 CHECK_EQ(false, error->BooleanValue(env.local()).FromJust());
18598 const char* functions[] = {"a", "display_a",
18599 "b", "display_b",
18600 "c", "c",
18601 "d", "d",
18602 "e", "e",
18603 "f", "f",
18604 "g", "set_in_runtime",
18605 "h", "displayName",
18606 "i", "function.name",
18607 "j", "function.name",
Ben Murdochda12d292016-06-02 14:46:10 +010018608 "k", "foo.bar.baz",
18609 "l", "baz"};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018610 for (size_t i = 0; i < sizeof(functions) / sizeof(functions[0]) / 2; ++i) {
18611 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
18612 env->Global()
18613 ->Get(env.local(),
18614 v8::String::NewFromUtf8(env->GetIsolate(), functions[i * 2],
18615 v8::NewStringType::kNormal)
18616 .ToLocalChecked())
18617 .ToLocalChecked());
18618 CHECK_EQ(0, strcmp(functions[i * 2 + 1],
18619 *v8::String::Utf8Value(f->GetDebugName())));
18620 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018621}
Andrei Popescu402d9372010-02-26 13:31:12 +000018622
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018623
18624THREADED_TEST(FunctionGetDisplayName) {
Andrei Popescu402d9372010-02-26 13:31:12 +000018625 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018626 v8::HandleScope scope(env->GetIsolate());
18627 const char* code = "var error = false;"
18628 "function a() { this.x = 1; };"
18629 "a.displayName = 'display_a';"
18630 "var b = (function() {"
18631 " var f = function() { this.x = 2; };"
18632 " f.displayName = 'display_b';"
18633 " return f;"
18634 "})();"
18635 "var c = function() {};"
18636 "c.__defineGetter__('displayName', function() {"
18637 " error = true;"
18638 " throw new Error();"
18639 "});"
18640 "function d() {};"
18641 "d.__defineGetter__('displayName', function() {"
18642 " error = true;"
18643 " return 'wrong_display_name';"
18644 "});"
18645 "function e() {};"
18646 "e.displayName = 'wrong_display_name';"
18647 "e.__defineSetter__('displayName', function() {"
18648 " error = true;"
18649 " throw new Error();"
18650 "});"
18651 "function f() {};"
18652 "f.displayName = { 'foo': 6, toString: function() {"
18653 " error = true;"
18654 " return 'wrong_display_name';"
18655 "}};"
18656 "var g = function() {"
18657 " arguments.callee.displayName = 'set_in_runtime';"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018658 "}; g();";
18659 v8::ScriptOrigin origin = v8::ScriptOrigin(v8_str("test"));
18660 v8::Script::Compile(env.local(), v8_str(code), &origin)
18661 .ToLocalChecked()
18662 ->Run(env.local())
18663 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018664 v8::Local<v8::Value> error =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018665 env->Global()->Get(env.local(), v8_str("error")).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018666 v8::Local<v8::Function> a = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018667 env->Global()->Get(env.local(), v8_str("a")).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018668 v8::Local<v8::Function> b = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018669 env->Global()->Get(env.local(), v8_str("b")).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018670 v8::Local<v8::Function> c = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018671 env->Global()->Get(env.local(), v8_str("c")).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018672 v8::Local<v8::Function> d = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018673 env->Global()->Get(env.local(), v8_str("d")).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018674 v8::Local<v8::Function> e = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018675 env->Global()->Get(env.local(), v8_str("e")).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018676 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018677 env->Global()->Get(env.local(), v8_str("f")).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018678 v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018679 env->Global()->Get(env.local(), v8_str("g")).ToLocalChecked());
18680 CHECK_EQ(false, error->BooleanValue(env.local()).FromJust());
18681 CHECK_EQ(0, strcmp("display_a", *v8::String::Utf8Value(a->GetDisplayName())));
18682 CHECK_EQ(0, strcmp("display_b", *v8::String::Utf8Value(b->GetDisplayName())));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018683 CHECK(c->GetDisplayName()->IsUndefined());
18684 CHECK(d->GetDisplayName()->IsUndefined());
18685 CHECK(e->GetDisplayName()->IsUndefined());
18686 CHECK(f->GetDisplayName()->IsUndefined());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018687 CHECK_EQ(
18688 0, strcmp("set_in_runtime", *v8::String::Utf8Value(g->GetDisplayName())));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018689}
18690
18691
18692THREADED_TEST(ScriptLineNumber) {
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("function f() {}\n\nfunction g() {}");
18697 v8::Script::Compile(env.local(), script, &origin)
18698 .ToLocalChecked()
18699 ->Run(env.local())
18700 .ToLocalChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +000018701 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018702 env->Global()->Get(env.local(), v8_str("f")).ToLocalChecked());
Andrei Popescu402d9372010-02-26 13:31:12 +000018703 v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018704 env->Global()->Get(env.local(), v8_str("g")).ToLocalChecked());
Andrei Popescu402d9372010-02-26 13:31:12 +000018705 CHECK_EQ(0, f->GetScriptLineNumber());
18706 CHECK_EQ(2, g->GetScriptLineNumber());
18707}
18708
18709
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018710THREADED_TEST(ScriptColumnNumber) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018711 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018712 v8::Isolate* isolate = env->GetIsolate();
18713 v8::HandleScope scope(isolate);
18714 v8::ScriptOrigin origin =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018715 v8::ScriptOrigin(v8_str("test"), v8::Integer::New(isolate, 3),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018716 v8::Integer::New(isolate, 2));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018717 v8::Local<v8::String> script =
18718 v8_str("function foo() {}\n\n function bar() {}");
18719 v8::Script::Compile(env.local(), script, &origin)
18720 .ToLocalChecked()
18721 ->Run(env.local())
18722 .ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018723 v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018724 env->Global()->Get(env.local(), v8_str("foo")).ToLocalChecked());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018725 v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018726 env->Global()->Get(env.local(), v8_str("bar")).ToLocalChecked());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018727 CHECK_EQ(14, foo->GetScriptColumnNumber());
18728 CHECK_EQ(17, bar->GetScriptColumnNumber());
18729}
18730
18731
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018732THREADED_TEST(FunctionIsBuiltin) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018733 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018734 v8::Isolate* isolate = env->GetIsolate();
18735 v8::HandleScope scope(isolate);
18736 v8::Local<v8::Function> f;
18737 f = v8::Local<v8::Function>::Cast(CompileRun("Math.floor"));
18738 CHECK(f->IsBuiltin());
18739 f = v8::Local<v8::Function>::Cast(CompileRun("Object"));
18740 CHECK(f->IsBuiltin());
18741 f = v8::Local<v8::Function>::Cast(CompileRun("Object.__defineSetter__"));
18742 CHECK(f->IsBuiltin());
18743 f = v8::Local<v8::Function>::Cast(CompileRun("Array.prototype.toString"));
18744 CHECK(f->IsBuiltin());
18745 f = v8::Local<v8::Function>::Cast(CompileRun("function a() {}; a;"));
18746 CHECK(!f->IsBuiltin());
18747}
18748
18749
18750THREADED_TEST(FunctionGetScriptId) {
18751 LocalContext env;
18752 v8::Isolate* isolate = env->GetIsolate();
18753 v8::HandleScope scope(isolate);
18754 v8::ScriptOrigin origin =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018755 v8::ScriptOrigin(v8_str("test"), v8::Integer::New(isolate, 3),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018756 v8::Integer::New(isolate, 2));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018757 v8::Local<v8::String> scriptSource =
18758 v8_str("function foo() {}\n\n function bar() {}");
18759 v8::Local<v8::Script> script(
18760 v8::Script::Compile(env.local(), scriptSource, &origin).ToLocalChecked());
18761 script->Run(env.local()).ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018762 v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018763 env->Global()->Get(env.local(), v8_str("foo")).ToLocalChecked());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018764 v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018765 env->Global()->Get(env.local(), v8_str("bar")).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018766 CHECK_EQ(script->GetUnboundScript()->GetId(), foo->ScriptId());
18767 CHECK_EQ(script->GetUnboundScript()->GetId(), bar->ScriptId());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010018768}
18769
18770
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018771THREADED_TEST(FunctionGetBoundFunction) {
18772 LocalContext env;
18773 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018774 v8::ScriptOrigin origin = v8::ScriptOrigin(v8_str("test"));
18775 v8::Local<v8::String> script = v8_str(
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018776 "var a = new Object();\n"
18777 "a.x = 1;\n"
18778 "function f () { return this.x };\n"
18779 "var g = f.bind(a);\n"
18780 "var b = g();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018781 v8::Script::Compile(env.local(), script, &origin)
18782 .ToLocalChecked()
18783 ->Run(env.local())
18784 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018785 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018786 env->Global()->Get(env.local(), v8_str("f")).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018787 v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018788 env->Global()->Get(env.local(), v8_str("g")).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018789 CHECK(g->GetBoundFunction()->IsFunction());
18790 Local<v8::Function> original_function = Local<v8::Function>::Cast(
18791 g->GetBoundFunction());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018792 CHECK(f->GetName()
18793 ->Equals(env.local(), original_function->GetName())
18794 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018795 CHECK_EQ(f->GetScriptLineNumber(), original_function->GetScriptLineNumber());
18796 CHECK_EQ(f->GetScriptColumnNumber(),
18797 original_function->GetScriptColumnNumber());
Andrei Popescu402d9372010-02-26 13:31:12 +000018798}
18799
18800
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018801static void GetterWhichReturns42(
18802 Local<String> name,
18803 const v8::PropertyCallbackInfo<v8::Value>& info) {
18804 CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
18805 CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
18806 info.GetReturnValue().Set(v8_num(42));
18807}
18808
18809
18810static void SetterWhichSetsYOnThisTo23(
18811 Local<String> name,
18812 Local<Value> value,
18813 const v8::PropertyCallbackInfo<void>& info) {
18814 CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
18815 CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018816 Local<Object>::Cast(info.This())
18817 ->Set(info.GetIsolate()->GetCurrentContext(), v8_str("y"), v8_num(23))
18818 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018819}
18820
18821
Emily Bernierd0a1eb72015-03-24 16:35:39 -040018822void FooGetInterceptor(Local<Name> name,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018823 const v8::PropertyCallbackInfo<v8::Value>& info) {
18824 CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
18825 CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018826 if (!name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
18827 .FromJust()) {
18828 return;
18829 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018830 info.GetReturnValue().Set(v8_num(42));
18831}
18832
18833
Emily Bernierd0a1eb72015-03-24 16:35:39 -040018834void FooSetInterceptor(Local<Name> name, Local<Value> value,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018835 const v8::PropertyCallbackInfo<v8::Value>& info) {
18836 CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
18837 CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018838 if (!name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
18839 .FromJust()) {
18840 return;
18841 }
18842 Local<Object>::Cast(info.This())
18843 ->Set(info.GetIsolate()->GetCurrentContext(), v8_str("y"), v8_num(23))
18844 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018845 info.GetReturnValue().Set(v8_num(23));
Andrei Popescu402d9372010-02-26 13:31:12 +000018846}
18847
18848
Steve Block6ded16b2010-05-10 14:33:55 +010018849TEST(SetterOnConstructorPrototype) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018850 v8::Isolate* isolate = CcTest::isolate();
18851 v8::HandleScope scope(isolate);
18852 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
18853 templ->SetAccessor(v8_str("x"), GetterWhichReturns42,
Andrei Popescu402d9372010-02-26 13:31:12 +000018854 SetterWhichSetsYOnThisTo23);
18855 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018856 CHECK(context->Global()
18857 ->Set(context.local(), v8_str("P"),
18858 templ->NewInstance(context.local()).ToLocalChecked())
18859 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000018860 CompileRun("function C1() {"
18861 " this.x = 23;"
18862 "};"
18863 "C1.prototype = P;"
18864 "function C2() {"
18865 " this.x = 23"
18866 "};"
18867 "C2.prototype = { };"
18868 "C2.prototype.__proto__ = P;");
18869
18870 v8::Local<v8::Script> script;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018871 script = v8_compile("new C1();");
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> c1 = v8::Local<v8::Object>::Cast(
18874 script->Run(context.local()).ToLocalChecked());
18875 CHECK_EQ(42, c1->Get(context.local(), v8_str("x"))
18876 .ToLocalChecked()
18877 ->Int32Value(context.local())
18878 .FromJust());
18879 CHECK_EQ(23, c1->Get(context.local(), v8_str("y"))
18880 .ToLocalChecked()
18881 ->Int32Value(context.local())
18882 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000018883 }
18884
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018885 script = v8_compile("new C2();");
Andrei Popescu402d9372010-02-26 13:31:12 +000018886 for (int i = 0; i < 10; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018887 v8::Local<v8::Object> c2 = v8::Local<v8::Object>::Cast(
18888 script->Run(context.local()).ToLocalChecked());
18889 CHECK_EQ(42, c2->Get(context.local(), v8_str("x"))
18890 .ToLocalChecked()
18891 ->Int32Value(context.local())
18892 .FromJust());
18893 CHECK_EQ(23, c2->Get(context.local(), v8_str("y"))
18894 .ToLocalChecked()
18895 ->Int32Value(context.local())
18896 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000018897 }
18898}
18899
18900
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018901static void NamedPropertySetterWhichSetsYOnThisTo23(
Emily Bernierd0a1eb72015-03-24 16:35:39 -040018902 Local<Name> name, Local<Value> value,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018903 const v8::PropertyCallbackInfo<v8::Value>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018904 if (name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("x"))
18905 .FromJust()) {
18906 Local<Object>::Cast(info.This())
18907 ->Set(info.GetIsolate()->GetCurrentContext(), v8_str("y"), v8_num(23))
18908 .FromJust();
Andrei Popescu402d9372010-02-26 13:31:12 +000018909 }
Andrei Popescu402d9372010-02-26 13:31:12 +000018910}
18911
18912
18913THREADED_TEST(InterceptorOnConstructorPrototype) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018914 v8::Isolate* isolate = CcTest::isolate();
18915 v8::HandleScope scope(isolate);
18916 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040018917 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
18918 NamedPropertyGetterWhichReturns42,
18919 NamedPropertySetterWhichSetsYOnThisTo23));
Andrei Popescu402d9372010-02-26 13:31:12 +000018920 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018921 CHECK(context->Global()
18922 ->Set(context.local(), v8_str("P"),
18923 templ->NewInstance(context.local()).ToLocalChecked())
18924 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000018925 CompileRun("function C1() {"
18926 " this.x = 23;"
18927 "};"
18928 "C1.prototype = P;"
18929 "function C2() {"
18930 " this.x = 23"
18931 "};"
18932 "C2.prototype = { };"
18933 "C2.prototype.__proto__ = P;");
18934
18935 v8::Local<v8::Script> script;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018936 script = v8_compile("new C1();");
Andrei Popescu402d9372010-02-26 13:31:12 +000018937 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(23, c1->Get(context.local(), v8_str("x"))
18941 .ToLocalChecked()
18942 ->Int32Value(context.local())
18943 .FromJust());
18944 CHECK_EQ(42, c1->Get(context.local(), v8_str("y"))
18945 .ToLocalChecked()
18946 ->Int32Value(context.local())
18947 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000018948 }
18949
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018950 script = v8_compile("new C2();");
Andrei Popescu402d9372010-02-26 13:31:12 +000018951 for (int i = 0; i < 10; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018952 v8::Local<v8::Object> c2 = v8::Local<v8::Object>::Cast(
18953 script->Run(context.local()).ToLocalChecked());
18954 CHECK_EQ(23, c2->Get(context.local(), v8_str("x"))
18955 .ToLocalChecked()
18956 ->Int32Value(context.local())
18957 .FromJust());
18958 CHECK_EQ(42, c2->Get(context.local(), v8_str("y"))
18959 .ToLocalChecked()
18960 ->Int32Value(context.local())
18961 .FromJust());
Andrei Popescu402d9372010-02-26 13:31:12 +000018962 }
18963}
Steve Block6ded16b2010-05-10 14:33:55 +010018964
18965
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018966TEST(Regress618) {
Steve Block6ded16b2010-05-10 14:33:55 +010018967 const char* source = "function C1() {"
18968 " this.x = 23;"
18969 "};"
18970 "C1.prototype = P;";
18971
Steve Block6ded16b2010-05-10 14:33:55 +010018972 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018973 v8::Isolate* isolate = context->GetIsolate();
18974 v8::HandleScope scope(isolate);
Steve Block6ded16b2010-05-10 14:33:55 +010018975 v8::Local<v8::Script> script;
18976
18977 // Use a simple object as prototype.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018978 v8::Local<v8::Object> prototype = v8::Object::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018979 prototype->Set(context.local(), v8_str("y"), v8_num(42)).FromJust();
18980 CHECK(context->Global()
18981 ->Set(context.local(), v8_str("P"), prototype)
18982 .FromJust());
Steve Block6ded16b2010-05-10 14:33:55 +010018983
18984 // This compile will add the code to the compilation cache.
18985 CompileRun(source);
18986
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018987 script = v8_compile("new C1();");
Kristian Monsen0d5e1162010-09-30 15:31:59 +010018988 // Allow enough iterations for the inobject slack tracking logic
18989 // to finalize instance size and install the fast construct stub.
18990 for (int i = 0; i < 256; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018991 v8::Local<v8::Object> c1 = v8::Local<v8::Object>::Cast(
18992 script->Run(context.local()).ToLocalChecked());
18993 CHECK_EQ(23, c1->Get(context.local(), v8_str("x"))
18994 .ToLocalChecked()
18995 ->Int32Value(context.local())
18996 .FromJust());
18997 CHECK_EQ(42, c1->Get(context.local(), v8_str("y"))
18998 .ToLocalChecked()
18999 ->Int32Value(context.local())
19000 .FromJust());
Steve Block6ded16b2010-05-10 14:33:55 +010019001 }
19002
19003 // Use an API object with accessors as prototype.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019004 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
19005 templ->SetAccessor(v8_str("x"), GetterWhichReturns42,
Steve Block6ded16b2010-05-10 14:33:55 +010019006 SetterWhichSetsYOnThisTo23);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019007 CHECK(context->Global()
19008 ->Set(context.local(), v8_str("P"),
19009 templ->NewInstance(context.local()).ToLocalChecked())
19010 .FromJust());
Steve Block6ded16b2010-05-10 14:33:55 +010019011
19012 // This compile will get the code from the compilation cache.
19013 CompileRun(source);
19014
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019015 script = v8_compile("new C1();");
Steve Block6ded16b2010-05-10 14:33:55 +010019016 for (int i = 0; i < 10; i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019017 v8::Local<v8::Object> c1 = v8::Local<v8::Object>::Cast(
19018 script->Run(context.local()).ToLocalChecked());
19019 CHECK_EQ(42, c1->Get(context.local(), v8_str("x"))
19020 .ToLocalChecked()
19021 ->Int32Value(context.local())
19022 .FromJust());
19023 CHECK_EQ(23, c1->Get(context.local(), v8_str("y"))
19024 .ToLocalChecked()
19025 ->Int32Value(context.local())
19026 .FromJust());
Steve Block6ded16b2010-05-10 14:33:55 +010019027 }
19028}
19029
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019030v8::Isolate* gc_callbacks_isolate = NULL;
Steve Block6ded16b2010-05-10 14:33:55 +010019031int prologue_call_count = 0;
19032int epilogue_call_count = 0;
19033int prologue_call_count_second = 0;
19034int epilogue_call_count_second = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019035int prologue_call_count_alloc = 0;
19036int epilogue_call_count_alloc = 0;
Steve Block6ded16b2010-05-10 14:33:55 +010019037
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019038void PrologueCallback(v8::Isolate* isolate,
19039 v8::GCType,
19040 v8::GCCallbackFlags flags) {
19041 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
19042 CHECK_EQ(gc_callbacks_isolate, isolate);
19043 ++prologue_call_count;
19044}
19045
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019046void EpilogueCallback(v8::Isolate* isolate,
19047 v8::GCType,
19048 v8::GCCallbackFlags flags) {
19049 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
19050 CHECK_EQ(gc_callbacks_isolate, isolate);
19051 ++epilogue_call_count;
19052}
19053
19054
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019055void PrologueCallbackSecond(v8::Isolate* isolate,
19056 v8::GCType,
19057 v8::GCCallbackFlags flags) {
19058 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
19059 CHECK_EQ(gc_callbacks_isolate, isolate);
19060 ++prologue_call_count_second;
19061}
19062
19063
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019064void EpilogueCallbackSecond(v8::Isolate* isolate,
19065 v8::GCType,
19066 v8::GCCallbackFlags flags) {
19067 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
19068 CHECK_EQ(gc_callbacks_isolate, isolate);
19069 ++epilogue_call_count_second;
19070}
19071
19072
19073void PrologueCallbackAlloc(v8::Isolate* isolate,
19074 v8::GCType,
19075 v8::GCCallbackFlags flags) {
19076 v8::HandleScope scope(isolate);
19077
19078 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
19079 CHECK_EQ(gc_callbacks_isolate, isolate);
19080 ++prologue_call_count_alloc;
19081
19082 // Simulate full heap to see if we will reenter this callback
Ben Murdoch61f157c2016-09-16 13:49:30 +010019083 i::heap::SimulateFullSpace(CcTest::heap()->new_space());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019084
19085 Local<Object> obj = Object::New(isolate);
19086 CHECK(!obj.IsEmpty());
19087
19088 CcTest::heap()->CollectAllGarbage(
19089 i::Heap::kAbortIncrementalMarkingMask);
19090}
19091
19092
19093void EpilogueCallbackAlloc(v8::Isolate* isolate,
19094 v8::GCType,
19095 v8::GCCallbackFlags flags) {
19096 v8::HandleScope scope(isolate);
19097
19098 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
19099 CHECK_EQ(gc_callbacks_isolate, isolate);
19100 ++epilogue_call_count_alloc;
19101
19102 // Simulate full heap to see if we will reenter this callback
Ben Murdoch61f157c2016-09-16 13:49:30 +010019103 i::heap::SimulateFullSpace(CcTest::heap()->new_space());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019104
19105 Local<Object> obj = Object::New(isolate);
19106 CHECK(!obj.IsEmpty());
19107
19108 CcTest::heap()->CollectAllGarbage(
19109 i::Heap::kAbortIncrementalMarkingMask);
19110}
19111
19112
19113TEST(GCCallbacksOld) {
Steve Block6ded16b2010-05-10 14:33:55 +010019114 LocalContext context;
19115
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019116 gc_callbacks_isolate = context->GetIsolate();
19117
19118 context->GetIsolate()->AddGCPrologueCallback(PrologueCallback);
19119 context->GetIsolate()->AddGCEpilogueCallback(EpilogueCallback);
Steve Block6ded16b2010-05-10 14:33:55 +010019120 CHECK_EQ(0, prologue_call_count);
19121 CHECK_EQ(0, epilogue_call_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019122 CcTest::heap()->CollectAllGarbage();
Steve Block6ded16b2010-05-10 14:33:55 +010019123 CHECK_EQ(1, prologue_call_count);
19124 CHECK_EQ(1, epilogue_call_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019125 context->GetIsolate()->AddGCPrologueCallback(PrologueCallbackSecond);
19126 context->GetIsolate()->AddGCEpilogueCallback(EpilogueCallbackSecond);
19127 CcTest::heap()->CollectAllGarbage();
Steve Block6ded16b2010-05-10 14:33:55 +010019128 CHECK_EQ(2, prologue_call_count);
19129 CHECK_EQ(2, epilogue_call_count);
19130 CHECK_EQ(1, prologue_call_count_second);
19131 CHECK_EQ(1, epilogue_call_count_second);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019132 context->GetIsolate()->RemoveGCPrologueCallback(PrologueCallback);
19133 context->GetIsolate()->RemoveGCEpilogueCallback(EpilogueCallback);
19134 CcTest::heap()->CollectAllGarbage();
Steve Block6ded16b2010-05-10 14:33:55 +010019135 CHECK_EQ(2, prologue_call_count);
19136 CHECK_EQ(2, epilogue_call_count);
19137 CHECK_EQ(2, prologue_call_count_second);
19138 CHECK_EQ(2, epilogue_call_count_second);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019139 context->GetIsolate()->RemoveGCPrologueCallback(PrologueCallbackSecond);
19140 context->GetIsolate()->RemoveGCEpilogueCallback(EpilogueCallbackSecond);
19141 CcTest::heap()->CollectAllGarbage();
Steve Block6ded16b2010-05-10 14:33:55 +010019142 CHECK_EQ(2, prologue_call_count);
19143 CHECK_EQ(2, epilogue_call_count);
19144 CHECK_EQ(2, prologue_call_count_second);
19145 CHECK_EQ(2, epilogue_call_count_second);
19146}
Kristian Monsen25f61362010-05-21 11:50:48 +010019147
19148
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019149TEST(GCCallbacks) {
19150 LocalContext context;
19151 v8::Isolate* isolate = context->GetIsolate();
19152 gc_callbacks_isolate = isolate;
19153 isolate->AddGCPrologueCallback(PrologueCallback);
19154 isolate->AddGCEpilogueCallback(EpilogueCallback);
19155 CHECK_EQ(0, prologue_call_count);
19156 CHECK_EQ(0, epilogue_call_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019157 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019158 CHECK_EQ(1, prologue_call_count);
19159 CHECK_EQ(1, epilogue_call_count);
19160 isolate->AddGCPrologueCallback(PrologueCallbackSecond);
19161 isolate->AddGCEpilogueCallback(EpilogueCallbackSecond);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019162 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019163 CHECK_EQ(2, prologue_call_count);
19164 CHECK_EQ(2, epilogue_call_count);
19165 CHECK_EQ(1, prologue_call_count_second);
19166 CHECK_EQ(1, epilogue_call_count_second);
19167 isolate->RemoveGCPrologueCallback(PrologueCallback);
19168 isolate->RemoveGCEpilogueCallback(EpilogueCallback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019169 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019170 CHECK_EQ(2, prologue_call_count);
19171 CHECK_EQ(2, epilogue_call_count);
19172 CHECK_EQ(2, prologue_call_count_second);
19173 CHECK_EQ(2, epilogue_call_count_second);
19174 isolate->RemoveGCPrologueCallback(PrologueCallbackSecond);
19175 isolate->RemoveGCEpilogueCallback(EpilogueCallbackSecond);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019176 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019177 CHECK_EQ(2, prologue_call_count);
19178 CHECK_EQ(2, epilogue_call_count);
19179 CHECK_EQ(2, prologue_call_count_second);
19180 CHECK_EQ(2, epilogue_call_count_second);
19181
19182 CHECK_EQ(0, prologue_call_count_alloc);
19183 CHECK_EQ(0, epilogue_call_count_alloc);
19184 isolate->AddGCPrologueCallback(PrologueCallbackAlloc);
19185 isolate->AddGCEpilogueCallback(EpilogueCallbackAlloc);
19186 CcTest::heap()->CollectAllGarbage(
19187 i::Heap::kAbortIncrementalMarkingMask);
19188 CHECK_EQ(1, prologue_call_count_alloc);
19189 CHECK_EQ(1, epilogue_call_count_alloc);
19190 isolate->RemoveGCPrologueCallback(PrologueCallbackAlloc);
19191 isolate->RemoveGCEpilogueCallback(EpilogueCallbackAlloc);
19192}
19193
19194
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019195THREADED_TEST(TwoByteStringInOneByteCons) {
Steve Block8defd9f2010-07-08 12:39:36 +010019196 // See Chromium issue 47824.
Steve Block8defd9f2010-07-08 12:39:36 +010019197 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019198 v8::HandleScope scope(context->GetIsolate());
19199
Steve Block8defd9f2010-07-08 12:39:36 +010019200 const char* init_code =
19201 "var str1 = 'abelspendabel';"
19202 "var str2 = str1 + str1 + str1;"
19203 "str2;";
19204 Local<Value> result = CompileRun(init_code);
19205
Ben Murdoch69a99ed2011-11-30 16:03:39 +000019206 Local<Value> indexof = CompileRun("str2.indexOf('els')");
19207 Local<Value> lastindexof = CompileRun("str2.lastIndexOf('dab')");
19208
Steve Block8defd9f2010-07-08 12:39:36 +010019209 CHECK(result->IsString());
19210 i::Handle<i::String> string = v8::Utils::OpenHandle(String::Cast(*result));
19211 int length = string->length();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019212 CHECK(string->IsOneByteRepresentation());
Steve Block8defd9f2010-07-08 12:39:36 +010019213
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019214 i::Handle<i::String> flat_string = i::String::Flatten(string);
Steve Block8defd9f2010-07-08 12:39:36 +010019215
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019216 CHECK(string->IsOneByteRepresentation());
19217 CHECK(flat_string->IsOneByteRepresentation());
Steve Block8defd9f2010-07-08 12:39:36 +010019218
19219 // Create external resource.
19220 uint16_t* uc16_buffer = new uint16_t[length + 1];
19221
19222 i::String::WriteToFlat(*flat_string, uc16_buffer, 0, length);
19223 uc16_buffer[length] = 0;
19224
19225 TestResource resource(uc16_buffer);
19226
19227 flat_string->MakeExternal(&resource);
19228
19229 CHECK(flat_string->IsTwoByteRepresentation());
19230
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019231 // If the cons string has been short-circuited, skip the following checks.
19232 if (!string.is_identical_to(flat_string)) {
19233 // At this point, we should have a Cons string which is flat and one-byte,
19234 // with a first half that is a two-byte string (although it only contains
19235 // one-byte characters). This is a valid sequence of steps, and it can
19236 // happen in real pages.
19237 CHECK(string->IsOneByteRepresentation());
19238 i::ConsString* cons = i::ConsString::cast(*string);
19239 CHECK_EQ(0, cons->second()->length());
19240 CHECK(cons->first()->IsTwoByteRepresentation());
19241 }
Steve Block8defd9f2010-07-08 12:39:36 +010019242
19243 // Check that some string operations work.
19244
19245 // Atom RegExp.
19246 Local<Value> reresult = CompileRun("str2.match(/abel/g).length;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019247 CHECK_EQ(6, reresult->Int32Value(context.local()).FromJust());
Steve Block8defd9f2010-07-08 12:39:36 +010019248
19249 // Nonatom RegExp.
19250 reresult = CompileRun("str2.match(/abe./g).length;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019251 CHECK_EQ(6, reresult->Int32Value(context.local()).FromJust());
Steve Block8defd9f2010-07-08 12:39:36 +010019252
19253 reresult = CompileRun("str2.search(/bel/g);");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019254 CHECK_EQ(1, reresult->Int32Value(context.local()).FromJust());
Steve Block8defd9f2010-07-08 12:39:36 +010019255
19256 reresult = CompileRun("str2.search(/be./g);");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019257 CHECK_EQ(1, reresult->Int32Value(context.local()).FromJust());
Steve Block8defd9f2010-07-08 12:39:36 +010019258
19259 ExpectTrue("/bel/g.test(str2);");
19260
19261 ExpectTrue("/be./g.test(str2);");
19262
19263 reresult = CompileRun("/bel/g.exec(str2);");
19264 CHECK(!reresult->IsNull());
19265
19266 reresult = CompileRun("/be./g.exec(str2);");
19267 CHECK(!reresult->IsNull());
19268
19269 ExpectString("str2.substring(2, 10);", "elspenda");
19270
19271 ExpectString("str2.substring(2, 20);", "elspendabelabelspe");
19272
19273 ExpectString("str2.charAt(2);", "e");
19274
Ben Murdoch69a99ed2011-11-30 16:03:39 +000019275 ExpectObject("str2.indexOf('els');", indexof);
19276
19277 ExpectObject("str2.lastIndexOf('dab');", lastindexof);
19278
Steve Block8defd9f2010-07-08 12:39:36 +010019279 reresult = CompileRun("str2.charCodeAt(2);");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019280 CHECK_EQ(static_cast<int32_t>('e'),
19281 reresult->Int32Value(context.local()).FromJust());
Steve Block8defd9f2010-07-08 12:39:36 +010019282}
Iain Merrick75681382010-08-19 15:07:18 +010019283
19284
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019285TEST(ContainsOnlyOneByte) {
19286 v8::V8::Initialize();
19287 v8::Isolate* isolate = CcTest::isolate();
19288 v8::HandleScope scope(isolate);
19289 // Make a buffer long enough that it won't automatically be converted.
19290 const int length = 512;
19291 // Ensure word aligned assignment.
19292 const int aligned_length = length*sizeof(uintptr_t)/sizeof(uint16_t);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019293 v8::base::SmartArrayPointer<uintptr_t> aligned_contents(
19294 new uintptr_t[aligned_length]);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019295 uint16_t* string_contents =
19296 reinterpret_cast<uint16_t*>(aligned_contents.get());
19297 // Set to contain only one byte.
19298 for (int i = 0; i < length-1; i++) {
19299 string_contents[i] = 0x41;
19300 }
19301 string_contents[length-1] = 0;
19302 // Simple case.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019303 Local<String> string =
19304 String::NewExternalTwoByte(isolate,
19305 new TestResource(string_contents, NULL, false))
19306 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019307 CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
19308 // Counter example.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019309 string = String::NewFromTwoByte(isolate, string_contents,
19310 v8::NewStringType::kNormal)
19311 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019312 CHECK(string->IsOneByte() && string->ContainsOnlyOneByte());
19313 // Test left right and balanced cons strings.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019314 Local<String> base = v8_str("a");
19315 Local<String> left = base;
19316 Local<String> right = base;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019317 for (int i = 0; i < 1000; i++) {
19318 left = String::Concat(base, left);
19319 right = String::Concat(right, base);
19320 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019321 Local<String> balanced = String::Concat(left, base);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019322 balanced = String::Concat(balanced, right);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019323 Local<String> cons_strings[] = {left, balanced, right};
19324 Local<String> two_byte =
19325 String::NewExternalTwoByte(isolate,
19326 new TestResource(string_contents, NULL, false))
19327 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019328 USE(two_byte); USE(cons_strings);
19329 for (size_t i = 0; i < arraysize(cons_strings); i++) {
19330 // Base assumptions.
19331 string = cons_strings[i];
19332 CHECK(string->IsOneByte() && string->ContainsOnlyOneByte());
19333 // Test left and right concatentation.
19334 string = String::Concat(two_byte, cons_strings[i]);
19335 CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
19336 string = String::Concat(cons_strings[i], two_byte);
19337 CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
19338 }
19339 // Set bits in different positions
19340 // for strings of different lengths and alignments.
19341 for (int alignment = 0; alignment < 7; alignment++) {
19342 for (int size = 2; alignment + size < length; size *= 2) {
19343 int zero_offset = size + alignment;
19344 string_contents[zero_offset] = 0;
19345 for (int i = 0; i < size; i++) {
19346 int shift = 8 + (i % 7);
19347 string_contents[alignment + i] = 1 << shift;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019348 string = String::NewExternalTwoByte(
19349 isolate,
19350 new TestResource(string_contents + alignment, NULL, false))
19351 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019352 CHECK_EQ(size, string->Length());
19353 CHECK(!string->ContainsOnlyOneByte());
19354 string_contents[alignment + i] = 0x41;
19355 }
19356 string_contents[zero_offset] = 0x41;
19357 }
19358 }
19359}
19360
19361
Iain Merrick75681382010-08-19 15:07:18 +010019362// Failed access check callback that performs a GC on each invocation.
19363void FailedAccessCheckCallbackGC(Local<v8::Object> target,
19364 v8::AccessType type,
19365 Local<v8::Value> data) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019366 CcTest::heap()->CollectAllGarbage();
19367 CcTest::isolate()->ThrowException(
19368 v8::Exception::Error(v8_str("cross context")));
Iain Merrick75681382010-08-19 15:07:18 +010019369}
19370
19371
19372TEST(GCInFailedAccessCheckCallback) {
19373 // Install a failed access check callback that performs a GC on each
19374 // invocation. Then force the callback to be called from va
19375
19376 v8::V8::Initialize();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019377 v8::Isolate* isolate = CcTest::isolate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019378
19379 isolate->SetFailedAccessCheckCallbackFunction(&FailedAccessCheckCallbackGC);
19380
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019381 v8::HandleScope scope(isolate);
Iain Merrick75681382010-08-19 15:07:18 +010019382
19383 // Create an ObjectTemplate for global objects and install access
19384 // check callbacks that will block access.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019385 v8::Local<v8::ObjectTemplate> global_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019386 v8::ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019387 global_template->SetAccessCheckCallback(AccessAlwaysBlocked);
Iain Merrick75681382010-08-19 15:07:18 +010019388
19389 // Create a context and set an x property on it's global object.
19390 LocalContext context0(NULL, global_template);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019391 CHECK(context0->Global()
19392 ->Set(context0.local(), v8_str("x"), v8_num(42))
19393 .FromJust());
19394 v8::Local<v8::Object> global0 = context0->Global();
Iain Merrick75681382010-08-19 15:07:18 +010019395
19396 // Create a context with a different security token so that the
19397 // failed access check callback will be called on each access.
19398 LocalContext context1(NULL, global_template);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019399 CHECK(context1->Global()
19400 ->Set(context1.local(), v8_str("other"), global0)
19401 .FromJust());
19402
19403 v8::TryCatch try_catch(isolate);
Iain Merrick75681382010-08-19 15:07:18 +010019404
19405 // Get property with failed access check.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019406 CHECK(CompileRun("other.x").IsEmpty());
19407 CHECK(try_catch.HasCaught());
19408 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010019409
19410 // Get element with failed access check.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019411 CHECK(CompileRun("other[0]").IsEmpty());
19412 CHECK(try_catch.HasCaught());
19413 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010019414
19415 // Set property with failed access check.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019416 CHECK(CompileRun("other.x = new Object()").IsEmpty());
19417 CHECK(try_catch.HasCaught());
19418 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010019419
19420 // Set element with failed access check.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019421 CHECK(CompileRun("other[0] = new Object()").IsEmpty());
19422 CHECK(try_catch.HasCaught());
19423 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010019424
19425 // Get property attribute with failed access check.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019426 CHECK(CompileRun("\'x\' in other").IsEmpty());
19427 CHECK(try_catch.HasCaught());
19428 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010019429
19430 // Get property attribute for element with failed access check.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019431 CHECK(CompileRun("0 in other").IsEmpty());
19432 CHECK(try_catch.HasCaught());
19433 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010019434
19435 // Delete property.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019436 CHECK(CompileRun("delete other.x").IsEmpty());
19437 CHECK(try_catch.HasCaught());
19438 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010019439
19440 // Delete element.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019441 CHECK(global0->Delete(context1.local(), 0).IsNothing());
19442 CHECK(try_catch.HasCaught());
19443 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010019444
19445 // DefineAccessor.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019446 CHECK(global0->SetAccessor(context1.local(), v8_str("x"), GetXValue, NULL,
19447 v8_str("x"))
19448 .IsNothing());
19449 CHECK(try_catch.HasCaught());
19450 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010019451
19452 // Define JavaScript accessor.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019453 CHECK(CompileRun(
19454 "Object.prototype.__defineGetter__.call("
19455 " other, \'x\', function() { return 42; })").IsEmpty());
19456 CHECK(try_catch.HasCaught());
19457 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010019458
19459 // LookupAccessor.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019460 CHECK(CompileRun(
19461 "Object.prototype.__lookupGetter__.call("
19462 " other, \'x\')").IsEmpty());
19463 CHECK(try_catch.HasCaught());
19464 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010019465
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019466 // HasOwnElement.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019467 CHECK(CompileRun(
19468 "Object.prototype.hasOwnProperty.call("
19469 "other, \'0\')").IsEmpty());
19470 CHECK(try_catch.HasCaught());
19471 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010019472
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019473 CHECK(global0->HasRealIndexedProperty(context1.local(), 0).IsNothing());
19474 CHECK(try_catch.HasCaught());
19475 try_catch.Reset();
19476
19477 CHECK(
19478 global0->HasRealNamedProperty(context1.local(), v8_str("x")).IsNothing());
19479 CHECK(try_catch.HasCaught());
19480 try_catch.Reset();
19481
19482 CHECK(global0->HasRealNamedCallbackProperty(context1.local(), v8_str("x"))
19483 .IsNothing());
19484 CHECK(try_catch.HasCaught());
19485 try_catch.Reset();
Iain Merrick75681382010-08-19 15:07:18 +010019486
19487 // Reset the failed access check callback so it does not influence
19488 // the other tests.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019489 isolate->SetFailedAccessCheckCallbackFunction(NULL);
Iain Merrick75681382010-08-19 15:07:18 +010019490}
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019491
Steve Block44f0eee2011-05-26 01:26:41 +010019492
19493TEST(IsolateNewDispose) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019494 v8::Isolate* current_isolate = CcTest::isolate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019495 v8::Isolate::CreateParams create_params;
19496 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
19497 v8::Isolate* isolate = v8::Isolate::New(create_params);
Steve Block44f0eee2011-05-26 01:26:41 +010019498 CHECK(isolate != NULL);
Steve Block44f0eee2011-05-26 01:26:41 +010019499 CHECK(current_isolate != isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019500 CHECK(current_isolate == CcTest::isolate());
Steve Block44f0eee2011-05-26 01:26:41 +010019501
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019502 isolate->SetFatalErrorHandler(StoringErrorCallback);
Steve Block44f0eee2011-05-26 01:26:41 +010019503 last_location = last_message = NULL;
19504 isolate->Dispose();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019505 CHECK(!last_location);
19506 CHECK(!last_message);
Steve Block44f0eee2011-05-26 01:26:41 +010019507}
19508
Steve Block44f0eee2011-05-26 01:26:41 +010019509
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019510UNINITIALIZED_TEST(DisposeIsolateWhenInUse) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019511 v8::Isolate::CreateParams create_params;
19512 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
19513 v8::Isolate* isolate = v8::Isolate::New(create_params);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019514 {
19515 v8::Isolate::Scope i_scope(isolate);
19516 v8::HandleScope scope(isolate);
19517 LocalContext context(isolate);
19518 // Run something in this isolate.
19519 ExpectTrue("true");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019520 isolate->SetFatalErrorHandler(StoringErrorCallback);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019521 last_location = last_message = NULL;
19522 // Still entered, should fail.
19523 isolate->Dispose();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019524 CHECK(last_location);
19525 CHECK(last_message);
Steve Block44f0eee2011-05-26 01:26:41 +010019526 }
Steve Block44f0eee2011-05-26 01:26:41 +010019527 isolate->Dispose();
Steve Block44f0eee2011-05-26 01:26:41 +010019528}
19529
Steve Block44f0eee2011-05-26 01:26:41 +010019530
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019531static void BreakArrayGuarantees(const char* script) {
19532 v8::Isolate::CreateParams create_params;
19533 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
19534 v8::Isolate* isolate1 = v8::Isolate::New(create_params);
19535 isolate1->Enter();
19536 v8::Persistent<v8::Context> context1;
19537 {
19538 v8::HandleScope scope(isolate1);
19539 context1.Reset(isolate1, Context::New(isolate1));
19540 }
19541
19542 {
19543 v8::HandleScope scope(isolate1);
19544 v8::Local<v8::Context> context =
19545 v8::Local<v8::Context>::New(isolate1, context1);
19546 v8::Context::Scope context_scope(context);
19547 v8::internal::Isolate* i_isolate =
19548 reinterpret_cast<v8::internal::Isolate*>(isolate1);
19549 CHECK_EQ(true, i_isolate->IsFastArrayConstructorPrototypeChainIntact());
19550 // Run something in new isolate.
19551 CompileRun(script);
19552 CHECK_EQ(false, i_isolate->IsFastArrayConstructorPrototypeChainIntact());
19553 }
19554 isolate1->Exit();
19555 isolate1->Dispose();
19556}
19557
19558
19559TEST(VerifyArrayPrototypeGuarantees) {
19560 // Break fast array hole handling by element changes.
19561 BreakArrayGuarantees("[].__proto__[1] = 3;");
19562 BreakArrayGuarantees("Object.prototype[3] = 'three';");
19563 BreakArrayGuarantees("Array.prototype.push(1);");
19564 BreakArrayGuarantees("Array.prototype.unshift(1);");
19565 // Break fast array hole handling by changing length.
19566 BreakArrayGuarantees("Array.prototype.length = 30;");
19567 // Break fast array hole handling by prototype structure changes.
19568 BreakArrayGuarantees("[].__proto__.__proto__ = { funny: true };");
19569 // By sending elements to dictionary mode.
19570 BreakArrayGuarantees(
19571 "Object.defineProperty(Array.prototype, 0, {"
19572 " get: function() { return 3; }});");
19573 BreakArrayGuarantees(
19574 "Object.defineProperty(Object.prototype, 0, {"
19575 " get: function() { return 3; }});");
19576}
19577
19578
Steve Block44f0eee2011-05-26 01:26:41 +010019579TEST(RunTwoIsolatesOnSingleThread) {
19580 // Run isolate 1.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019581 v8::Isolate::CreateParams create_params;
19582 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
19583 v8::Isolate* isolate1 = v8::Isolate::New(create_params);
Steve Block44f0eee2011-05-26 01:26:41 +010019584 isolate1->Enter();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019585 v8::Persistent<v8::Context> context1;
19586 {
19587 v8::HandleScope scope(isolate1);
19588 context1.Reset(isolate1, Context::New(isolate1));
19589 }
Steve Block44f0eee2011-05-26 01:26:41 +010019590
19591 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019592 v8::HandleScope scope(isolate1);
19593 v8::Local<v8::Context> context =
19594 v8::Local<v8::Context>::New(isolate1, context1);
19595 v8::Context::Scope context_scope(context);
Steve Block44f0eee2011-05-26 01:26:41 +010019596 // Run something in new isolate.
19597 CompileRun("var foo = 'isolate 1';");
19598 ExpectString("function f() { return foo; }; f()", "isolate 1");
19599 }
19600
19601 // Run isolate 2.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019602 v8::Isolate* isolate2 = v8::Isolate::New(create_params);
Steve Block44f0eee2011-05-26 01:26:41 +010019603 v8::Persistent<v8::Context> context2;
19604
19605 {
19606 v8::Isolate::Scope iscope(isolate2);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019607 v8::HandleScope scope(isolate2);
19608 context2.Reset(isolate2, Context::New(isolate2));
19609 v8::Local<v8::Context> context =
19610 v8::Local<v8::Context>::New(isolate2, context2);
19611 v8::Context::Scope context_scope(context);
Steve Block44f0eee2011-05-26 01:26:41 +010019612
19613 // Run something in new isolate.
19614 CompileRun("var foo = 'isolate 2';");
19615 ExpectString("function f() { return foo; }; f()", "isolate 2");
19616 }
19617
19618 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019619 v8::HandleScope scope(isolate1);
19620 v8::Local<v8::Context> context =
19621 v8::Local<v8::Context>::New(isolate1, context1);
19622 v8::Context::Scope context_scope(context);
Steve Block44f0eee2011-05-26 01:26:41 +010019623 // Now again in isolate 1
19624 ExpectString("function f() { return foo; }; f()", "isolate 1");
19625 }
19626
19627 isolate1->Exit();
19628
19629 // Run some stuff in default isolate.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019630 v8::Persistent<v8::Context> context_default;
19631 {
19632 v8::Isolate* isolate = CcTest::isolate();
19633 v8::Isolate::Scope iscope(isolate);
19634 v8::HandleScope scope(isolate);
19635 context_default.Reset(isolate, Context::New(isolate));
19636 }
Steve Block44f0eee2011-05-26 01:26:41 +010019637
19638 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019639 v8::HandleScope scope(CcTest::isolate());
19640 v8::Local<v8::Context> context =
19641 v8::Local<v8::Context>::New(CcTest::isolate(), context_default);
19642 v8::Context::Scope context_scope(context);
Steve Block44f0eee2011-05-26 01:26:41 +010019643 // Variables in other isolates should be not available, verify there
19644 // is an exception.
19645 ExpectTrue("function f() {"
19646 " try {"
19647 " foo;"
19648 " return false;"
19649 " } catch(e) {"
19650 " return true;"
19651 " }"
19652 "};"
19653 "var isDefaultIsolate = true;"
19654 "f()");
19655 }
19656
19657 isolate1->Enter();
19658
19659 {
19660 v8::Isolate::Scope iscope(isolate2);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019661 v8::HandleScope scope(isolate2);
19662 v8::Local<v8::Context> context =
19663 v8::Local<v8::Context>::New(isolate2, context2);
19664 v8::Context::Scope context_scope(context);
Steve Block44f0eee2011-05-26 01:26:41 +010019665 ExpectString("function f() { return foo; }; f()", "isolate 2");
19666 }
19667
19668 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019669 v8::HandleScope scope(v8::Isolate::GetCurrent());
19670 v8::Local<v8::Context> context =
19671 v8::Local<v8::Context>::New(v8::Isolate::GetCurrent(), context1);
19672 v8::Context::Scope context_scope(context);
Steve Block44f0eee2011-05-26 01:26:41 +010019673 ExpectString("function f() { return foo; }; f()", "isolate 1");
19674 }
19675
19676 {
19677 v8::Isolate::Scope iscope(isolate2);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019678 context2.Reset();
Steve Block44f0eee2011-05-26 01:26:41 +010019679 }
19680
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019681 context1.Reset();
Steve Block44f0eee2011-05-26 01:26:41 +010019682 isolate1->Exit();
19683
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019684 isolate2->SetFatalErrorHandler(StoringErrorCallback);
Steve Block44f0eee2011-05-26 01:26:41 +010019685 last_location = last_message = NULL;
19686
19687 isolate1->Dispose();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019688 CHECK(!last_location);
19689 CHECK(!last_message);
Steve Block44f0eee2011-05-26 01:26:41 +010019690
19691 isolate2->Dispose();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019692 CHECK(!last_location);
19693 CHECK(!last_message);
Steve Block44f0eee2011-05-26 01:26:41 +010019694
19695 // Check that default isolate still runs.
19696 {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019697 v8::HandleScope scope(CcTest::isolate());
19698 v8::Local<v8::Context> context =
19699 v8::Local<v8::Context>::New(CcTest::isolate(), context_default);
19700 v8::Context::Scope context_scope(context);
Steve Block44f0eee2011-05-26 01:26:41 +010019701 ExpectTrue("function f() { return isDefaultIsolate; }; f()");
19702 }
19703}
19704
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019705
Steve Block44f0eee2011-05-26 01:26:41 +010019706static int CalcFibonacci(v8::Isolate* isolate, int limit) {
19707 v8::Isolate::Scope isolate_scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019708 v8::HandleScope scope(isolate);
19709 LocalContext context(isolate);
Steve Block44f0eee2011-05-26 01:26:41 +010019710 i::ScopedVector<char> code(1024);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019711 i::SNPrintF(code, "function fib(n) {"
19712 " if (n <= 2) return 1;"
19713 " return fib(n-1) + fib(n-2);"
19714 "}"
19715 "fib(%d)", limit);
Steve Block44f0eee2011-05-26 01:26:41 +010019716 Local<Value> value = CompileRun(code.start());
19717 CHECK(value->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019718 return static_cast<int>(value->NumberValue(context.local()).FromJust());
Steve Block44f0eee2011-05-26 01:26:41 +010019719}
19720
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019721class IsolateThread : public v8::base::Thread {
Steve Block44f0eee2011-05-26 01:26:41 +010019722 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019723 explicit IsolateThread(int fib_limit)
19724 : Thread(Options("IsolateThread")), fib_limit_(fib_limit), result_(0) {}
Steve Block44f0eee2011-05-26 01:26:41 +010019725
19726 void Run() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019727 v8::Isolate::CreateParams create_params;
19728 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
19729 v8::Isolate* isolate = v8::Isolate::New(create_params);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019730 result_ = CalcFibonacci(isolate, fib_limit_);
19731 isolate->Dispose();
Steve Block44f0eee2011-05-26 01:26:41 +010019732 }
19733
19734 int result() { return result_; }
19735
19736 private:
Steve Block44f0eee2011-05-26 01:26:41 +010019737 int fib_limit_;
19738 int result_;
19739};
19740
Steve Block44f0eee2011-05-26 01:26:41 +010019741
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019742TEST(MultipleIsolatesOnIndividualThreads) {
19743 IsolateThread thread1(21);
19744 IsolateThread thread2(12);
Steve Block44f0eee2011-05-26 01:26:41 +010019745
19746 // Compute some fibonacci numbers on 3 threads in 3 isolates.
19747 thread1.Start();
19748 thread2.Start();
19749
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019750 int result1 = CalcFibonacci(CcTest::isolate(), 21);
19751 int result2 = CalcFibonacci(CcTest::isolate(), 12);
Steve Block44f0eee2011-05-26 01:26:41 +010019752
19753 thread1.Join();
19754 thread2.Join();
19755
19756 // Compare results. The actual fibonacci numbers for 12 and 21 are taken
19757 // (I'm lazy!) from http://en.wikipedia.org/wiki/Fibonacci_number
19758 CHECK_EQ(result1, 10946);
19759 CHECK_EQ(result2, 144);
19760 CHECK_EQ(result1, thread1.result());
19761 CHECK_EQ(result2, thread2.result());
Steve Block44f0eee2011-05-26 01:26:41 +010019762}
19763
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019764
Ben Murdoch257744e2011-11-30 15:57:28 +000019765TEST(IsolateDifferentContexts) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019766 v8::Isolate::CreateParams create_params;
19767 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
19768 v8::Isolate* isolate = v8::Isolate::New(create_params);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019769 Local<v8::Context> context;
Ben Murdoch257744e2011-11-30 15:57:28 +000019770 {
19771 v8::Isolate::Scope isolate_scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019772 v8::HandleScope handle_scope(isolate);
19773 context = v8::Context::New(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000019774 v8::Context::Scope context_scope(context);
19775 Local<Value> v = CompileRun("2");
19776 CHECK(v->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019777 CHECK_EQ(2, static_cast<int>(v->NumberValue(context).FromJust()));
Ben Murdoch257744e2011-11-30 15:57:28 +000019778 }
19779 {
19780 v8::Isolate::Scope isolate_scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019781 v8::HandleScope handle_scope(isolate);
19782 context = v8::Context::New(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000019783 v8::Context::Scope context_scope(context);
19784 Local<Value> v = CompileRun("22");
19785 CHECK(v->IsNumber());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019786 CHECK_EQ(22, static_cast<int>(v->NumberValue(context).FromJust()));
Ben Murdoch257744e2011-11-30 15:57:28 +000019787 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019788 isolate->Dispose();
Ben Murdoch257744e2011-11-30 15:57:28 +000019789}
Steve Block44f0eee2011-05-26 01:26:41 +010019790
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019791class InitDefaultIsolateThread : public v8::base::Thread {
Steve Block44f0eee2011-05-26 01:26:41 +010019792 public:
19793 enum TestCase {
Steve Block44f0eee2011-05-26 01:26:41 +010019794 SetResourceConstraints,
19795 SetFatalHandler,
19796 SetCounterFunction,
19797 SetCreateHistogramFunction,
19798 SetAddHistogramSampleFunction
19799 };
19800
19801 explicit InitDefaultIsolateThread(TestCase testCase)
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019802 : Thread(Options("InitDefaultIsolateThread")),
Steve Block44f0eee2011-05-26 01:26:41 +010019803 testCase_(testCase),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019804 result_(false) {}
Steve Block44f0eee2011-05-26 01:26:41 +010019805
19806 void Run() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019807 v8::Isolate::CreateParams create_params;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019808 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
19809 const intptr_t pageSizeMult =
19810 v8::internal::Page::kPageSize / v8::internal::MB;
Steve Block44f0eee2011-05-26 01:26:41 +010019811 switch (testCase_) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019812 case SetResourceConstraints: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019813 create_params.constraints.set_max_semi_space_size(1 * pageSizeMult);
19814 create_params.constraints.set_max_old_space_size(4 * pageSizeMult);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019815 break;
19816 }
19817 default:
19818 break;
Steve Block44f0eee2011-05-26 01:26:41 +010019819 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019820 v8::Isolate* isolate = v8::Isolate::New(create_params);
19821 isolate->Enter();
19822 switch (testCase_) {
19823 case SetResourceConstraints:
19824 // Already handled in pre-Isolate-creation block.
19825 break;
Steve Block44f0eee2011-05-26 01:26:41 +010019826
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019827 case SetFatalHandler:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019828 isolate->SetFatalErrorHandler(NULL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019829 break;
Steve Block44f0eee2011-05-26 01:26:41 +010019830
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019831 case SetCounterFunction:
19832 CcTest::isolate()->SetCounterFunction(NULL);
19833 break;
Steve Block44f0eee2011-05-26 01:26:41 +010019834
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019835 case SetCreateHistogramFunction:
19836 CcTest::isolate()->SetCreateHistogramFunction(NULL);
19837 break;
Steve Block44f0eee2011-05-26 01:26:41 +010019838
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019839 case SetAddHistogramSampleFunction:
19840 CcTest::isolate()->SetAddHistogramSampleFunction(NULL);
19841 break;
Steve Block44f0eee2011-05-26 01:26:41 +010019842 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019843 isolate->Exit();
19844 isolate->Dispose();
Steve Block44f0eee2011-05-26 01:26:41 +010019845 result_ = true;
19846 }
19847
19848 bool result() { return result_; }
19849
19850 private:
19851 TestCase testCase_;
19852 bool result_;
19853};
19854
19855
19856static void InitializeTestHelper(InitDefaultIsolateThread::TestCase testCase) {
19857 InitDefaultIsolateThread thread(testCase);
19858 thread.Start();
19859 thread.Join();
19860 CHECK_EQ(thread.result(), true);
19861}
19862
Steve Block44f0eee2011-05-26 01:26:41 +010019863
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019864TEST(InitializeDefaultIsolateOnSecondaryThread1) {
Steve Block44f0eee2011-05-26 01:26:41 +010019865 InitializeTestHelper(InitDefaultIsolateThread::SetResourceConstraints);
19866}
19867
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019868
19869TEST(InitializeDefaultIsolateOnSecondaryThread2) {
Steve Block44f0eee2011-05-26 01:26:41 +010019870 InitializeTestHelper(InitDefaultIsolateThread::SetFatalHandler);
19871}
19872
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019873
19874TEST(InitializeDefaultIsolateOnSecondaryThread3) {
Steve Block44f0eee2011-05-26 01:26:41 +010019875 InitializeTestHelper(InitDefaultIsolateThread::SetCounterFunction);
19876}
19877
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019878
19879TEST(InitializeDefaultIsolateOnSecondaryThread4) {
Steve Block44f0eee2011-05-26 01:26:41 +010019880 InitializeTestHelper(InitDefaultIsolateThread::SetCreateHistogramFunction);
19881}
19882
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019883
19884TEST(InitializeDefaultIsolateOnSecondaryThread5) {
Steve Block44f0eee2011-05-26 01:26:41 +010019885 InitializeTestHelper(InitDefaultIsolateThread::SetAddHistogramSampleFunction);
19886}
19887
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019888
19889TEST(StringCheckMultipleContexts) {
19890 const char* code =
19891 "(function() { return \"a\".charAt(0); })()";
19892
19893 {
19894 // Run the code twice in the first context to initialize the call IC.
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019895 LocalContext context1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019896 v8::HandleScope scope(context1->GetIsolate());
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019897 ExpectString(code, "a");
19898 ExpectString(code, "a");
19899 }
19900
19901 {
19902 // Change the String.prototype in the second context and check
19903 // that the right function gets called.
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019904 LocalContext context2;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019905 v8::HandleScope scope(context2->GetIsolate());
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019906 CompileRun("String.prototype.charAt = function() { return \"not a\"; }");
19907 ExpectString(code, "not a");
19908 }
19909}
19910
19911
19912TEST(NumberCheckMultipleContexts) {
19913 const char* code =
19914 "(function() { return (42).toString(); })()";
19915
19916 {
19917 // Run the code twice in the first context to initialize the call IC.
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019918 LocalContext context1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019919 v8::HandleScope scope(context1->GetIsolate());
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019920 ExpectString(code, "42");
19921 ExpectString(code, "42");
19922 }
19923
19924 {
19925 // Change the Number.prototype in the second context and check
19926 // that the right function gets called.
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019927 LocalContext context2;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019928 v8::HandleScope scope(context2->GetIsolate());
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019929 CompileRun("Number.prototype.toString = function() { return \"not 42\"; }");
19930 ExpectString(code, "not 42");
19931 }
19932}
19933
19934
19935TEST(BooleanCheckMultipleContexts) {
19936 const char* code =
19937 "(function() { return true.toString(); })()";
19938
19939 {
19940 // Run the code twice in the first context to initialize the call IC.
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019941 LocalContext context1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019942 v8::HandleScope scope(context1->GetIsolate());
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019943 ExpectString(code, "true");
19944 ExpectString(code, "true");
19945 }
19946
19947 {
19948 // Change the Boolean.prototype in the second context and check
19949 // that the right function gets called.
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019950 LocalContext context2;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019951 v8::HandleScope scope(context2->GetIsolate());
Kristian Monsen0d5e1162010-09-30 15:31:59 +010019952 CompileRun("Boolean.prototype.toString = function() { return \"\"; }");
19953 ExpectString(code, "");
19954 }
19955}
Ben Murdochf87a2032010-10-22 12:50:53 +010019956
19957
19958TEST(DontDeleteCellLoadIC) {
19959 const char* function_code =
19960 "function readCell() { while (true) { return cell; } }";
19961
19962 {
19963 // Run the code twice in the first context to initialize the load
19964 // IC for a don't delete cell.
Ben Murdochf87a2032010-10-22 12:50:53 +010019965 LocalContext context1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019966 v8::HandleScope scope(context1->GetIsolate());
Ben Murdochf87a2032010-10-22 12:50:53 +010019967 CompileRun("var cell = \"first\";");
19968 ExpectBoolean("delete cell", false);
19969 CompileRun(function_code);
19970 ExpectString("readCell()", "first");
19971 ExpectString("readCell()", "first");
19972 }
19973
19974 {
19975 // Use a deletable cell in the second context.
Ben Murdochf87a2032010-10-22 12:50:53 +010019976 LocalContext context2;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019977 v8::HandleScope scope(context2->GetIsolate());
Ben Murdochf87a2032010-10-22 12:50:53 +010019978 CompileRun("cell = \"second\";");
19979 CompileRun(function_code);
19980 ExpectString("readCell()", "second");
19981 ExpectBoolean("delete cell", true);
19982 ExpectString("(function() {"
19983 " try {"
19984 " return readCell();"
19985 " } catch(e) {"
19986 " return e.toString();"
19987 " }"
19988 "})()",
19989 "ReferenceError: cell is not defined");
19990 CompileRun("cell = \"new_second\";");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019991 CcTest::heap()->CollectAllGarbage();
Ben Murdochf87a2032010-10-22 12:50:53 +010019992 ExpectString("readCell()", "new_second");
19993 ExpectString("readCell()", "new_second");
19994 }
19995}
19996
19997
Ben Murdochb8a8cc12014-11-26 15:28:44 +000019998class Visitor42 : public v8::PersistentHandleVisitor {
19999 public:
20000 explicit Visitor42(v8::Persistent<v8::Object>* object)
20001 : counter_(0), object_(object) { }
20002
20003 virtual void VisitPersistentHandle(Persistent<Value>* value,
20004 uint16_t class_id) {
20005 if (class_id != 42) return;
20006 CHECK_EQ(42, value->WrapperClassId());
20007 v8::Isolate* isolate = CcTest::isolate();
20008 v8::HandleScope handle_scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020009 v8::Local<v8::Value> handle = v8::Local<v8::Value>::New(isolate, *value);
20010 v8::Local<v8::Value> object = v8::Local<v8::Object>::New(isolate, *object_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020011 CHECK(handle->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020012 CHECK(Local<Object>::Cast(handle)
20013 ->Equals(isolate->GetCurrentContext(), object)
20014 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020015 ++counter_;
20016 }
20017
20018 int counter_;
20019 v8::Persistent<v8::Object>* object_;
20020};
20021
20022
20023TEST(PersistentHandleVisitor) {
Ben Murdochf87a2032010-10-22 12:50:53 +010020024 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020025 v8::Isolate* isolate = context->GetIsolate();
20026 v8::HandleScope scope(isolate);
20027 v8::Persistent<v8::Object> object(isolate, v8::Object::New(isolate));
20028 CHECK_EQ(0, object.WrapperClassId());
20029 object.SetWrapperClassId(42);
20030 CHECK_EQ(42, object.WrapperClassId());
20031
20032 Visitor42 visitor(&object);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020033 isolate->VisitHandlesWithClassIds(&visitor);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020034 CHECK_EQ(1, visitor.counter_);
20035
20036 object.Reset();
20037}
20038
20039
20040TEST(WrapperClassId) {
20041 LocalContext context;
20042 v8::Isolate* isolate = context->GetIsolate();
20043 v8::HandleScope scope(isolate);
20044 v8::Persistent<v8::Object> object(isolate, v8::Object::New(isolate));
20045 CHECK_EQ(0, object.WrapperClassId());
20046 object.SetWrapperClassId(65535);
20047 CHECK_EQ(65535, object.WrapperClassId());
20048 object.Reset();
20049}
20050
20051
20052TEST(PersistentHandleInNewSpaceVisitor) {
20053 LocalContext context;
20054 v8::Isolate* isolate = context->GetIsolate();
20055 v8::HandleScope scope(isolate);
20056 v8::Persistent<v8::Object> object1(isolate, v8::Object::New(isolate));
20057 CHECK_EQ(0, object1.WrapperClassId());
20058 object1.SetWrapperClassId(42);
20059 CHECK_EQ(42, object1.WrapperClassId());
20060
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020061 CcTest::heap()->CollectAllGarbage();
20062 CcTest::heap()->CollectAllGarbage();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020063
20064 v8::Persistent<v8::Object> object2(isolate, v8::Object::New(isolate));
20065 CHECK_EQ(0, object2.WrapperClassId());
20066 object2.SetWrapperClassId(42);
20067 CHECK_EQ(42, object2.WrapperClassId());
20068
20069 Visitor42 visitor(&object2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020070 isolate->VisitHandlesForPartialDependence(&visitor);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020071 CHECK_EQ(1, visitor.counter_);
20072
20073 object1.Reset();
20074 object2.Reset();
20075}
20076
20077
20078TEST(RegExp) {
20079 LocalContext context;
20080 v8::HandleScope scope(context->GetIsolate());
Ben Murdochf87a2032010-10-22 12:50:53 +010020081
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020082 v8::Local<v8::RegExp> re =
20083 v8::RegExp::New(context.local(), v8_str("foo"), v8::RegExp::kNone)
20084 .ToLocalChecked();
Ben Murdochf87a2032010-10-22 12:50:53 +010020085 CHECK(re->IsRegExp());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020086 CHECK(re->GetSource()->Equals(context.local(), v8_str("foo")).FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020087 CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
Ben Murdochf87a2032010-10-22 12:50:53 +010020088
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020089 re = v8::RegExp::New(context.local(), v8_str("bar"),
Ben Murdochf87a2032010-10-22 12:50:53 +010020090 static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020091 v8::RegExp::kGlobal))
20092 .ToLocalChecked();
Ben Murdochf87a2032010-10-22 12:50:53 +010020093 CHECK(re->IsRegExp());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020094 CHECK(re->GetSource()->Equals(context.local(), v8_str("bar")).FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020095 CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kGlobal,
20096 static_cast<int>(re->GetFlags()));
Ben Murdochf87a2032010-10-22 12:50:53 +010020097
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020098 re = v8::RegExp::New(context.local(), v8_str("baz"),
Ben Murdochf87a2032010-10-22 12:50:53 +010020099 static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020100 v8::RegExp::kMultiline))
20101 .ToLocalChecked();
Ben Murdochf87a2032010-10-22 12:50:53 +010020102 CHECK(re->IsRegExp());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020103 CHECK(re->GetSource()->Equals(context.local(), v8_str("baz")).FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020104 CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
20105 static_cast<int>(re->GetFlags()));
Ben Murdochf87a2032010-10-22 12:50:53 +010020106
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020107 re = v8::RegExp::New(context.local(), v8_str("baz"),
20108 static_cast<v8::RegExp::Flags>(v8::RegExp::kUnicode |
20109 v8::RegExp::kSticky))
20110 .ToLocalChecked();
20111 CHECK(re->IsRegExp());
20112 CHECK(re->GetSource()->Equals(context.local(), v8_str("baz")).FromJust());
20113 CHECK_EQ(v8::RegExp::kUnicode | v8::RegExp::kSticky,
20114 static_cast<int>(re->GetFlags()));
20115
Ben Murdochf87a2032010-10-22 12:50:53 +010020116 re = CompileRun("/quux/").As<v8::RegExp>();
20117 CHECK(re->IsRegExp());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020118 CHECK(re->GetSource()->Equals(context.local(), v8_str("quux")).FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020119 CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
Ben Murdochf87a2032010-10-22 12:50:53 +010020120
20121 re = CompileRun("/quux/gm").As<v8::RegExp>();
20122 CHECK(re->IsRegExp());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020123 CHECK(re->GetSource()->Equals(context.local(), v8_str("quux")).FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020124 CHECK_EQ(v8::RegExp::kGlobal | v8::RegExp::kMultiline,
20125 static_cast<int>(re->GetFlags()));
Ben Murdochf87a2032010-10-22 12:50:53 +010020126
20127 // Override the RegExp constructor and check the API constructor
20128 // still works.
20129 CompileRun("RegExp = function() {}");
20130
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020131 re = v8::RegExp::New(context.local(), v8_str("foobar"), v8::RegExp::kNone)
20132 .ToLocalChecked();
Ben Murdochf87a2032010-10-22 12:50:53 +010020133 CHECK(re->IsRegExp());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020134 CHECK(re->GetSource()->Equals(context.local(), v8_str("foobar")).FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020135 CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
Ben Murdochf87a2032010-10-22 12:50:53 +010020136
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020137 re = v8::RegExp::New(context.local(), v8_str("foobarbaz"),
Ben Murdochf87a2032010-10-22 12:50:53 +010020138 static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020139 v8::RegExp::kMultiline))
20140 .ToLocalChecked();
Ben Murdochf87a2032010-10-22 12:50:53 +010020141 CHECK(re->IsRegExp());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020142 CHECK(
20143 re->GetSource()->Equals(context.local(), v8_str("foobarbaz")).FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020144 CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
20145 static_cast<int>(re->GetFlags()));
Ben Murdochf87a2032010-10-22 12:50:53 +010020146
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020147 CHECK(context->Global()->Set(context.local(), v8_str("re"), re).FromJust());
Ben Murdochf87a2032010-10-22 12:50:53 +010020148 ExpectTrue("re.test('FoobarbaZ')");
20149
Ben Murdoch257744e2011-11-30 15:57:28 +000020150 // RegExps are objects on which you can set properties.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020151 re->Set(context.local(), v8_str("property"),
20152 v8::Integer::New(context->GetIsolate(), 32))
20153 .FromJust();
20154 v8::Local<v8::Value> value(CompileRun("re.property"));
20155 CHECK_EQ(32, value->Int32Value(context.local()).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000020156
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020157 v8::TryCatch try_catch(context->GetIsolate());
20158 CHECK(v8::RegExp::New(context.local(), v8_str("foo["), v8::RegExp::kNone)
20159 .IsEmpty());
Ben Murdochf87a2032010-10-22 12:50:53 +010020160 CHECK(try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020161 CHECK(context->Global()
20162 ->Set(context.local(), v8_str("ex"), try_catch.Exception())
20163 .FromJust());
Ben Murdochf87a2032010-10-22 12:50:53 +010020164 ExpectTrue("ex instanceof SyntaxError");
20165}
20166
20167
Steve Block1e0659c2011-05-24 12:43:12 +010020168THREADED_TEST(Equals) {
Steve Block1e0659c2011-05-24 12:43:12 +010020169 LocalContext localContext;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020170 v8::HandleScope handleScope(localContext->GetIsolate());
Steve Block1e0659c2011-05-24 12:43:12 +010020171
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020172 v8::Local<v8::Object> globalProxy = localContext->Global();
20173 v8::Local<Value> global = globalProxy->GetPrototype();
Steve Block1e0659c2011-05-24 12:43:12 +010020174
20175 CHECK(global->StrictEquals(global));
20176 CHECK(!global->StrictEquals(globalProxy));
20177 CHECK(!globalProxy->StrictEquals(global));
20178 CHECK(globalProxy->StrictEquals(globalProxy));
20179
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020180 CHECK(global->Equals(localContext.local(), global).FromJust());
20181 CHECK(!global->Equals(localContext.local(), globalProxy).FromJust());
20182 CHECK(!globalProxy->Equals(localContext.local(), global).FromJust());
20183 CHECK(globalProxy->Equals(localContext.local(), globalProxy).FromJust());
Steve Block1e0659c2011-05-24 12:43:12 +010020184}
20185
20186
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020187static void Getter(v8::Local<v8::Name> property,
20188 const v8::PropertyCallbackInfo<v8::Value>& info) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020189 info.GetReturnValue().Set(v8_str("42!"));
Ben Murdochf87a2032010-10-22 12:50:53 +010020190}
20191
20192
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020193static void Enumerator(const v8::PropertyCallbackInfo<v8::Array>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020194 v8::Local<v8::Array> result = v8::Array::New(info.GetIsolate());
20195 result->Set(info.GetIsolate()->GetCurrentContext(), 0,
20196 v8_str("universalAnswer"))
20197 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020198 info.GetReturnValue().Set(result);
Ben Murdochf87a2032010-10-22 12:50:53 +010020199}
20200
20201
20202TEST(NamedEnumeratorAndForIn) {
Ben Murdochf87a2032010-10-22 12:50:53 +010020203 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020204 v8::Isolate* isolate = context->GetIsolate();
20205 v8::HandleScope handle_scope(isolate);
Ben Murdochf87a2032010-10-22 12:50:53 +010020206 v8::Context::Scope context_scope(context.local());
20207
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020208 v8::Local<v8::ObjectTemplate> tmpl = v8::ObjectTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020209 tmpl->SetHandler(v8::NamedPropertyHandlerConfiguration(Getter, NULL, NULL,
20210 NULL, Enumerator));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020211 CHECK(context->Global()
20212 ->Set(context.local(), v8_str("o"),
20213 tmpl->NewInstance(context.local()).ToLocalChecked())
20214 .FromJust());
20215 v8::Local<v8::Array> result = v8::Local<v8::Array>::Cast(
20216 CompileRun("var result = []; for (var k in o) result.push(k); result"));
20217 CHECK_EQ(1u, result->Length());
20218 CHECK(v8_str("universalAnswer")
20219 ->Equals(context.local(),
20220 result->Get(context.local(), 0).ToLocalChecked())
20221 .FromJust());
Ben Murdochf87a2032010-10-22 12:50:53 +010020222}
Steve Block1e0659c2011-05-24 12:43:12 +010020223
20224
20225TEST(DefinePropertyPostDetach) {
Steve Block1e0659c2011-05-24 12:43:12 +010020226 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020227 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020228 v8::Local<v8::Object> proxy = context->Global();
20229 v8::Local<v8::Function> define_property =
20230 CompileRun(
20231 "(function() {"
20232 " Object.defineProperty("
20233 " this,"
20234 " 1,"
20235 " { configurable: true, enumerable: true, value: 3 });"
20236 "})")
20237 .As<Function>();
Steve Block1e0659c2011-05-24 12:43:12 +010020238 context->DetachGlobal();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020239 CHECK(define_property->Call(context.local(), proxy, 0, NULL).IsEmpty());
Steve Block1e0659c2011-05-24 12:43:12 +010020240}
Ben Murdoch8b112d22011-06-08 16:22:53 +010020241
20242
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020243static void InstallContextId(v8::Local<Context> context, int id) {
Ben Murdoch8b112d22011-06-08 16:22:53 +010020244 Context::Scope scope(context);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020245 CHECK(CompileRun("Object.prototype")
20246 .As<Object>()
20247 ->Set(context, v8_str("context_id"),
20248 v8::Integer::New(context->GetIsolate(), id))
20249 .FromJust());
Ben Murdoch8b112d22011-06-08 16:22:53 +010020250}
20251
20252
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020253static void CheckContextId(v8::Local<Object> object, int expected) {
20254 v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
20255 CHECK_EQ(expected, object->Get(context, v8_str("context_id"))
20256 .ToLocalChecked()
20257 ->Int32Value(context)
20258 .FromJust());
Ben Murdoch8b112d22011-06-08 16:22:53 +010020259}
20260
20261
20262THREADED_TEST(CreationContext) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020263 v8::Isolate* isolate = CcTest::isolate();
20264 HandleScope handle_scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020265 Local<Context> context1 = Context::New(isolate);
Ben Murdoch8b112d22011-06-08 16:22:53 +010020266 InstallContextId(context1, 1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020267 Local<Context> context2 = Context::New(isolate);
Ben Murdoch8b112d22011-06-08 16:22:53 +010020268 InstallContextId(context2, 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020269 Local<Context> context3 = Context::New(isolate);
Ben Murdoch8b112d22011-06-08 16:22:53 +010020270 InstallContextId(context3, 3);
20271
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020272 Local<v8::FunctionTemplate> tmpl = v8::FunctionTemplate::New(isolate);
Ben Murdoch8b112d22011-06-08 16:22:53 +010020273
20274 Local<Object> object1;
20275 Local<Function> func1;
20276 {
20277 Context::Scope scope(context1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020278 object1 = Object::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020279 func1 = tmpl->GetFunction(context1).ToLocalChecked();
Ben Murdoch8b112d22011-06-08 16:22:53 +010020280 }
20281
20282 Local<Object> object2;
20283 Local<Function> func2;
20284 {
20285 Context::Scope scope(context2);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020286 object2 = Object::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020287 func2 = tmpl->GetFunction(context2).ToLocalChecked();
Ben Murdoch8b112d22011-06-08 16:22:53 +010020288 }
20289
20290 Local<Object> instance1;
20291 Local<Object> instance2;
20292
20293 {
20294 Context::Scope scope(context3);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020295 instance1 = func1->NewInstance(context3).ToLocalChecked();
20296 instance2 = func2->NewInstance(context3).ToLocalChecked();
Ben Murdoch8b112d22011-06-08 16:22:53 +010020297 }
20298
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020299 {
20300 Local<Context> other_context = Context::New(isolate);
20301 Context::Scope scope(other_context);
20302 CHECK(object1->CreationContext() == context1);
20303 CheckContextId(object1, 1);
20304 CHECK(func1->CreationContext() == context1);
20305 CheckContextId(func1, 1);
20306 CHECK(instance1->CreationContext() == context1);
20307 CheckContextId(instance1, 1);
20308 CHECK(object2->CreationContext() == context2);
20309 CheckContextId(object2, 2);
20310 CHECK(func2->CreationContext() == context2);
20311 CheckContextId(func2, 2);
20312 CHECK(instance2->CreationContext() == context2);
20313 CheckContextId(instance2, 2);
20314 }
Ben Murdoch8b112d22011-06-08 16:22:53 +010020315
20316 {
20317 Context::Scope scope(context1);
20318 CHECK(object1->CreationContext() == context1);
20319 CheckContextId(object1, 1);
20320 CHECK(func1->CreationContext() == context1);
20321 CheckContextId(func1, 1);
20322 CHECK(instance1->CreationContext() == context1);
20323 CheckContextId(instance1, 1);
20324 CHECK(object2->CreationContext() == context2);
20325 CheckContextId(object2, 2);
20326 CHECK(func2->CreationContext() == context2);
20327 CheckContextId(func2, 2);
20328 CHECK(instance2->CreationContext() == context2);
20329 CheckContextId(instance2, 2);
20330 }
20331
20332 {
20333 Context::Scope scope(context2);
20334 CHECK(object1->CreationContext() == context1);
20335 CheckContextId(object1, 1);
20336 CHECK(func1->CreationContext() == context1);
20337 CheckContextId(func1, 1);
20338 CHECK(instance1->CreationContext() == context1);
20339 CheckContextId(instance1, 1);
20340 CHECK(object2->CreationContext() == context2);
20341 CheckContextId(object2, 2);
20342 CHECK(func2->CreationContext() == context2);
20343 CheckContextId(func2, 2);
20344 CHECK(instance2->CreationContext() == context2);
20345 CheckContextId(instance2, 2);
20346 }
Ben Murdoch8b112d22011-06-08 16:22:53 +010020347}
Ben Murdoch257744e2011-11-30 15:57:28 +000020348
20349
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020350THREADED_TEST(CreationContextOfJsFunction) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020351 HandleScope handle_scope(CcTest::isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020352 Local<Context> context = Context::New(CcTest::isolate());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020353 InstallContextId(context, 1);
20354
20355 Local<Object> function;
20356 {
20357 Context::Scope scope(context);
20358 function = CompileRun("function foo() {}; foo").As<Object>();
20359 }
20360
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020361 Local<Context> other_context = Context::New(CcTest::isolate());
20362 Context::Scope scope(other_context);
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020363 CHECK(function->CreationContext() == context);
20364 CheckContextId(function, 1);
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020365}
20366
20367
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020368THREADED_TEST(CreationContextOfJsBoundFunction) {
20369 HandleScope handle_scope(CcTest::isolate());
20370 Local<Context> context1 = Context::New(CcTest::isolate());
20371 InstallContextId(context1, 1);
20372 Local<Context> context2 = Context::New(CcTest::isolate());
20373 InstallContextId(context2, 2);
20374
20375 Local<Function> target_function;
20376 {
20377 Context::Scope scope(context1);
20378 target_function = CompileRun("function foo() {}; foo").As<Function>();
20379 }
20380
20381 Local<Function> bound_function1, bound_function2;
20382 {
20383 Context::Scope scope(context2);
20384 CHECK(context2->Global()
20385 ->Set(context2, v8_str("foo"), target_function)
20386 .FromJust());
20387 bound_function1 = CompileRun("foo.bind(1)").As<Function>();
20388 bound_function2 =
20389 CompileRun("Function.prototype.bind.call(foo, 2)").As<Function>();
20390 }
20391
20392 Local<Context> other_context = Context::New(CcTest::isolate());
20393 Context::Scope scope(other_context);
20394 CHECK(bound_function1->CreationContext() == context1);
20395 CheckContextId(bound_function1, 1);
Ben Murdoch097c5b22016-05-18 11:27:45 +010020396 CHECK(bound_function2->CreationContext() == context1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020397 CheckContextId(bound_function2, 1);
20398}
20399
20400
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020401void HasOwnPropertyIndexedPropertyGetter(
20402 uint32_t index,
20403 const v8::PropertyCallbackInfo<v8::Value>& info) {
20404 if (index == 42) info.GetReturnValue().Set(v8_str("yes"));
Ben Murdoch257744e2011-11-30 15:57:28 +000020405}
20406
20407
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020408void HasOwnPropertyNamedPropertyGetter(
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020409 Local<Name> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020410 if (property->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
20411 .FromJust()) {
20412 info.GetReturnValue().Set(v8_str("yes"));
20413 }
Ben Murdoch257744e2011-11-30 15:57:28 +000020414}
20415
20416
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020417void HasOwnPropertyIndexedPropertyQuery(
20418 uint32_t index, const v8::PropertyCallbackInfo<v8::Integer>& info) {
20419 if (index == 42) info.GetReturnValue().Set(1);
Ben Murdoch257744e2011-11-30 15:57:28 +000020420}
20421
20422
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020423void HasOwnPropertyNamedPropertyQuery(
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020424 Local<Name> property, const v8::PropertyCallbackInfo<v8::Integer>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020425 if (property->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
20426 .FromJust()) {
20427 info.GetReturnValue().Set(1);
20428 }
Ben Murdoch257744e2011-11-30 15:57:28 +000020429}
20430
20431
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020432void HasOwnPropertyNamedPropertyQuery2(
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020433 Local<Name> property, const v8::PropertyCallbackInfo<v8::Integer>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020434 if (property->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("bar"))
20435 .FromJust()) {
20436 info.GetReturnValue().Set(1);
20437 }
Ben Murdoch257744e2011-11-30 15:57:28 +000020438}
20439
20440
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020441void HasOwnPropertyAccessorGetter(
20442 Local<String> property,
20443 const v8::PropertyCallbackInfo<v8::Value>& info) {
20444 info.GetReturnValue().Set(v8_str("yes"));
Ben Murdoch257744e2011-11-30 15:57:28 +000020445}
20446
20447
20448TEST(HasOwnProperty) {
Ben Murdoch257744e2011-11-30 15:57:28 +000020449 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020450 v8::Isolate* isolate = env->GetIsolate();
20451 v8::HandleScope scope(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000020452 { // Check normal properties and defined getters.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020453 Local<Value> value = CompileRun(
Ben Murdoch257744e2011-11-30 15:57:28 +000020454 "function Foo() {"
20455 " this.foo = 11;"
20456 " this.__defineGetter__('baz', function() { return 1; });"
20457 "};"
20458 "function Bar() { "
20459 " this.bar = 13;"
20460 " this.__defineGetter__('bla', function() { return 2; });"
20461 "};"
20462 "Bar.prototype = new Foo();"
20463 "new Bar();");
20464 CHECK(value->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020465 Local<Object> object = value->ToObject(env.local()).ToLocalChecked();
20466 CHECK(object->Has(env.local(), v8_str("foo")).FromJust());
20467 CHECK(!object->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
20468 CHECK(object->HasOwnProperty(env.local(), v8_str("bar")).FromJust());
20469 CHECK(object->Has(env.local(), v8_str("baz")).FromJust());
20470 CHECK(!object->HasOwnProperty(env.local(), v8_str("baz")).FromJust());
20471 CHECK(object->HasOwnProperty(env.local(), v8_str("bla")).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000020472 }
20473 { // Check named getter interceptors.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020474 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020475 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
20476 HasOwnPropertyNamedPropertyGetter));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020477 Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
20478 CHECK(!instance->HasOwnProperty(env.local(), v8_str("42")).FromJust());
Ben Murdochc5610432016-08-08 18:44:38 +010020479 CHECK(!instance->HasOwnProperty(env.local(), 42).FromJust());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020480 CHECK(instance->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
20481 CHECK(!instance->HasOwnProperty(env.local(), v8_str("bar")).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000020482 }
20483 { // Check indexed getter interceptors.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020484 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020485 templ->SetHandler(v8::IndexedPropertyHandlerConfiguration(
20486 HasOwnPropertyIndexedPropertyGetter));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020487 Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
20488 CHECK(instance->HasOwnProperty(env.local(), v8_str("42")).FromJust());
Ben Murdochc5610432016-08-08 18:44:38 +010020489 CHECK(instance->HasOwnProperty(env.local(), 42).FromJust());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020490 CHECK(!instance->HasOwnProperty(env.local(), v8_str("43")).FromJust());
Ben Murdochc5610432016-08-08 18:44:38 +010020491 CHECK(!instance->HasOwnProperty(env.local(), 43).FromJust());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020492 CHECK(!instance->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000020493 }
20494 { // Check named query interceptors.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020495 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020496 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
20497 0, 0, HasOwnPropertyNamedPropertyQuery));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020498 Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
20499 CHECK(instance->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
20500 CHECK(!instance->HasOwnProperty(env.local(), v8_str("bar")).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000020501 }
20502 { // Check indexed query interceptors.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020503 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020504 templ->SetHandler(v8::IndexedPropertyHandlerConfiguration(
20505 0, 0, HasOwnPropertyIndexedPropertyQuery));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020506 Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
20507 CHECK(instance->HasOwnProperty(env.local(), v8_str("42")).FromJust());
Ben Murdochc5610432016-08-08 18:44:38 +010020508 CHECK(instance->HasOwnProperty(env.local(), 42).FromJust());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020509 CHECK(!instance->HasOwnProperty(env.local(), v8_str("41")).FromJust());
Ben Murdochc5610432016-08-08 18:44:38 +010020510 CHECK(!instance->HasOwnProperty(env.local(), 41).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000020511 }
20512 { // Check callbacks.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020513 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000020514 templ->SetAccessor(v8_str("foo"), HasOwnPropertyAccessorGetter);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020515 Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
20516 CHECK(instance->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
20517 CHECK(!instance->HasOwnProperty(env.local(), v8_str("bar")).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000020518 }
20519 { // Check that query wins on disagreement.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020520 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020521 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
20522 HasOwnPropertyNamedPropertyGetter, 0,
20523 HasOwnPropertyNamedPropertyQuery2));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020524 Local<Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
20525 CHECK(!instance->HasOwnProperty(env.local(), v8_str("foo")).FromJust());
20526 CHECK(instance->HasOwnProperty(env.local(), v8_str("bar")).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000020527 }
20528}
20529
20530
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020531TEST(IndexedInterceptorWithStringProto) {
20532 v8::Isolate* isolate = CcTest::isolate();
20533 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020534 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020535 templ->SetHandler(v8::IndexedPropertyHandlerConfiguration(
20536 NULL, NULL, HasOwnPropertyIndexedPropertyQuery));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020537 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020538 CHECK(context->Global()
20539 ->Set(context.local(), v8_str("obj"),
20540 templ->NewInstance(context.local()).ToLocalChecked())
20541 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020542 CompileRun("var s = new String('foobar'); obj.__proto__ = s;");
20543 // These should be intercepted.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020544 CHECK(CompileRun("42 in obj")->BooleanValue(context.local()).FromJust());
20545 CHECK(CompileRun("'42' in obj")->BooleanValue(context.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020546 // These should fall through to the String prototype.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020547 CHECK(CompileRun("0 in obj")->BooleanValue(context.local()).FromJust());
20548 CHECK(CompileRun("'0' in obj")->BooleanValue(context.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020549 // And these should both fail.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020550 CHECK(!CompileRun("32 in obj")->BooleanValue(context.local()).FromJust());
20551 CHECK(!CompileRun("'32' in obj")->BooleanValue(context.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020552}
20553
20554
Ben Murdoch257744e2011-11-30 15:57:28 +000020555void CheckCodeGenerationAllowed() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020556 Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
20557 Local<Value> result = CompileRun("eval('42')");
20558 CHECK_EQ(42, result->Int32Value(context).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000020559 result = CompileRun("(function(e) { return e('42'); })(eval)");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020560 CHECK_EQ(42, result->Int32Value(context).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000020561 result = CompileRun("var f = new Function('return 42'); f()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020562 CHECK_EQ(42, result->Int32Value(context).FromJust());
Ben Murdoch257744e2011-11-30 15:57:28 +000020563}
20564
20565
20566void CheckCodeGenerationDisallowed() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020567 TryCatch try_catch(CcTest::isolate());
Ben Murdoch257744e2011-11-30 15:57:28 +000020568
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020569 Local<Value> result = CompileRun("eval('42')");
Ben Murdoch257744e2011-11-30 15:57:28 +000020570 CHECK(result.IsEmpty());
20571 CHECK(try_catch.HasCaught());
20572 try_catch.Reset();
20573
20574 result = CompileRun("(function(e) { return e('42'); })(eval)");
20575 CHECK(result.IsEmpty());
20576 CHECK(try_catch.HasCaught());
20577 try_catch.Reset();
20578
20579 result = CompileRun("var f = new Function('return 42'); f()");
20580 CHECK(result.IsEmpty());
20581 CHECK(try_catch.HasCaught());
20582}
20583
20584
20585bool CodeGenerationAllowed(Local<Context> context) {
20586 ApiTestFuzzer::Fuzz();
20587 return true;
20588}
20589
20590
20591bool CodeGenerationDisallowed(Local<Context> context) {
20592 ApiTestFuzzer::Fuzz();
20593 return false;
20594}
20595
20596
20597THREADED_TEST(AllowCodeGenFromStrings) {
Ben Murdoch257744e2011-11-30 15:57:28 +000020598 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020599 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch257744e2011-11-30 15:57:28 +000020600
20601 // eval and the Function constructor allowed by default.
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020602 CHECK(context->IsCodeGenerationFromStringsAllowed());
Ben Murdoch257744e2011-11-30 15:57:28 +000020603 CheckCodeGenerationAllowed();
20604
20605 // Disallow eval and the Function constructor.
20606 context->AllowCodeGenerationFromStrings(false);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020607 CHECK(!context->IsCodeGenerationFromStringsAllowed());
Ben Murdoch257744e2011-11-30 15:57:28 +000020608 CheckCodeGenerationDisallowed();
20609
20610 // Allow again.
20611 context->AllowCodeGenerationFromStrings(true);
20612 CheckCodeGenerationAllowed();
20613
20614 // Disallow but setting a global callback that will allow the calls.
20615 context->AllowCodeGenerationFromStrings(false);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020616 context->GetIsolate()->SetAllowCodeGenerationFromStringsCallback(
20617 &CodeGenerationAllowed);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020618 CHECK(!context->IsCodeGenerationFromStringsAllowed());
Ben Murdoch257744e2011-11-30 15:57:28 +000020619 CheckCodeGenerationAllowed();
20620
20621 // Set a callback that disallows the code generation.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020622 context->GetIsolate()->SetAllowCodeGenerationFromStringsCallback(
20623 &CodeGenerationDisallowed);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020624 CHECK(!context->IsCodeGenerationFromStringsAllowed());
Ben Murdoch257744e2011-11-30 15:57:28 +000020625 CheckCodeGenerationDisallowed();
20626}
20627
20628
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020629TEST(SetErrorMessageForCodeGenFromStrings) {
20630 LocalContext context;
20631 v8::HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020632 TryCatch try_catch(context->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020633
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020634 Local<String> message = v8_str("Message");
20635 Local<String> expected_message = v8_str("Uncaught EvalError: Message");
20636 context->GetIsolate()->SetAllowCodeGenerationFromStringsCallback(
20637 &CodeGenerationDisallowed);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020638 context->AllowCodeGenerationFromStrings(false);
20639 context->SetErrorMessageForCodeGenerationFromStrings(message);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020640 Local<Value> result = CompileRun("eval('42')");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020641 CHECK(result.IsEmpty());
20642 CHECK(try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020643 Local<String> actual_message = try_catch.Message()->Get();
20644 CHECK(expected_message->Equals(context.local(), actual_message).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020645}
20646
20647
20648static void NonObjectThis(const v8::FunctionCallbackInfo<v8::Value>& args) {
Ben Murdoch257744e2011-11-30 15:57:28 +000020649}
20650
20651
20652THREADED_TEST(CallAPIFunctionOnNonObject) {
Ben Murdoch257744e2011-11-30 15:57:28 +000020653 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020654 v8::Isolate* isolate = context->GetIsolate();
20655 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020656 Local<FunctionTemplate> templ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020657 v8::FunctionTemplate::New(isolate, NonObjectThis);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020658 Local<Function> function =
20659 templ->GetFunction(context.local()).ToLocalChecked();
20660 CHECK(context->Global()
20661 ->Set(context.local(), v8_str("f"), function)
20662 .FromJust());
20663 TryCatch try_catch(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +000020664 CompileRun("f.call(2)");
20665}
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020666
20667
20668// Regression test for issue 1470.
20669THREADED_TEST(ReadOnlyIndexedProperties) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020670 v8::Isolate* isolate = CcTest::isolate();
20671 v8::HandleScope scope(isolate);
20672 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020673
20674 LocalContext context;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020675 Local<v8::Object> obj = templ->NewInstance(context.local()).ToLocalChecked();
20676 CHECK(context->Global()->Set(context.local(), v8_str("obj"), obj).FromJust());
20677 obj->DefineOwnProperty(context.local(), v8_str("1"), v8_str("DONT_CHANGE"),
20678 v8::ReadOnly)
20679 .FromJust();
20680 obj->Set(context.local(), v8_str("1"), v8_str("foobar")).FromJust();
20681 CHECK(v8_str("DONT_CHANGE")
20682 ->Equals(context.local(),
20683 obj->Get(context.local(), v8_str("1")).ToLocalChecked())
20684 .FromJust());
20685 obj->DefineOwnProperty(context.local(), v8_str("2"), v8_str("DONT_CHANGE"),
20686 v8::ReadOnly)
20687 .FromJust();
20688 obj->Set(context.local(), v8_num(2), v8_str("foobar")).FromJust();
20689 CHECK(v8_str("DONT_CHANGE")
20690 ->Equals(context.local(),
20691 obj->Get(context.local(), v8_num(2)).ToLocalChecked())
20692 .FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020693
20694 // Test non-smi case.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020695 obj->DefineOwnProperty(context.local(), v8_str("2000000000"),
20696 v8_str("DONT_CHANGE"), v8::ReadOnly)
20697 .FromJust();
20698 obj->Set(context.local(), v8_str("2000000000"), v8_str("foobar")).FromJust();
20699 CHECK(v8_str("DONT_CHANGE")
20700 ->Equals(context.local(),
20701 obj->Get(context.local(), v8_str("2000000000"))
20702 .ToLocalChecked())
20703 .FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020704}
20705
20706
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020707static int CountLiveMapsInMapCache(i::Context* context) {
20708 i::FixedArray* map_cache = i::FixedArray::cast(context->map_cache());
20709 int length = map_cache->length();
20710 int count = 0;
20711 for (int i = 0; i < length; i++) {
20712 i::Object* value = map_cache->get(i);
20713 if (value->IsWeakCell() && !i::WeakCell::cast(value)->cleared()) count++;
20714 }
20715 return count;
20716}
20717
20718
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020719THREADED_TEST(Regress1516) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020720 LocalContext context;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020721 v8::HandleScope scope(context->GetIsolate());
20722
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020723 // Object with 20 properties is not a common case, so it should be removed
20724 // from the cache after GC.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020725 { v8::HandleScope temp_scope(context->GetIsolate());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020726 CompileRun(
20727 "({"
20728 "'a00': 0, 'a01': 0, 'a02': 0, 'a03': 0, 'a04': 0, "
20729 "'a05': 0, 'a06': 0, 'a07': 0, 'a08': 0, 'a09': 0, "
20730 "'a10': 0, 'a11': 0, 'a12': 0, 'a13': 0, 'a14': 0, "
20731 "'a15': 0, 'a16': 0, 'a17': 0, 'a18': 0, 'a19': 0, "
20732 "})");
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020733 }
20734
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020735 int elements = CountLiveMapsInMapCache(CcTest::i_isolate()->context());
20736 CHECK_LE(1, elements);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020737
Ben Murdochda12d292016-06-02 14:46:10 +010020738 // We have to abort incremental marking here to abandon black pages.
20739 CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020740
20741 CHECK_GT(elements, CountLiveMapsInMapCache(CcTest::i_isolate()->context()));
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020742}
20743
20744
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020745THREADED_TEST(Regress93759) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020746 v8::Isolate* isolate = CcTest::isolate();
20747 HandleScope scope(isolate);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020748
20749 // Template for object with security check.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020750 Local<ObjectTemplate> no_proto_template = v8::ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020751 no_proto_template->SetAccessCheckCallback(AccessAlwaysBlocked);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020752
20753 // Templates for objects with hidden prototypes and possibly security check.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020754 Local<FunctionTemplate> hidden_proto_template =
20755 v8::FunctionTemplate::New(isolate);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020756 hidden_proto_template->SetHiddenPrototype(true);
20757
20758 Local<FunctionTemplate> protected_hidden_proto_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020759 v8::FunctionTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020760 protected_hidden_proto_template->InstanceTemplate()->SetAccessCheckCallback(
20761 AccessAlwaysBlocked);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020762 protected_hidden_proto_template->SetHiddenPrototype(true);
20763
20764 // Context for "foreign" objects used in test.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020765 Local<Context> context = v8::Context::New(isolate);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020766 context->Enter();
20767
20768 // Plain object, no security check.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020769 Local<Object> simple_object = Object::New(isolate);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020770
20771 // Object with explicit security check.
20772 Local<Object> protected_object =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020773 no_proto_template->NewInstance(context).ToLocalChecked();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020774
20775 // JSGlobalProxy object, always have security check.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020776 Local<Object> proxy_object = context->Global();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020777
20778 // Global object, the prototype of proxy_object. No security checks.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020779 Local<Object> global_object =
20780 proxy_object->GetPrototype()->ToObject(context).ToLocalChecked();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020781
20782 // Hidden prototype without security check.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020783 Local<Object> hidden_prototype = hidden_proto_template->GetFunction(context)
20784 .ToLocalChecked()
20785 ->NewInstance(context)
20786 .ToLocalChecked();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020787 Local<Object> object_with_hidden =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020788 Object::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020789 object_with_hidden->SetPrototype(context, hidden_prototype).FromJust();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020790
20791 context->Exit();
20792
Ben Murdoch097c5b22016-05-18 11:27:45 +010020793 LocalContext context2;
20794 v8::Local<v8::Object> global = context2->Global();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020795
Ben Murdoch097c5b22016-05-18 11:27:45 +010020796 // Setup global variables.
20797 CHECK(global->Set(context2.local(), v8_str("simple"), simple_object)
20798 .FromJust());
20799 CHECK(global->Set(context2.local(), v8_str("protected"), protected_object)
20800 .FromJust());
20801 CHECK(global->Set(context2.local(), v8_str("global"), global_object)
20802 .FromJust());
20803 CHECK(
20804 global->Set(context2.local(), v8_str("proxy"), proxy_object).FromJust());
20805 CHECK(global->Set(context2.local(), v8_str("hidden"), object_with_hidden)
20806 .FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020807
20808 Local<Value> result1 = CompileRun("Object.getPrototypeOf(simple)");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020809 CHECK(result1->Equals(context2.local(), simple_object->GetPrototype())
20810 .FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020811
20812 Local<Value> result2 = CompileRun("Object.getPrototypeOf(protected)");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020813 CHECK(result2->IsNull());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020814
20815 Local<Value> result3 = CompileRun("Object.getPrototypeOf(global)");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020816 CHECK(result3->Equals(context2.local(), global_object->GetPrototype())
20817 .FromJust());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020818
20819 Local<Value> result4 = CompileRun("Object.getPrototypeOf(proxy)");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020820 CHECK(result4->IsNull());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000020821
20822 Local<Value> result5 = CompileRun("Object.getPrototypeOf(hidden)");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020823 CHECK(result5->Equals(context2.local(), object_with_hidden->GetPrototype()
20824 ->ToObject(context2.local())
20825 .ToLocalChecked()
20826 ->GetPrototype())
20827 .FromJust());
Ben Murdoch5710cea2012-05-21 14:52:42 +010020828}
20829
20830
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020831static void TestReceiver(Local<Value> expected_result,
20832 Local<Value> expected_receiver,
20833 const char* code) {
20834 Local<Value> result = CompileRun(code);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020835 Local<Context> context = CcTest::isolate()->GetCurrentContext();
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020836 CHECK(result->IsObject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020837 CHECK(expected_receiver
20838 ->Equals(context,
20839 result.As<v8::Object>()->Get(context, 1).ToLocalChecked())
20840 .FromJust());
20841 CHECK(expected_result
20842 ->Equals(context,
20843 result.As<v8::Object>()->Get(context, 0).ToLocalChecked())
20844 .FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020845}
20846
20847
20848THREADED_TEST(ForeignFunctionReceiver) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020849 v8::Isolate* isolate = CcTest::isolate();
20850 HandleScope scope(isolate);
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020851
20852 // Create two contexts with different "id" properties ('i' and 'o').
20853 // Call a function both from its own context and from a the foreign
20854 // context, and see what "this" is bound to (returning both "this"
20855 // and "this.id" for comparison).
20856
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020857 Local<Context> foreign_context = v8::Context::New(isolate);
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020858 foreign_context->Enter();
20859 Local<Value> foreign_function =
20860 CompileRun("function func() { return { 0: this.id, "
20861 " 1: this, "
20862 " toString: function() { "
20863 " return this[0];"
20864 " }"
20865 " };"
20866 "}"
20867 "var id = 'i';"
20868 "func;");
20869 CHECK(foreign_function->IsFunction());
20870 foreign_context->Exit();
20871
20872 LocalContext context;
20873
20874 Local<String> password = v8_str("Password");
20875 // Don't get hit by security checks when accessing foreign_context's
20876 // global receiver (aka. global proxy).
20877 context->SetSecurityToken(password);
20878 foreign_context->SetSecurityToken(password);
20879
20880 Local<String> i = v8_str("i");
20881 Local<String> o = v8_str("o");
20882 Local<String> id = v8_str("id");
20883
20884 CompileRun("function ownfunc() { return { 0: this.id, "
20885 " 1: this, "
20886 " toString: function() { "
20887 " return this[0];"
20888 " }"
20889 " };"
20890 "}"
20891 "var id = 'o';"
20892 "ownfunc");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020893 CHECK(context->Global()
20894 ->Set(context.local(), v8_str("func"), foreign_function)
20895 .FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020896
20897 // Sanity check the contexts.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020898 CHECK(
20899 i->Equals(
20900 context.local(),
20901 foreign_context->Global()->Get(context.local(), id).ToLocalChecked())
20902 .FromJust());
20903 CHECK(o->Equals(context.local(),
20904 context->Global()->Get(context.local(), id).ToLocalChecked())
20905 .FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020906
20907 // Checking local function's receiver.
20908 // Calling function using its call/apply methods.
20909 TestReceiver(o, context->Global(), "ownfunc.call()");
20910 TestReceiver(o, context->Global(), "ownfunc.apply()");
20911 // Making calls through built-in functions.
20912 TestReceiver(o, context->Global(), "[1].map(ownfunc)[0]");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020913 CHECK(
20914 o->Equals(context.local(), CompileRun("'abcbd'.replace(/b/,ownfunc)[1]"))
20915 .FromJust());
20916 CHECK(
20917 o->Equals(context.local(), CompileRun("'abcbd'.replace(/b/g,ownfunc)[1]"))
20918 .FromJust());
20919 CHECK(
20920 o->Equals(context.local(), CompileRun("'abcbd'.replace(/b/g,ownfunc)[3]"))
20921 .FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020922 // Calling with environment record as base.
20923 TestReceiver(o, context->Global(), "ownfunc()");
20924 // Calling with no base.
20925 TestReceiver(o, context->Global(), "(1,ownfunc)()");
20926
20927 // Checking foreign function return value.
20928 // Calling function using its call/apply methods.
20929 TestReceiver(i, foreign_context->Global(), "func.call()");
20930 TestReceiver(i, foreign_context->Global(), "func.apply()");
20931 // Calling function using another context's call/apply methods.
20932 TestReceiver(i, foreign_context->Global(),
20933 "Function.prototype.call.call(func)");
20934 TestReceiver(i, foreign_context->Global(),
20935 "Function.prototype.call.apply(func)");
20936 TestReceiver(i, foreign_context->Global(),
20937 "Function.prototype.apply.call(func)");
20938 TestReceiver(i, foreign_context->Global(),
20939 "Function.prototype.apply.apply(func)");
20940 // Making calls through built-in functions.
20941 TestReceiver(i, foreign_context->Global(), "[1].map(func)[0]");
20942 // ToString(func()) is func()[0], i.e., the returned this.id.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020943 CHECK(i->Equals(context.local(), CompileRun("'abcbd'.replace(/b/,func)[1]"))
20944 .FromJust());
20945 CHECK(i->Equals(context.local(), CompileRun("'abcbd'.replace(/b/g,func)[1]"))
20946 .FromJust());
20947 CHECK(i->Equals(context.local(), CompileRun("'abcbd'.replace(/b/g,func)[3]"))
20948 .FromJust());
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020949
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020950 // Calling with environment record as base.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020951 TestReceiver(i, foreign_context->Global(), "func()");
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020952 // Calling with no base.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020953 TestReceiver(i, foreign_context->Global(), "(1,func)()");
Ben Murdoch69a99ed2011-11-30 16:03:39 +000020954}
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020955
20956
20957uint8_t callback_fired = 0;
Ben Murdoch097c5b22016-05-18 11:27:45 +010020958uint8_t before_call_entered_callback_count1 = 0;
20959uint8_t before_call_entered_callback_count2 = 0;
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020960
20961
Ben Murdoch097c5b22016-05-18 11:27:45 +010020962void CallCompletedCallback1(v8::Isolate*) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020963 v8::base::OS::Print("Firing callback 1.\n");
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020964 callback_fired ^= 1; // Toggle first bit.
20965}
20966
20967
Ben Murdoch097c5b22016-05-18 11:27:45 +010020968void CallCompletedCallback2(v8::Isolate*) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020969 v8::base::OS::Print("Firing callback 2.\n");
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020970 callback_fired ^= 2; // Toggle second bit.
20971}
20972
20973
Ben Murdoch097c5b22016-05-18 11:27:45 +010020974void BeforeCallEnteredCallback1(v8::Isolate*) {
20975 v8::base::OS::Print("Firing before call entered callback 1.\n");
20976 before_call_entered_callback_count1++;
20977}
20978
20979
20980void BeforeCallEnteredCallback2(v8::Isolate*) {
20981 v8::base::OS::Print("Firing before call entered callback 2.\n");
20982 before_call_entered_callback_count2++;
20983}
20984
20985
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020986void RecursiveCall(const v8::FunctionCallbackInfo<v8::Value>& args) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020987 int32_t level =
20988 args[0]->Int32Value(args.GetIsolate()->GetCurrentContext()).FromJust();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020989 if (level < 3) {
20990 level++;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020991 v8::base::OS::Print("Entering recursion level %d.\n", level);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020992 char script[64];
20993 i::Vector<char> script_vector(script, sizeof(script));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020994 i::SNPrintF(script_vector, "recursion(%d)", level);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020995 CompileRun(script_vector.start());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020996 v8::base::OS::Print("Leaving recursion level %d.\n", level);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010020997 CHECK_EQ(0, callback_fired);
20998 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020999 v8::base::OS::Print("Recursion ends.\n");
Ben Murdoch3ef787d2012-04-12 10:51:47 +010021000 CHECK_EQ(0, callback_fired);
21001 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +010021002}
21003
21004
21005TEST(CallCompletedCallback) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010021006 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021007 v8::HandleScope scope(env->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021008 v8::Local<v8::FunctionTemplate> recursive_runtime =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021009 v8::FunctionTemplate::New(env->GetIsolate(), RecursiveCall);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021010 env->Global()
21011 ->Set(env.local(), v8_str("recursion"),
21012 recursive_runtime->GetFunction(env.local()).ToLocalChecked())
21013 .FromJust();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010021014 // Adding the same callback a second time has no effect.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021015 env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback1);
21016 env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback1);
21017 env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback2);
Ben Murdoch097c5b22016-05-18 11:27:45 +010021018 env->GetIsolate()->AddBeforeCallEnteredCallback(BeforeCallEnteredCallback1);
21019 env->GetIsolate()->AddBeforeCallEnteredCallback(BeforeCallEnteredCallback2);
21020 env->GetIsolate()->AddBeforeCallEnteredCallback(BeforeCallEnteredCallback1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021021 v8::base::OS::Print("--- Script (1) ---\n");
Ben Murdoch097c5b22016-05-18 11:27:45 +010021022 callback_fired = 0;
21023 before_call_entered_callback_count1 = 0;
21024 before_call_entered_callback_count2 = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021025 Local<Script> script =
21026 v8::Script::Compile(env.local(), v8_str("recursion(0)")).ToLocalChecked();
21027 script->Run(env.local()).ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010021028 CHECK_EQ(3, callback_fired);
Ben Murdoch097c5b22016-05-18 11:27:45 +010021029 CHECK_EQ(4, before_call_entered_callback_count1);
21030 CHECK_EQ(4, before_call_entered_callback_count2);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010021031
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021032 v8::base::OS::Print("\n--- Script (2) ---\n");
Ben Murdoch3ef787d2012-04-12 10:51:47 +010021033 callback_fired = 0;
Ben Murdoch097c5b22016-05-18 11:27:45 +010021034 before_call_entered_callback_count1 = 0;
21035 before_call_entered_callback_count2 = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021036 env->GetIsolate()->RemoveCallCompletedCallback(CallCompletedCallback1);
Ben Murdoch097c5b22016-05-18 11:27:45 +010021037 env->GetIsolate()->RemoveBeforeCallEnteredCallback(
21038 BeforeCallEnteredCallback1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021039 script->Run(env.local()).ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010021040 CHECK_EQ(2, callback_fired);
Ben Murdoch097c5b22016-05-18 11:27:45 +010021041 CHECK_EQ(0, before_call_entered_callback_count1);
21042 CHECK_EQ(4, before_call_entered_callback_count2);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010021043
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021044 v8::base::OS::Print("\n--- Function ---\n");
Ben Murdoch3ef787d2012-04-12 10:51:47 +010021045 callback_fired = 0;
Ben Murdoch097c5b22016-05-18 11:27:45 +010021046 before_call_entered_callback_count1 = 0;
21047 before_call_entered_callback_count2 = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021048 Local<Function> recursive_function = Local<Function>::Cast(
21049 env->Global()->Get(env.local(), v8_str("recursion")).ToLocalChecked());
21050 v8::Local<Value> args[] = {v8_num(0)};
21051 recursive_function->Call(env.local(), env->Global(), 1, args)
21052 .ToLocalChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010021053 CHECK_EQ(2, callback_fired);
Ben Murdoch097c5b22016-05-18 11:27:45 +010021054 CHECK_EQ(0, before_call_entered_callback_count1);
21055 CHECK_EQ(4, before_call_entered_callback_count2);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010021056}
21057
21058
Ben Murdoch097c5b22016-05-18 11:27:45 +010021059void CallCompletedCallbackNoException(v8::Isolate*) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021060 v8::HandleScope scope(CcTest::isolate());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010021061 CompileRun("1+1;");
21062}
21063
21064
Ben Murdoch097c5b22016-05-18 11:27:45 +010021065void CallCompletedCallbackException(v8::Isolate*) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021066 v8::HandleScope scope(CcTest::isolate());
Ben Murdoch3ef787d2012-04-12 10:51:47 +010021067 CompileRun("throw 'second exception';");
21068}
21069
21070
21071TEST(CallCompletedCallbackOneException) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010021072 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021073 v8::HandleScope scope(env->GetIsolate());
21074 env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallbackNoException);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010021075 CompileRun("throw 'exception';");
21076}
21077
21078
21079TEST(CallCompletedCallbackTwoExceptions) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010021080 LocalContext env;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021081 v8::HandleScope scope(env->GetIsolate());
21082 env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallbackException);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010021083 CompileRun("throw 'first exception';");
21084}
21085
21086
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021087static void MicrotaskOne(const v8::FunctionCallbackInfo<Value>& info) {
Ben Murdochc5610432016-08-08 18:44:38 +010021088 CHECK(v8::MicrotasksScope::IsRunningMicrotasks(info.GetIsolate()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021089 v8::HandleScope scope(info.GetIsolate());
Ben Murdochda12d292016-06-02 14:46:10 +010021090 v8::MicrotasksScope microtasks(info.GetIsolate(),
21091 v8::MicrotasksScope::kDoNotRunMicrotasks);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021092 CompileRun("ext1Calls++;");
21093}
21094
21095
21096static void MicrotaskTwo(const v8::FunctionCallbackInfo<Value>& info) {
Ben Murdochc5610432016-08-08 18:44:38 +010021097 CHECK(v8::MicrotasksScope::IsRunningMicrotasks(info.GetIsolate()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021098 v8::HandleScope scope(info.GetIsolate());
Ben Murdochda12d292016-06-02 14:46:10 +010021099 v8::MicrotasksScope microtasks(info.GetIsolate(),
21100 v8::MicrotasksScope::kDoNotRunMicrotasks);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021101 CompileRun("ext2Calls++;");
21102}
21103
21104
21105void* g_passed_to_three = NULL;
21106
21107
21108static void MicrotaskThree(void* data) {
21109 g_passed_to_three = data;
21110}
21111
21112
21113TEST(EnqueueMicrotask) {
21114 LocalContext env;
21115 v8::HandleScope scope(env->GetIsolate());
Ben Murdochc5610432016-08-08 18:44:38 +010021116 CHECK(!v8::MicrotasksScope::IsRunningMicrotasks(env->GetIsolate()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021117 CompileRun(
21118 "var ext1Calls = 0;"
21119 "var ext2Calls = 0;");
21120 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021121 CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21122 CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021123
21124 env->GetIsolate()->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021125 Function::New(env.local(), MicrotaskOne).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021126 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021127 CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21128 CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021129
21130 env->GetIsolate()->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021131 Function::New(env.local(), MicrotaskOne).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021132 env->GetIsolate()->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021133 Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021134 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021135 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21136 CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021137
21138 env->GetIsolate()->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021139 Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021140 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021141 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21142 CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021143
21144 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021145 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21146 CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021147
21148 g_passed_to_three = NULL;
21149 env->GetIsolate()->EnqueueMicrotask(MicrotaskThree);
21150 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021151 CHECK(!g_passed_to_three);
21152 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21153 CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021154
21155 int dummy;
21156 env->GetIsolate()->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021157 Function::New(env.local(), MicrotaskOne).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021158 env->GetIsolate()->EnqueueMicrotask(MicrotaskThree, &dummy);
21159 env->GetIsolate()->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021160 Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021161 CompileRun("1+1;");
21162 CHECK_EQ(&dummy, g_passed_to_three);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021163 CHECK_EQ(3, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21164 CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021165 g_passed_to_three = NULL;
21166}
21167
21168
21169static void MicrotaskExceptionOne(
21170 const v8::FunctionCallbackInfo<Value>& info) {
21171 v8::HandleScope scope(info.GetIsolate());
21172 CompileRun("exception1Calls++;");
21173 info.GetIsolate()->ThrowException(
21174 v8::Exception::Error(v8_str("first")));
21175}
21176
21177
21178static void MicrotaskExceptionTwo(
21179 const v8::FunctionCallbackInfo<Value>& info) {
21180 v8::HandleScope scope(info.GetIsolate());
21181 CompileRun("exception2Calls++;");
21182 info.GetIsolate()->ThrowException(
21183 v8::Exception::Error(v8_str("second")));
21184}
21185
21186
21187TEST(RunMicrotasksIgnoresThrownExceptions) {
21188 LocalContext env;
21189 v8::Isolate* isolate = env->GetIsolate();
21190 v8::HandleScope scope(isolate);
21191 CompileRun(
21192 "var exception1Calls = 0;"
21193 "var exception2Calls = 0;");
21194 isolate->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021195 Function::New(env.local(), MicrotaskExceptionOne).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021196 isolate->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021197 Function::New(env.local(), MicrotaskExceptionTwo).ToLocalChecked());
21198 TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021199 CompileRun("1+1;");
21200 CHECK(!try_catch.HasCaught());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021201 CHECK_EQ(1,
21202 CompileRun("exception1Calls")->Int32Value(env.local()).FromJust());
21203 CHECK_EQ(1,
21204 CompileRun("exception2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021205}
21206
21207
Ben Murdochda12d292016-06-02 14:46:10 +010021208uint8_t microtasks_completed_callback_count = 0;
21209
21210
21211static void MicrotasksCompletedCallback(v8::Isolate* isolate) {
21212 ++microtasks_completed_callback_count;
21213}
21214
21215
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021216TEST(SetAutorunMicrotasks) {
21217 LocalContext env;
21218 v8::HandleScope scope(env->GetIsolate());
Ben Murdochda12d292016-06-02 14:46:10 +010021219 env->GetIsolate()->AddMicrotasksCompletedCallback(
21220 &MicrotasksCompletedCallback);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021221 CompileRun(
21222 "var ext1Calls = 0;"
21223 "var ext2Calls = 0;");
21224 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021225 CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21226 CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochda12d292016-06-02 14:46:10 +010021227 CHECK_EQ(0u, microtasks_completed_callback_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021228
21229 env->GetIsolate()->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021230 Function::New(env.local(), MicrotaskOne).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021231 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021232 CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21233 CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochda12d292016-06-02 14:46:10 +010021234 CHECK_EQ(1u, microtasks_completed_callback_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021235
Ben Murdochda12d292016-06-02 14:46:10 +010021236 env->GetIsolate()->SetMicrotasksPolicy(v8::MicrotasksPolicy::kExplicit);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021237 env->GetIsolate()->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021238 Function::New(env.local(), MicrotaskOne).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021239 env->GetIsolate()->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021240 Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021241 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021242 CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21243 CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochda12d292016-06-02 14:46:10 +010021244 CHECK_EQ(1u, microtasks_completed_callback_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021245
21246 env->GetIsolate()->RunMicrotasks();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021247 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21248 CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochda12d292016-06-02 14:46:10 +010021249 CHECK_EQ(2u, microtasks_completed_callback_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021250
21251 env->GetIsolate()->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021252 Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021253 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021254 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21255 CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochda12d292016-06-02 14:46:10 +010021256 CHECK_EQ(2u, microtasks_completed_callback_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021257
21258 env->GetIsolate()->RunMicrotasks();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021259 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21260 CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochda12d292016-06-02 14:46:10 +010021261 CHECK_EQ(3u, microtasks_completed_callback_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021262
Ben Murdochda12d292016-06-02 14:46:10 +010021263 env->GetIsolate()->SetMicrotasksPolicy(v8::MicrotasksPolicy::kAuto);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021264 env->GetIsolate()->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021265 Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021266 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021267 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21268 CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochda12d292016-06-02 14:46:10 +010021269 CHECK_EQ(4u, microtasks_completed_callback_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021270
21271 env->GetIsolate()->EnqueueMicrotask(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021272 Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021273 {
21274 v8::Isolate::SuppressMicrotaskExecutionScope scope(env->GetIsolate());
21275 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021276 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21277 CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochda12d292016-06-02 14:46:10 +010021278 CHECK_EQ(4u, microtasks_completed_callback_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021279 }
21280
21281 CompileRun("1+1;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021282 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21283 CHECK_EQ(4, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
Ben Murdochda12d292016-06-02 14:46:10 +010021284 CHECK_EQ(5u, microtasks_completed_callback_count);
21285
21286 env->GetIsolate()->RemoveMicrotasksCompletedCallback(
21287 &MicrotasksCompletedCallback);
21288 env->GetIsolate()->EnqueueMicrotask(
21289 Function::New(env.local(), MicrotaskOne).ToLocalChecked());
21290 CompileRun("1+1;");
21291 CHECK_EQ(3, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21292 CHECK_EQ(4, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
21293 CHECK_EQ(5u, microtasks_completed_callback_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021294}
21295
21296
21297TEST(RunMicrotasksWithoutEnteringContext) {
21298 v8::Isolate* isolate = CcTest::isolate();
21299 HandleScope handle_scope(isolate);
Ben Murdochda12d292016-06-02 14:46:10 +010021300 isolate->SetMicrotasksPolicy(v8::MicrotasksPolicy::kExplicit);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021301 Local<Context> context = Context::New(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021302 {
21303 Context::Scope context_scope(context);
21304 CompileRun("var ext1Calls = 0;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021305 isolate->EnqueueMicrotask(
21306 Function::New(context, MicrotaskOne).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021307 }
21308 isolate->RunMicrotasks();
21309 {
21310 Context::Scope context_scope(context);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021311 CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(context).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021312 }
Ben Murdochda12d292016-06-02 14:46:10 +010021313 isolate->SetMicrotasksPolicy(v8::MicrotasksPolicy::kAuto);
21314}
21315
21316
21317TEST(ScopedMicrotasks) {
21318 LocalContext env;
21319 v8::HandleScope handles(env->GetIsolate());
21320 env->GetIsolate()->SetMicrotasksPolicy(v8::MicrotasksPolicy::kScoped);
21321 {
21322 v8::MicrotasksScope scope1(env->GetIsolate(),
21323 v8::MicrotasksScope::kDoNotRunMicrotasks);
21324 env->GetIsolate()->EnqueueMicrotask(
21325 Function::New(env.local(), MicrotaskOne).ToLocalChecked());
21326 CompileRun(
21327 "var ext1Calls = 0;"
21328 "var ext2Calls = 0;");
21329 CompileRun("1+1;");
21330 CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21331 CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
21332 {
21333 v8::MicrotasksScope scope2(env->GetIsolate(),
21334 v8::MicrotasksScope::kRunMicrotasks);
21335 CompileRun("1+1;");
21336 CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21337 CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
21338 {
21339 v8::MicrotasksScope scope3(env->GetIsolate(),
21340 v8::MicrotasksScope::kRunMicrotasks);
21341 CompileRun("1+1;");
21342 CHECK_EQ(0,
21343 CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21344 CHECK_EQ(0,
21345 CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
21346 }
21347 CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21348 CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
21349 }
21350 CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21351 CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
21352 env->GetIsolate()->EnqueueMicrotask(
21353 Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
21354 }
21355
21356 {
21357 v8::MicrotasksScope scope(env->GetIsolate(),
21358 v8::MicrotasksScope::kDoNotRunMicrotasks);
21359 CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21360 CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
21361 }
21362
21363 {
21364 v8::MicrotasksScope scope1(env->GetIsolate(),
21365 v8::MicrotasksScope::kRunMicrotasks);
21366 CompileRun("1+1;");
21367 CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21368 CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
21369 {
21370 v8::MicrotasksScope scope2(env->GetIsolate(),
21371 v8::MicrotasksScope::kDoNotRunMicrotasks);
21372 }
21373 CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21374 CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
21375 }
21376
21377 {
21378 v8::MicrotasksScope scope(env->GetIsolate(),
21379 v8::MicrotasksScope::kDoNotRunMicrotasks);
21380 CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21381 CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
21382 env->GetIsolate()->EnqueueMicrotask(
21383 Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
21384 }
21385
21386 {
21387 v8::Isolate::SuppressMicrotaskExecutionScope scope1(env->GetIsolate());
21388 {
21389 v8::MicrotasksScope scope2(env->GetIsolate(),
21390 v8::MicrotasksScope::kRunMicrotasks);
21391 }
21392 v8::MicrotasksScope scope3(env->GetIsolate(),
21393 v8::MicrotasksScope::kDoNotRunMicrotasks);
21394 CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21395 CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
21396 }
21397
21398 {
21399 v8::MicrotasksScope scope1(env->GetIsolate(),
21400 v8::MicrotasksScope::kRunMicrotasks);
21401 v8::MicrotasksScope::PerformCheckpoint(env->GetIsolate());
21402 CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21403 CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
21404 }
21405
21406 {
21407 v8::MicrotasksScope scope(env->GetIsolate(),
21408 v8::MicrotasksScope::kDoNotRunMicrotasks);
21409 CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21410 CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
21411 }
21412
21413 v8::MicrotasksScope::PerformCheckpoint(env->GetIsolate());
21414
21415 {
21416 v8::MicrotasksScope scope(env->GetIsolate(),
21417 v8::MicrotasksScope::kDoNotRunMicrotasks);
21418 CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21419 CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
21420 env->GetIsolate()->EnqueueMicrotask(
21421 Function::New(env.local(), MicrotaskTwo).ToLocalChecked());
21422 }
21423
21424 v8::MicrotasksScope::PerformCheckpoint(env->GetIsolate());
21425
21426 {
21427 v8::MicrotasksScope scope(env->GetIsolate(),
21428 v8::MicrotasksScope::kDoNotRunMicrotasks);
21429 CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21430 CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
21431 }
21432
21433 env->GetIsolate()->EnqueueMicrotask(
21434 Function::New(env.local(), MicrotaskOne).ToLocalChecked());
21435 {
21436 v8::Isolate::SuppressMicrotaskExecutionScope scope1(env->GetIsolate());
21437 v8::MicrotasksScope::PerformCheckpoint(env->GetIsolate());
21438 v8::MicrotasksScope scope2(env->GetIsolate(),
21439 v8::MicrotasksScope::kDoNotRunMicrotasks);
21440 CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21441 CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
21442 }
21443
21444 v8::MicrotasksScope::PerformCheckpoint(env->GetIsolate());
21445
21446 {
21447 v8::MicrotasksScope scope(env->GetIsolate(),
21448 v8::MicrotasksScope::kDoNotRunMicrotasks);
21449 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value(env.local()).FromJust());
21450 CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value(env.local()).FromJust());
21451 }
21452
21453 env->GetIsolate()->SetMicrotasksPolicy(v8::MicrotasksPolicy::kAuto);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021454}
21455
Emily Bernierd0a1eb72015-03-24 16:35:39 -040021456#ifdef ENABLE_DISASSEMBLER
Ben Murdoch61f157c2016-09-16 13:49:30 +010021457// FLAG_test_primary_stub_cache and FLAG_test_secondary_stub_cache are read
21458// only when ENABLE_DISASSEMBLER is not defined.
Ben Murdoch3ef787d2012-04-12 10:51:47 +010021459
Ben Murdoch61f157c2016-09-16 13:49:30 +010021460namespace {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010021461
Ben Murdoch61f157c2016-09-16 13:49:30 +010021462int probes_counter = 0;
21463int misses_counter = 0;
21464int updates_counter = 0;
21465
21466int* LookupCounter(const char* name) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010021467 if (strcmp(name, "c:V8.MegamorphicStubCacheProbes") == 0) {
21468 return &probes_counter;
21469 } else if (strcmp(name, "c:V8.MegamorphicStubCacheMisses") == 0) {
21470 return &misses_counter;
21471 } else if (strcmp(name, "c:V8.MegamorphicStubCacheUpdates") == 0) {
21472 return &updates_counter;
21473 }
21474 return NULL;
21475}
21476
Ben Murdoch61f157c2016-09-16 13:49:30 +010021477const char* kMegamorphicTestProgram =
21478 "function CreateClass(name) {\n"
21479 " var src = \n"
21480 " ` function ${name}() {};` +\n"
21481 " ` ${name}.prototype.foo = function() {};` +\n"
21482 " ` ${name};\\n`;\n"
21483 " return (0, eval)(src);\n"
21484 "}\n"
21485 "function fooify(obj) { obj.foo(); };\n"
21486 "var objs = [];\n"
21487 "for (var i = 0; i < 6; i++) {\n"
21488 " var Class = CreateClass('Class' + i);\n"
21489 " var obj = new Class();\n"
21490 " objs.push(obj);\n"
21491 "}\n"
21492 "for (var i = 0; i < 10000; i++) {\n"
21493 " for (var obj of objs) {\n"
21494 " fooify(obj);\n"
21495 " }\n"
21496 "}\n";
Ben Murdoch3ef787d2012-04-12 10:51:47 +010021497
Ben Murdoch61f157c2016-09-16 13:49:30 +010021498void StubCacheHelper(bool primary) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +010021499 i::FLAG_native_code_counters = true;
21500 if (primary) {
21501 i::FLAG_test_primary_stub_cache = true;
21502 } else {
21503 i::FLAG_test_secondary_stub_cache = true;
21504 }
21505 i::FLAG_crankshaft = false;
Ben Murdoch61f157c2016-09-16 13:49:30 +010021506 i::FLAG_turbo = false;
21507 v8::Isolate::CreateParams create_params;
21508 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
21509 create_params.counter_lookup_callback = LookupCounter;
21510 v8::Isolate* isolate = v8::Isolate::New(create_params);
21511 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
21512
21513 if (!i_isolate->snapshot_available()) {
21514 // The test is valid only for no-snapshot mode.
21515 v8::Isolate::Scope isolate_scope(isolate);
21516 LocalContext env(isolate);
21517 v8::HandleScope scope(isolate);
21518
21519 int initial_probes = probes_counter;
21520 int initial_misses = misses_counter;
21521 int initial_updates = updates_counter;
21522 CompileRun(kMegamorphicTestProgram);
21523 int probes = probes_counter - initial_probes;
21524 int misses = misses_counter - initial_misses;
21525 int updates = updates_counter - initial_updates;
21526 const int kClassesCount = 6;
21527 // Check that updates and misses counts are bounded.
21528 CHECK_LE(kClassesCount, updates);
21529 CHECK_LT(updates, kClassesCount * 3);
21530 CHECK_LE(1, misses);
21531 CHECK_LT(misses, kClassesCount * 2);
21532 // 2 is for PREMONOMORPHIC and MONOMORPHIC states,
21533 // 4 is for POLYMORPHIC states,
21534 // and all the others probes are for MEGAMORPHIC state.
21535 CHECK_EQ(10000 * kClassesCount - 2 - 4, probes);
21536 }
21537 isolate->Dispose();
Ben Murdoch3ef787d2012-04-12 10:51:47 +010021538}
21539
Ben Murdoch61f157c2016-09-16 13:49:30 +010021540} // namespace
Ben Murdoch3ef787d2012-04-12 10:51:47 +010021541
Ben Murdoch61f157c2016-09-16 13:49:30 +010021542UNINITIALIZED_TEST(PrimaryStubCache) { StubCacheHelper(true); }
Ben Murdoch3ef787d2012-04-12 10:51:47 +010021543
Ben Murdoch61f157c2016-09-16 13:49:30 +010021544UNINITIALIZED_TEST(SecondaryStubCache) { StubCacheHelper(false); }
Ben Murdoch3ef787d2012-04-12 10:51:47 +010021545
Ben Murdoch61f157c2016-09-16 13:49:30 +010021546#endif // ENABLE_DISASSEMBLER
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021547
21548#ifdef DEBUG
21549static int cow_arrays_created_runtime = 0;
21550
21551
21552static int* LookupCounterCOWArrays(const char* name) {
21553 if (strcmp(name, "c:V8.COWArraysCreatedRuntime") == 0) {
21554 return &cow_arrays_created_runtime;
21555 }
21556 return NULL;
21557}
21558#endif
21559
21560
21561TEST(CheckCOWArraysCreatedRuntimeCounter) {
21562#ifdef DEBUG
21563 i::FLAG_native_code_counters = true;
21564 LocalContext env;
21565 env->GetIsolate()->SetCounterFunction(LookupCounterCOWArrays);
21566 v8::HandleScope scope(env->GetIsolate());
21567 int initial_cow_arrays = cow_arrays_created_runtime;
21568 CompileRun("var o = [1, 2, 3];");
21569 CHECK_EQ(1, cow_arrays_created_runtime - initial_cow_arrays);
21570 CompileRun("var o = {foo: [4, 5, 6], bar: [3, 0]};");
21571 CHECK_EQ(3, cow_arrays_created_runtime - initial_cow_arrays);
21572 CompileRun("var o = {foo: [1, 2, 3, [4, 5, 6]], bar: 'hi'};");
21573 CHECK_EQ(4, cow_arrays_created_runtime - initial_cow_arrays);
21574#endif
21575}
21576
21577
21578TEST(StaticGetters) {
21579 LocalContext context;
21580 i::Factory* factory = CcTest::i_isolate()->factory();
21581 v8::Isolate* isolate = CcTest::isolate();
21582 v8::HandleScope scope(isolate);
21583 i::Handle<i::Object> undefined_value = factory->undefined_value();
21584 CHECK(*v8::Utils::OpenHandle(*v8::Undefined(isolate)) == *undefined_value);
21585 i::Handle<i::Object> null_value = factory->null_value();
21586 CHECK(*v8::Utils::OpenHandle(*v8::Null(isolate)) == *null_value);
21587 i::Handle<i::Object> true_value = factory->true_value();
21588 CHECK(*v8::Utils::OpenHandle(*v8::True(isolate)) == *true_value);
21589 i::Handle<i::Object> false_value = factory->false_value();
21590 CHECK(*v8::Utils::OpenHandle(*v8::False(isolate)) == *false_value);
21591}
21592
21593
21594UNINITIALIZED_TEST(IsolateEmbedderData) {
21595 CcTest::DisableAutomaticDispose();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021596 v8::Isolate::CreateParams create_params;
21597 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
21598 v8::Isolate* isolate = v8::Isolate::New(create_params);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021599 isolate->Enter();
21600 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
21601 for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021602 CHECK(!isolate->GetData(slot));
21603 CHECK(!i_isolate->GetData(slot));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021604 }
21605 for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
21606 void* data = reinterpret_cast<void*>(0xacce55ed + slot);
21607 isolate->SetData(slot, data);
21608 }
21609 for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
21610 void* data = reinterpret_cast<void*>(0xacce55ed + slot);
21611 CHECK_EQ(data, isolate->GetData(slot));
21612 CHECK_EQ(data, i_isolate->GetData(slot));
21613 }
21614 for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
21615 void* data = reinterpret_cast<void*>(0xdecea5ed + slot);
21616 isolate->SetData(slot, data);
21617 }
21618 for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
21619 void* data = reinterpret_cast<void*>(0xdecea5ed + slot);
21620 CHECK_EQ(data, isolate->GetData(slot));
21621 CHECK_EQ(data, i_isolate->GetData(slot));
21622 }
21623 isolate->Exit();
21624 isolate->Dispose();
21625}
21626
21627
21628TEST(StringEmpty) {
21629 LocalContext context;
21630 i::Factory* factory = CcTest::i_isolate()->factory();
21631 v8::Isolate* isolate = CcTest::isolate();
21632 v8::HandleScope scope(isolate);
21633 i::Handle<i::Object> empty_string = factory->empty_string();
21634 CHECK(*v8::Utils::OpenHandle(*v8::String::Empty(isolate)) == *empty_string);
21635}
21636
21637
21638static int instance_checked_getter_count = 0;
21639static void InstanceCheckedGetter(
21640 Local<String> name,
21641 const v8::PropertyCallbackInfo<v8::Value>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021642 CHECK(name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
21643 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021644 instance_checked_getter_count++;
21645 info.GetReturnValue().Set(v8_num(11));
21646}
21647
21648
21649static int instance_checked_setter_count = 0;
21650static void InstanceCheckedSetter(Local<String> name,
21651 Local<Value> value,
21652 const v8::PropertyCallbackInfo<void>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021653 CHECK(name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("foo"))
21654 .FromJust());
21655 CHECK(value->Equals(info.GetIsolate()->GetCurrentContext(), v8_num(23))
21656 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021657 instance_checked_setter_count++;
21658}
21659
21660
21661static void CheckInstanceCheckedResult(int getters, int setters,
21662 bool expects_callbacks,
21663 TryCatch* try_catch) {
21664 if (expects_callbacks) {
21665 CHECK(!try_catch->HasCaught());
21666 CHECK_EQ(getters, instance_checked_getter_count);
21667 CHECK_EQ(setters, instance_checked_setter_count);
21668 } else {
21669 CHECK(try_catch->HasCaught());
21670 CHECK_EQ(0, instance_checked_getter_count);
21671 CHECK_EQ(0, instance_checked_setter_count);
21672 }
21673 try_catch->Reset();
21674}
21675
21676
21677static void CheckInstanceCheckedAccessors(bool expects_callbacks) {
21678 instance_checked_getter_count = 0;
21679 instance_checked_setter_count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021680 TryCatch try_catch(CcTest::isolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021681
21682 // Test path through generic runtime code.
21683 CompileRun("obj.foo");
21684 CheckInstanceCheckedResult(1, 0, expects_callbacks, &try_catch);
21685 CompileRun("obj.foo = 23");
21686 CheckInstanceCheckedResult(1, 1, expects_callbacks, &try_catch);
21687
21688 // Test path through generated LoadIC and StoredIC.
21689 CompileRun("function test_get(o) { o.foo; }"
21690 "test_get(obj);");
21691 CheckInstanceCheckedResult(2, 1, expects_callbacks, &try_catch);
21692 CompileRun("test_get(obj);");
21693 CheckInstanceCheckedResult(3, 1, expects_callbacks, &try_catch);
21694 CompileRun("test_get(obj);");
21695 CheckInstanceCheckedResult(4, 1, expects_callbacks, &try_catch);
21696 CompileRun("function test_set(o) { o.foo = 23; }"
21697 "test_set(obj);");
21698 CheckInstanceCheckedResult(4, 2, expects_callbacks, &try_catch);
21699 CompileRun("test_set(obj);");
21700 CheckInstanceCheckedResult(4, 3, expects_callbacks, &try_catch);
21701 CompileRun("test_set(obj);");
21702 CheckInstanceCheckedResult(4, 4, expects_callbacks, &try_catch);
21703
21704 // Test path through optimized code.
21705 CompileRun("%OptimizeFunctionOnNextCall(test_get);"
21706 "test_get(obj);");
21707 CheckInstanceCheckedResult(5, 4, expects_callbacks, &try_catch);
21708 CompileRun("%OptimizeFunctionOnNextCall(test_set);"
21709 "test_set(obj);");
21710 CheckInstanceCheckedResult(5, 5, expects_callbacks, &try_catch);
21711
21712 // Cleanup so that closures start out fresh in next check.
21713 CompileRun("%DeoptimizeFunction(test_get);"
21714 "%ClearFunctionTypeFeedback(test_get);"
21715 "%DeoptimizeFunction(test_set);"
21716 "%ClearFunctionTypeFeedback(test_set);");
21717}
21718
21719
21720THREADED_TEST(InstanceCheckOnInstanceAccessor) {
21721 v8::internal::FLAG_allow_natives_syntax = true;
21722 LocalContext context;
21723 v8::HandleScope scope(context->GetIsolate());
21724
21725 Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
21726 Local<ObjectTemplate> inst = templ->InstanceTemplate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021727 inst->SetAccessor(v8_str("foo"), InstanceCheckedGetter, InstanceCheckedSetter,
21728 Local<Value>(), v8::DEFAULT, v8::None,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021729 v8::AccessorSignature::New(context->GetIsolate(), templ));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021730 CHECK(context->Global()
21731 ->Set(context.local(), v8_str("f"),
21732 templ->GetFunction(context.local()).ToLocalChecked())
21733 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021734
21735 printf("Testing positive ...\n");
21736 CompileRun("var obj = new f();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021737 CHECK(templ->HasInstance(
21738 context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021739 CheckInstanceCheckedAccessors(true);
21740
21741 printf("Testing negative ...\n");
21742 CompileRun("var obj = {};"
21743 "obj.__proto__ = new f();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021744 CHECK(!templ->HasInstance(
21745 context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021746 CheckInstanceCheckedAccessors(false);
21747}
21748
21749
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021750static void EmptyInterceptorGetter(
21751 Local<String> name, const v8::PropertyCallbackInfo<v8::Value>& info) {}
21752
21753
21754static void EmptyInterceptorSetter(
21755 Local<String> name, Local<Value> value,
21756 const v8::PropertyCallbackInfo<v8::Value>& info) {}
21757
21758
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021759THREADED_TEST(InstanceCheckOnInstanceAccessorWithInterceptor) {
21760 v8::internal::FLAG_allow_natives_syntax = true;
21761 LocalContext context;
21762 v8::HandleScope scope(context->GetIsolate());
21763
21764 Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
21765 Local<ObjectTemplate> inst = templ->InstanceTemplate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021766 templ->InstanceTemplate()->SetNamedPropertyHandler(EmptyInterceptorGetter,
21767 EmptyInterceptorSetter);
21768 inst->SetAccessor(v8_str("foo"), InstanceCheckedGetter, InstanceCheckedSetter,
21769 Local<Value>(), v8::DEFAULT, v8::None,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021770 v8::AccessorSignature::New(context->GetIsolate(), templ));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021771 CHECK(context->Global()
21772 ->Set(context.local(), v8_str("f"),
21773 templ->GetFunction(context.local()).ToLocalChecked())
21774 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021775
21776 printf("Testing positive ...\n");
21777 CompileRun("var obj = new f();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021778 CHECK(templ->HasInstance(
21779 context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021780 CheckInstanceCheckedAccessors(true);
21781
21782 printf("Testing negative ...\n");
21783 CompileRun("var obj = {};"
21784 "obj.__proto__ = new f();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021785 CHECK(!templ->HasInstance(
21786 context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021787 CheckInstanceCheckedAccessors(false);
21788}
21789
21790
21791THREADED_TEST(InstanceCheckOnPrototypeAccessor) {
21792 v8::internal::FLAG_allow_natives_syntax = true;
21793 LocalContext context;
21794 v8::HandleScope scope(context->GetIsolate());
21795
21796 Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
21797 Local<ObjectTemplate> proto = templ->PrototypeTemplate();
21798 proto->SetAccessor(v8_str("foo"), InstanceCheckedGetter,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021799 InstanceCheckedSetter, Local<Value>(), v8::DEFAULT,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021800 v8::None,
21801 v8::AccessorSignature::New(context->GetIsolate(), templ));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021802 CHECK(context->Global()
21803 ->Set(context.local(), v8_str("f"),
21804 templ->GetFunction(context.local()).ToLocalChecked())
21805 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021806
21807 printf("Testing positive ...\n");
21808 CompileRun("var obj = new f();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021809 CHECK(templ->HasInstance(
21810 context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021811 CheckInstanceCheckedAccessors(true);
21812
21813 printf("Testing negative ...\n");
21814 CompileRun("var obj = {};"
21815 "obj.__proto__ = new f();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021816 CHECK(!templ->HasInstance(
21817 context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021818 CheckInstanceCheckedAccessors(false);
21819
21820 printf("Testing positive with modified prototype chain ...\n");
21821 CompileRun("var obj = new f();"
21822 "var pro = {};"
21823 "pro.__proto__ = obj.__proto__;"
21824 "obj.__proto__ = pro;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021825 CHECK(templ->HasInstance(
21826 context->Global()->Get(context.local(), v8_str("obj")).ToLocalChecked()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021827 CheckInstanceCheckedAccessors(true);
21828}
21829
21830
21831TEST(TryFinallyMessage) {
21832 LocalContext context;
21833 v8::HandleScope scope(context->GetIsolate());
21834 {
21835 // Test that the original error message is not lost if there is a
21836 // recursive call into Javascript is done in the finally block, e.g. to
21837 // initialize an IC. (crbug.com/129171)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021838 TryCatch try_catch(context->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021839 const char* trigger_ic =
21840 "try { \n"
21841 " throw new Error('test'); \n"
21842 "} finally { \n"
21843 " var x = 0; \n"
21844 " x++; \n" // Trigger an IC initialization here.
21845 "} \n";
21846 CompileRun(trigger_ic);
21847 CHECK(try_catch.HasCaught());
21848 Local<Message> message = try_catch.Message();
21849 CHECK(!message.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021850 CHECK_EQ(2, message->GetLineNumber(context.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021851 }
21852
21853 {
21854 // Test that the original exception message is indeed overwritten if
21855 // a new error is thrown in the finally block.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021856 TryCatch try_catch(context->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021857 const char* throw_again =
21858 "try { \n"
21859 " throw new Error('test'); \n"
21860 "} finally { \n"
21861 " var x = 0; \n"
21862 " x++; \n"
21863 " throw new Error('again'); \n" // This is the new uncaught error.
21864 "} \n";
21865 CompileRun(throw_again);
21866 CHECK(try_catch.HasCaught());
21867 Local<Message> message = try_catch.Message();
21868 CHECK(!message.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021869 CHECK_EQ(6, message->GetLineNumber(context.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021870 }
21871}
21872
21873
21874static void Helper137002(bool do_store,
21875 bool polymorphic,
21876 bool remove_accessor,
21877 bool interceptor) {
21878 LocalContext context;
21879 Local<ObjectTemplate> templ = ObjectTemplate::New(context->GetIsolate());
21880 if (interceptor) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040021881 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(FooGetInterceptor,
21882 FooSetInterceptor));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021883 } else {
21884 templ->SetAccessor(v8_str("foo"),
21885 GetterWhichReturns42,
21886 SetterWhichSetsYOnThisTo23);
21887 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021888 CHECK(context->Global()
21889 ->Set(context.local(), v8_str("obj"),
21890 templ->NewInstance(context.local()).ToLocalChecked())
21891 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021892
21893 // Turn monomorphic on slow object with native accessor, then turn
21894 // polymorphic, finally optimize to create negative lookup and fail.
21895 CompileRun(do_store ?
21896 "function f(x) { x.foo = void 0; }" :
21897 "function f(x) { return x.foo; }");
21898 CompileRun("obj.y = void 0;");
21899 if (!interceptor) {
21900 CompileRun("%OptimizeObjectForAddingMultipleProperties(obj, 1);");
21901 }
21902 CompileRun("obj.__proto__ = null;"
21903 "f(obj); f(obj); f(obj);");
21904 if (polymorphic) {
21905 CompileRun("f({});");
21906 }
21907 CompileRun("obj.y = void 0;"
21908 "%OptimizeFunctionOnNextCall(f);");
21909 if (remove_accessor) {
21910 CompileRun("delete obj.foo;");
21911 }
21912 CompileRun("var result = f(obj);");
21913 if (do_store) {
21914 CompileRun("result = obj.y;");
21915 }
21916 if (remove_accessor && !interceptor) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021917 CHECK(context->Global()
21918 ->Get(context.local(), v8_str("result"))
21919 .ToLocalChecked()
21920 ->IsUndefined());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021921 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021922 CHECK_EQ(do_store ? 23 : 42, context->Global()
21923 ->Get(context.local(), v8_str("result"))
21924 .ToLocalChecked()
21925 ->Int32Value(context.local())
21926 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021927 }
21928}
21929
21930
21931THREADED_TEST(Regress137002a) {
21932 i::FLAG_allow_natives_syntax = true;
21933 i::FLAG_compilation_cache = false;
21934 v8::HandleScope scope(CcTest::isolate());
21935 for (int i = 0; i < 16; i++) {
21936 Helper137002(i & 8, i & 4, i & 2, i & 1);
21937 }
21938}
21939
21940
21941THREADED_TEST(Regress137002b) {
21942 i::FLAG_allow_natives_syntax = true;
21943 LocalContext context;
21944 v8::Isolate* isolate = context->GetIsolate();
21945 v8::HandleScope scope(isolate);
21946 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
21947 templ->SetAccessor(v8_str("foo"),
21948 GetterWhichReturns42,
21949 SetterWhichSetsYOnThisTo23);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021950 CHECK(context->Global()
21951 ->Set(context.local(), v8_str("obj"),
21952 templ->NewInstance(context.local()).ToLocalChecked())
21953 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021954
21955 // Turn monomorphic on slow object with native accessor, then just
21956 // delete the property and fail.
21957 CompileRun("function load(x) { return x.foo; }"
21958 "function store(x) { x.foo = void 0; }"
21959 "function keyed_load(x, key) { return x[key]; }"
21960 // Second version of function has a different source (add void 0)
21961 // so that it does not share code with the first version. This
21962 // ensures that the ICs are monomorphic.
21963 "function load2(x) { void 0; return x.foo; }"
21964 "function store2(x) { void 0; x.foo = void 0; }"
21965 "function keyed_load2(x, key) { void 0; return x[key]; }"
21966
21967 "obj.y = void 0;"
21968 "obj.__proto__ = null;"
21969 "var subobj = {};"
21970 "subobj.y = void 0;"
21971 "subobj.__proto__ = obj;"
21972 "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
21973
21974 // Make the ICs monomorphic.
21975 "load(obj); load(obj);"
21976 "load2(subobj); load2(subobj);"
21977 "store(obj); store(obj);"
21978 "store2(subobj); store2(subobj);"
21979 "keyed_load(obj, 'foo'); keyed_load(obj, 'foo');"
21980 "keyed_load2(subobj, 'foo'); keyed_load2(subobj, 'foo');"
21981
21982 // Actually test the shiny new ICs and better not crash. This
21983 // serves as a regression test for issue 142088 as well.
21984 "load(obj);"
21985 "load2(subobj);"
21986 "store(obj);"
21987 "store2(subobj);"
21988 "keyed_load(obj, 'foo');"
21989 "keyed_load2(subobj, 'foo');"
21990
21991 // Delete the accessor. It better not be called any more now.
21992 "delete obj.foo;"
21993 "obj.y = void 0;"
21994 "subobj.y = void 0;"
21995
21996 "var load_result = load(obj);"
21997 "var load_result2 = load2(subobj);"
21998 "var keyed_load_result = keyed_load(obj, 'foo');"
21999 "var keyed_load_result2 = keyed_load2(subobj, 'foo');"
22000 "store(obj);"
22001 "store2(subobj);"
22002 "var y_from_obj = obj.y;"
22003 "var y_from_subobj = subobj.y;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022004 CHECK(context->Global()
22005 ->Get(context.local(), v8_str("load_result"))
22006 .ToLocalChecked()
22007 ->IsUndefined());
22008 CHECK(context->Global()
22009 ->Get(context.local(), v8_str("load_result2"))
22010 .ToLocalChecked()
22011 ->IsUndefined());
22012 CHECK(context->Global()
22013 ->Get(context.local(), v8_str("keyed_load_result"))
22014 .ToLocalChecked()
22015 ->IsUndefined());
22016 CHECK(context->Global()
22017 ->Get(context.local(), v8_str("keyed_load_result2"))
22018 .ToLocalChecked()
22019 ->IsUndefined());
22020 CHECK(context->Global()
22021 ->Get(context.local(), v8_str("y_from_obj"))
22022 .ToLocalChecked()
22023 ->IsUndefined());
22024 CHECK(context->Global()
22025 ->Get(context.local(), v8_str("y_from_subobj"))
22026 .ToLocalChecked()
22027 ->IsUndefined());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022028}
22029
22030
22031THREADED_TEST(Regress142088) {
22032 i::FLAG_allow_natives_syntax = true;
22033 LocalContext context;
22034 v8::Isolate* isolate = context->GetIsolate();
22035 v8::HandleScope scope(isolate);
22036 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
22037 templ->SetAccessor(v8_str("foo"),
22038 GetterWhichReturns42,
22039 SetterWhichSetsYOnThisTo23);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022040 CHECK(context->Global()
22041 ->Set(context.local(), v8_str("obj"),
22042 templ->NewInstance(context.local()).ToLocalChecked())
22043 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022044
22045 CompileRun("function load(x) { return x.foo; }"
22046 "var o = Object.create(obj);"
22047 "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
22048 "load(o); load(o); load(o); load(o);");
22049}
22050
22051
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022052THREADED_TEST(Regress137496) {
22053 i::FLAG_expose_gc = true;
22054 LocalContext context;
22055 v8::HandleScope scope(context->GetIsolate());
22056
22057 // Compile a try-finally clause where the finally block causes a GC
22058 // while there still is a message pending for external reporting.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022059 TryCatch try_catch(context->GetIsolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022060 try_catch.SetVerbose(true);
22061 CompileRun("try { throw new Error(); } finally { gc(); }");
22062 CHECK(try_catch.HasCaught());
22063}
22064
22065
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022066THREADED_TEST(Regress157124) {
22067 LocalContext context;
22068 v8::Isolate* isolate = context->GetIsolate();
22069 v8::HandleScope scope(isolate);
22070 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022071 Local<Object> obj = templ->NewInstance(context.local()).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022072 obj->GetIdentityHash();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022073 obj->DeletePrivate(context.local(),
22074 v8::Private::ForApi(isolate, v8_str("Bug")))
22075 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022076}
22077
22078
22079THREADED_TEST(Regress2535) {
22080 LocalContext context;
22081 v8::HandleScope scope(context->GetIsolate());
22082 Local<Value> set_value = CompileRun("new Set();");
22083 Local<Object> set_object(Local<Object>::Cast(set_value));
22084 CHECK_EQ(0, set_object->InternalFieldCount());
22085 Local<Value> map_value = CompileRun("new Map();");
22086 Local<Object> map_object(Local<Object>::Cast(map_value));
22087 CHECK_EQ(0, map_object->InternalFieldCount());
22088}
22089
22090
22091THREADED_TEST(Regress2746) {
22092 LocalContext context;
22093 v8::Isolate* isolate = context->GetIsolate();
22094 v8::HandleScope scope(isolate);
22095 Local<Object> obj = Object::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022096 Local<v8::Private> key = v8::Private::New(isolate, v8_str("key"));
22097 CHECK(
22098 obj->SetPrivate(context.local(), key, v8::Undefined(isolate)).FromJust());
22099 Local<Value> value = obj->GetPrivate(context.local(), key).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022100 CHECK(!value.IsEmpty());
22101 CHECK(value->IsUndefined());
22102}
22103
22104
22105THREADED_TEST(Regress260106) {
22106 LocalContext context;
22107 v8::Isolate* isolate = context->GetIsolate();
22108 v8::HandleScope scope(isolate);
22109 Local<FunctionTemplate> templ = FunctionTemplate::New(isolate,
22110 DummyCallHandler);
22111 CompileRun("for (var i = 0; i < 128; i++) Object.prototype[i] = 0;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022112 Local<Function> function =
22113 templ->GetFunction(context.local()).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022114 CHECK(!function.IsEmpty());
22115 CHECK(function->IsFunction());
22116}
22117
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022118THREADED_TEST(JSONParseObject) {
22119 LocalContext context;
22120 HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022121 Local<Value> obj =
Ben Murdochc5610432016-08-08 18:44:38 +010022122 v8::JSON::Parse(context.local(), v8_str("{\"x\":42}")).ToLocalChecked();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022123 Local<Object> global = context->Global();
22124 global->Set(context.local(), v8_str("obj"), obj).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022125 ExpectString("JSON.stringify(obj)", "{\"x\":42}");
22126}
22127
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022128THREADED_TEST(JSONParseNumber) {
22129 LocalContext context;
22130 HandleScope scope(context->GetIsolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022131 Local<Value> obj =
Ben Murdochc5610432016-08-08 18:44:38 +010022132 v8::JSON::Parse(context.local(), v8_str("42")).ToLocalChecked();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022133 Local<Object> global = context->Global();
22134 global->Set(context.local(), v8_str("obj"), obj).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022135 ExpectString("JSON.stringify(obj)", "42");
22136}
22137
Ben Murdochc5610432016-08-08 18:44:38 +010022138THREADED_TEST(JSONStringifyObject) {
22139 LocalContext context;
22140 HandleScope scope(context->GetIsolate());
22141 Local<Value> value =
22142 v8::JSON::Parse(context.local(), v8_str("{\"x\":42}")).ToLocalChecked();
22143 Local<Object> obj = value->ToObject(context.local()).ToLocalChecked();
22144 Local<Object> global = context->Global();
22145 global->Set(context.local(), v8_str("obj"), obj).FromJust();
22146 Local<String> json =
22147 v8::JSON::Stringify(context.local(), obj).ToLocalChecked();
22148 v8::String::Utf8Value utf8(json);
22149 ExpectString("JSON.stringify(obj)", *utf8);
22150}
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022151
Ben Murdoch61f157c2016-09-16 13:49:30 +010022152THREADED_TEST(JSONStringifyObjectWithGap) {
22153 LocalContext context;
22154 HandleScope scope(context->GetIsolate());
22155 Local<Value> value =
22156 v8::JSON::Parse(context.local(), v8_str("{\"x\":42}")).ToLocalChecked();
22157 Local<Object> obj = value->ToObject(context.local()).ToLocalChecked();
22158 Local<Object> global = context->Global();
22159 global->Set(context.local(), v8_str("obj"), obj).FromJust();
22160 Local<String> json =
22161 v8::JSON::Stringify(context.local(), obj, v8_str("*")).ToLocalChecked();
22162 v8::String::Utf8Value utf8(json);
22163 ExpectString("JSON.stringify(obj, null, '*')", *utf8);
22164}
22165
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022166#if V8_OS_POSIX && !V8_OS_NACL
22167class ThreadInterruptTest {
22168 public:
22169 ThreadInterruptTest() : sem_(0), sem_value_(0) { }
22170 ~ThreadInterruptTest() {}
22171
22172 void RunTest() {
22173 InterruptThread i_thread(this);
22174 i_thread.Start();
22175
22176 sem_.Wait();
22177 CHECK_EQ(kExpectedValue, sem_value_);
22178 }
22179
22180 private:
22181 static const int kExpectedValue = 1;
22182
22183 class InterruptThread : public v8::base::Thread {
22184 public:
22185 explicit InterruptThread(ThreadInterruptTest* test)
22186 : Thread(Options("InterruptThread")), test_(test) {}
22187
22188 virtual void Run() {
22189 struct sigaction action;
22190
22191 // Ensure that we'll enter waiting condition
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022192 v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(100));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022193
22194 // Setup signal handler
22195 memset(&action, 0, sizeof(action));
22196 action.sa_handler = SignalHandler;
22197 sigaction(SIGCHLD, &action, NULL);
22198
22199 // Send signal
22200 kill(getpid(), SIGCHLD);
22201
22202 // Ensure that if wait has returned because of error
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022203 v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(100));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022204
22205 // Set value and signal semaphore
22206 test_->sem_value_ = 1;
22207 test_->sem_.Signal();
22208 }
22209
22210 static void SignalHandler(int signal) {
22211 }
22212
22213 private:
22214 ThreadInterruptTest* test_;
22215 };
22216
22217 v8::base::Semaphore sem_;
22218 volatile int sem_value_;
22219};
22220
22221
22222THREADED_TEST(SemaphoreInterruption) {
22223 ThreadInterruptTest().RunTest();
22224}
22225
22226
22227#endif // V8_OS_POSIX
22228
22229
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022230void UnreachableCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
22231 CHECK(false);
22232}
22233
22234
22235TEST(JSONStringifyAccessCheck) {
22236 v8::V8::Initialize();
22237 v8::Isolate* isolate = CcTest::isolate();
22238 v8::HandleScope scope(isolate);
22239
22240 // Create an ObjectTemplate for global objects and install access
22241 // check callbacks that will block access.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022242 v8::Local<v8::ObjectTemplate> global_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022243 v8::ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022244 global_template->SetAccessCheckCallback(AccessAlwaysBlocked);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022245
22246 // Create a context and set an x property on it's global object.
22247 LocalContext context0(NULL, global_template);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022248 v8::Local<v8::Object> global0 = context0->Global();
22249 global0->Set(context0.local(), v8_str("x"), v8_num(42)).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022250 ExpectString("JSON.stringify(this)", "{\"x\":42}");
22251
22252 for (int i = 0; i < 2; i++) {
22253 if (i == 1) {
22254 // Install a toJSON function on the second run.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022255 v8::Local<v8::FunctionTemplate> toJSON =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022256 v8::FunctionTemplate::New(isolate, UnreachableCallback);
22257
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022258 global0->Set(context0.local(), v8_str("toJSON"),
22259 toJSON->GetFunction(context0.local()).ToLocalChecked())
22260 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022261 }
22262 // Create a context with a different security token so that the
22263 // failed access check callback will be called on each access.
22264 LocalContext context1(NULL, global_template);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022265 CHECK(context1->Global()
22266 ->Set(context1.local(), v8_str("other"), global0)
22267 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022268
22269 CHECK(CompileRun("JSON.stringify(other)").IsEmpty());
22270 CHECK(CompileRun("JSON.stringify({ 'a' : other, 'b' : ['c'] })").IsEmpty());
22271 CHECK(CompileRun("JSON.stringify([other, 'b', 'c'])").IsEmpty());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022272 }
22273}
22274
22275
22276bool access_check_fail_thrown = false;
22277bool catch_callback_called = false;
22278
22279
22280// Failed access check callback that performs a GC on each invocation.
22281void FailedAccessCheckThrows(Local<v8::Object> target,
22282 v8::AccessType type,
22283 Local<v8::Value> data) {
22284 access_check_fail_thrown = true;
22285 i::PrintF("Access check failed. Error thrown.\n");
22286 CcTest::isolate()->ThrowException(
22287 v8::Exception::Error(v8_str("cross context")));
22288}
22289
22290
22291void CatcherCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
22292 for (int i = 0; i < args.Length(); i++) {
22293 i::PrintF("%s\n", *String::Utf8Value(args[i]));
22294 }
22295 catch_callback_called = true;
22296}
22297
22298
22299void HasOwnPropertyCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022300 v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
22301 CHECK(
22302 args[0]
22303 ->ToObject(context)
22304 .ToLocalChecked()
22305 ->HasOwnProperty(context, args[1]->ToString(context).ToLocalChecked())
22306 .IsNothing());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022307}
22308
22309
22310void CheckCorrectThrow(const char* script) {
22311 // Test that the script, when wrapped into a try-catch, triggers the catch
22312 // clause due to failed access check throwing an exception.
22313 // The subsequent try-catch should run without any exception.
22314 access_check_fail_thrown = false;
22315 catch_callback_called = false;
22316 i::ScopedVector<char> source(1024);
22317 i::SNPrintF(source, "try { %s; } catch (e) { catcher(e); }", script);
22318 CompileRun(source.start());
22319 CHECK(access_check_fail_thrown);
22320 CHECK(catch_callback_called);
22321
22322 access_check_fail_thrown = false;
22323 catch_callback_called = false;
22324 CompileRun("try { [1, 2, 3].sort(); } catch (e) { catcher(e) };");
22325 CHECK(!access_check_fail_thrown);
22326 CHECK(!catch_callback_called);
22327}
22328
22329
22330TEST(AccessCheckThrows) {
22331 i::FLAG_allow_natives_syntax = true;
22332 v8::V8::Initialize();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022333 v8::Isolate* isolate = CcTest::isolate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022334 isolate->SetFailedAccessCheckCallbackFunction(&FailedAccessCheckThrows);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022335 v8::HandleScope scope(isolate);
22336
22337 // Create an ObjectTemplate for global objects and install access
22338 // check callbacks that will block access.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022339 v8::Local<v8::ObjectTemplate> global_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022340 v8::ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022341 global_template->SetAccessCheckCallback(AccessAlwaysBlocked);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022342
22343 // Create a context and set an x property on it's global object.
22344 LocalContext context0(NULL, global_template);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022345 v8::Local<v8::Object> global0 = context0->Global();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022346
22347 // Create a context with a different security token so that the
22348 // failed access check callback will be called on each access.
22349 LocalContext context1(NULL, global_template);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022350 CHECK(context1->Global()
22351 ->Set(context1.local(), v8_str("other"), global0)
22352 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022353
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022354 v8::Local<v8::FunctionTemplate> catcher_fun =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022355 v8::FunctionTemplate::New(isolate, CatcherCallback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022356 CHECK(context1->Global()
22357 ->Set(context1.local(), v8_str("catcher"),
22358 catcher_fun->GetFunction(context1.local()).ToLocalChecked())
22359 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022360
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022361 v8::Local<v8::FunctionTemplate> has_own_property_fun =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022362 v8::FunctionTemplate::New(isolate, HasOwnPropertyCallback);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022363 CHECK(context1->Global()
22364 ->Set(context1.local(), v8_str("has_own_property"),
22365 has_own_property_fun->GetFunction(context1.local())
22366 .ToLocalChecked())
22367 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022368
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022369 {
22370 v8::TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022371 access_check_fail_thrown = false;
22372 CompileRun("other.x;");
22373 CHECK(access_check_fail_thrown);
22374 CHECK(try_catch.HasCaught());
22375 }
22376
22377 CheckCorrectThrow("other.x");
22378 CheckCorrectThrow("other[1]");
22379 CheckCorrectThrow("JSON.stringify(other)");
22380 CheckCorrectThrow("has_own_property(other, 'x')");
22381 CheckCorrectThrow("%GetProperty(other, 'x')");
22382 CheckCorrectThrow("%SetProperty(other, 'x', 'foo', 0)");
22383 CheckCorrectThrow("%AddNamedProperty(other, 'x', 'foo', 1)");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022384 CheckCorrectThrow("%DeleteProperty_Sloppy(other, 'x')");
22385 CheckCorrectThrow("%DeleteProperty_Strict(other, 'x')");
22386 CheckCorrectThrow("%DeleteProperty_Sloppy(other, '1')");
22387 CheckCorrectThrow("%DeleteProperty_Strict(other, '1')");
Ben Murdochda12d292016-06-02 14:46:10 +010022388 CheckCorrectThrow("Object.prototype.hasOwnProperty.call(other, 'x')");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022389 CheckCorrectThrow("%HasProperty('x', other)");
22390 CheckCorrectThrow("%PropertyIsEnumerable(other, 'x')");
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022391 // PROPERTY_ATTRIBUTES_NONE = 0
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022392 CheckCorrectThrow("%DefineAccessorPropertyUnchecked("
22393 "other, 'x', null, null, 1)");
22394
22395 // Reset the failed access check callback so it does not influence
22396 // the other tests.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022397 isolate->SetFailedAccessCheckCallbackFunction(NULL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022398}
22399
22400
22401class RequestInterruptTestBase {
22402 public:
22403 RequestInterruptTestBase()
22404 : env_(),
22405 isolate_(env_->GetIsolate()),
22406 sem_(0),
22407 warmup_(20000),
22408 should_continue_(true) {
22409 }
22410
22411 virtual ~RequestInterruptTestBase() { }
22412
22413 virtual void StartInterruptThread() = 0;
22414
22415 virtual void TestBody() = 0;
22416
22417 void RunTest() {
22418 StartInterruptThread();
22419
22420 v8::HandleScope handle_scope(isolate_);
22421
22422 TestBody();
22423
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022424 // Verify we arrived here because interruptor was called
22425 // not due to a bug causing us to exit the loop too early.
22426 CHECK(!should_continue());
22427 }
22428
22429 void WakeUpInterruptor() {
22430 sem_.Signal();
22431 }
22432
22433 bool should_continue() const { return should_continue_; }
22434
22435 bool ShouldContinue() {
22436 if (warmup_ > 0) {
22437 if (--warmup_ == 0) {
22438 WakeUpInterruptor();
22439 }
22440 }
22441
22442 return should_continue_;
22443 }
22444
22445 static void ShouldContinueCallback(
22446 const v8::FunctionCallbackInfo<Value>& info) {
22447 RequestInterruptTestBase* test =
22448 reinterpret_cast<RequestInterruptTestBase*>(
22449 info.Data().As<v8::External>()->Value());
22450 info.GetReturnValue().Set(test->ShouldContinue());
22451 }
22452
22453 LocalContext env_;
22454 v8::Isolate* isolate_;
22455 v8::base::Semaphore sem_;
22456 int warmup_;
22457 bool should_continue_;
22458};
22459
22460
22461class RequestInterruptTestBaseWithSimpleInterrupt
22462 : public RequestInterruptTestBase {
22463 public:
22464 RequestInterruptTestBaseWithSimpleInterrupt() : i_thread(this) { }
22465
22466 virtual void StartInterruptThread() {
22467 i_thread.Start();
22468 }
22469
22470 private:
22471 class InterruptThread : public v8::base::Thread {
22472 public:
22473 explicit InterruptThread(RequestInterruptTestBase* test)
22474 : Thread(Options("RequestInterruptTest")), test_(test) {}
22475
22476 virtual void Run() {
22477 test_->sem_.Wait();
22478 test_->isolate_->RequestInterrupt(&OnInterrupt, test_);
22479 }
22480
22481 static void OnInterrupt(v8::Isolate* isolate, void* data) {
22482 reinterpret_cast<RequestInterruptTestBase*>(data)->
22483 should_continue_ = false;
22484 }
22485
22486 private:
22487 RequestInterruptTestBase* test_;
22488 };
22489
22490 InterruptThread i_thread;
22491};
22492
22493
22494class RequestInterruptTestWithFunctionCall
22495 : public RequestInterruptTestBaseWithSimpleInterrupt {
22496 public:
22497 virtual void TestBody() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022498 Local<Function> func = Function::New(env_.local(), ShouldContinueCallback,
22499 v8::External::New(isolate_, this))
22500 .ToLocalChecked();
22501 CHECK(env_->Global()
22502 ->Set(env_.local(), v8_str("ShouldContinue"), func)
22503 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022504
22505 CompileRun("while (ShouldContinue()) { }");
22506 }
22507};
22508
22509
22510class RequestInterruptTestWithMethodCall
22511 : public RequestInterruptTestBaseWithSimpleInterrupt {
22512 public:
22513 virtual void TestBody() {
22514 v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
22515 v8::Local<v8::Template> proto = t->PrototypeTemplate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022516 proto->Set(v8_str("shouldContinue"),
Ben Murdoch097c5b22016-05-18 11:27:45 +010022517 FunctionTemplate::New(isolate_, ShouldContinueCallback,
22518 v8::External::New(isolate_, this)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022519 CHECK(env_->Global()
22520 ->Set(env_.local(), v8_str("Klass"),
22521 t->GetFunction(env_.local()).ToLocalChecked())
22522 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022523
22524 CompileRun("var obj = new Klass; while (obj.shouldContinue()) { }");
22525 }
22526};
22527
22528
22529class RequestInterruptTestWithAccessor
22530 : public RequestInterruptTestBaseWithSimpleInterrupt {
22531 public:
22532 virtual void TestBody() {
22533 v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
22534 v8::Local<v8::Template> proto = t->PrototypeTemplate();
22535 proto->SetAccessorProperty(v8_str("shouldContinue"), FunctionTemplate::New(
22536 isolate_, ShouldContinueCallback, v8::External::New(isolate_, this)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022537 CHECK(env_->Global()
22538 ->Set(env_.local(), v8_str("Klass"),
22539 t->GetFunction(env_.local()).ToLocalChecked())
22540 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022541
22542 CompileRun("var obj = new Klass; while (obj.shouldContinue) { }");
22543 }
22544};
22545
22546
22547class RequestInterruptTestWithNativeAccessor
22548 : public RequestInterruptTestBaseWithSimpleInterrupt {
22549 public:
22550 virtual void TestBody() {
22551 v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
22552 t->InstanceTemplate()->SetNativeDataProperty(
22553 v8_str("shouldContinue"),
22554 &ShouldContinueNativeGetter,
22555 NULL,
22556 v8::External::New(isolate_, this));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022557 CHECK(env_->Global()
22558 ->Set(env_.local(), v8_str("Klass"),
22559 t->GetFunction(env_.local()).ToLocalChecked())
22560 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022561
22562 CompileRun("var obj = new Klass; while (obj.shouldContinue) { }");
22563 }
22564
22565 private:
22566 static void ShouldContinueNativeGetter(
22567 Local<String> property,
22568 const v8::PropertyCallbackInfo<v8::Value>& info) {
22569 RequestInterruptTestBase* test =
22570 reinterpret_cast<RequestInterruptTestBase*>(
22571 info.Data().As<v8::External>()->Value());
22572 info.GetReturnValue().Set(test->ShouldContinue());
22573 }
22574};
22575
22576
22577class RequestInterruptTestWithMethodCallAndInterceptor
22578 : public RequestInterruptTestBaseWithSimpleInterrupt {
22579 public:
22580 virtual void TestBody() {
22581 v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
22582 v8::Local<v8::Template> proto = t->PrototypeTemplate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022583 proto->Set(v8_str("shouldContinue"),
Ben Murdoch097c5b22016-05-18 11:27:45 +010022584 FunctionTemplate::New(isolate_, ShouldContinueCallback,
22585 v8::External::New(isolate_, this)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022586 v8::Local<v8::ObjectTemplate> instance_template = t->InstanceTemplate();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040022587 instance_template->SetHandler(
22588 v8::NamedPropertyHandlerConfiguration(EmptyInterceptor));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022589
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022590 CHECK(env_->Global()
22591 ->Set(env_.local(), v8_str("Klass"),
22592 t->GetFunction(env_.local()).ToLocalChecked())
22593 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022594
22595 CompileRun("var obj = new Klass; while (obj.shouldContinue()) { }");
22596 }
22597
22598 private:
22599 static void EmptyInterceptor(
Emily Bernierd0a1eb72015-03-24 16:35:39 -040022600 Local<Name> property, const v8::PropertyCallbackInfo<v8::Value>& info) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022601};
22602
22603
22604class RequestInterruptTestWithMathAbs
22605 : public RequestInterruptTestBaseWithSimpleInterrupt {
22606 public:
22607 virtual void TestBody() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022608 env_->Global()
22609 ->Set(env_.local(), v8_str("WakeUpInterruptor"),
22610 Function::New(env_.local(), WakeUpInterruptorCallback,
22611 v8::External::New(isolate_, this))
22612 .ToLocalChecked())
22613 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022614
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022615 env_->Global()
22616 ->Set(env_.local(), v8_str("ShouldContinue"),
22617 Function::New(env_.local(), ShouldContinueCallback,
22618 v8::External::New(isolate_, this))
22619 .ToLocalChecked())
22620 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022621
22622 i::FLAG_allow_natives_syntax = true;
22623 CompileRun("function loopish(o) {"
22624 " var pre = 10;"
22625 " while (o.abs(1) > 0) {"
22626 " if (o.abs(1) >= 0 && !ShouldContinue()) break;"
22627 " if (pre > 0) {"
22628 " if (--pre === 0) WakeUpInterruptor(o === Math);"
22629 " }"
22630 " }"
22631 "}"
22632 "var i = 50;"
22633 "var obj = {abs: function () { return i-- }, x: null};"
22634 "delete obj.x;"
22635 "loopish(obj);"
22636 "%OptimizeFunctionOnNextCall(loopish);"
22637 "loopish(Math);");
22638
22639 i::FLAG_allow_natives_syntax = false;
22640 }
22641
22642 private:
22643 static void WakeUpInterruptorCallback(
22644 const v8::FunctionCallbackInfo<Value>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022645 if (!info[0]
22646 ->BooleanValue(info.GetIsolate()->GetCurrentContext())
22647 .FromJust()) {
22648 return;
22649 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022650
22651 RequestInterruptTestBase* test =
22652 reinterpret_cast<RequestInterruptTestBase*>(
22653 info.Data().As<v8::External>()->Value());
22654 test->WakeUpInterruptor();
22655 }
22656
22657 static void ShouldContinueCallback(
22658 const v8::FunctionCallbackInfo<Value>& info) {
22659 RequestInterruptTestBase* test =
22660 reinterpret_cast<RequestInterruptTestBase*>(
22661 info.Data().As<v8::External>()->Value());
22662 info.GetReturnValue().Set(test->should_continue());
22663 }
22664};
22665
22666
22667TEST(RequestInterruptTestWithFunctionCall) {
22668 RequestInterruptTestWithFunctionCall().RunTest();
22669}
22670
22671
22672TEST(RequestInterruptTestWithMethodCall) {
22673 RequestInterruptTestWithMethodCall().RunTest();
22674}
22675
22676
22677TEST(RequestInterruptTestWithAccessor) {
22678 RequestInterruptTestWithAccessor().RunTest();
22679}
22680
22681
22682TEST(RequestInterruptTestWithNativeAccessor) {
22683 RequestInterruptTestWithNativeAccessor().RunTest();
22684}
22685
22686
22687TEST(RequestInterruptTestWithMethodCallAndInterceptor) {
22688 RequestInterruptTestWithMethodCallAndInterceptor().RunTest();
22689}
22690
22691
22692TEST(RequestInterruptTestWithMathAbs) {
22693 RequestInterruptTestWithMathAbs().RunTest();
22694}
22695
22696
Emily Bernierd0a1eb72015-03-24 16:35:39 -040022697class RequestMultipleInterrupts : public RequestInterruptTestBase {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022698 public:
Emily Bernierd0a1eb72015-03-24 16:35:39 -040022699 RequestMultipleInterrupts() : i_thread(this), counter_(0) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022700
22701 virtual void StartInterruptThread() {
22702 i_thread.Start();
22703 }
22704
22705 virtual void TestBody() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022706 Local<Function> func = Function::New(env_.local(), ShouldContinueCallback,
22707 v8::External::New(isolate_, this))
22708 .ToLocalChecked();
22709 CHECK(env_->Global()
22710 ->Set(env_.local(), v8_str("ShouldContinue"), func)
22711 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022712
22713 CompileRun("while (ShouldContinue()) { }");
22714 }
22715
22716 private:
22717 class InterruptThread : public v8::base::Thread {
22718 public:
Emily Bernierd0a1eb72015-03-24 16:35:39 -040022719 enum { NUM_INTERRUPTS = 10 };
22720 explicit InterruptThread(RequestMultipleInterrupts* test)
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022721 : Thread(Options("RequestInterruptTest")), test_(test) {}
22722
22723 virtual void Run() {
22724 test_->sem_.Wait();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040022725 for (int i = 0; i < NUM_INTERRUPTS; i++) {
22726 test_->isolate_->RequestInterrupt(&OnInterrupt, test_);
22727 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022728 }
22729
22730 static void OnInterrupt(v8::Isolate* isolate, void* data) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040022731 RequestMultipleInterrupts* test =
22732 reinterpret_cast<RequestMultipleInterrupts*>(data);
22733 test->should_continue_ = ++test->counter_ < NUM_INTERRUPTS;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022734 }
22735
22736 private:
Emily Bernierd0a1eb72015-03-24 16:35:39 -040022737 RequestMultipleInterrupts* test_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022738 };
22739
22740 InterruptThread i_thread;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040022741 int counter_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022742};
22743
22744
Emily Bernierd0a1eb72015-03-24 16:35:39 -040022745TEST(RequestMultipleInterrupts) { RequestMultipleInterrupts().RunTest(); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022746
22747
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022748static bool interrupt_was_called = false;
22749
22750
22751void SmallScriptsInterruptCallback(v8::Isolate* isolate, void* data) {
22752 interrupt_was_called = true;
22753}
22754
22755
22756TEST(RequestInterruptSmallScripts) {
22757 LocalContext env;
22758 v8::Isolate* isolate = CcTest::isolate();
22759 v8::HandleScope scope(isolate);
22760
22761 interrupt_was_called = false;
22762 isolate->RequestInterrupt(&SmallScriptsInterruptCallback, NULL);
22763 CompileRun("(function(x){return x;})(1);");
22764 CHECK(interrupt_was_called);
22765}
22766
22767
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022768static Local<Value> function_new_expected_env;
22769static void FunctionNewCallback(const v8::FunctionCallbackInfo<Value>& info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022770 CHECK(
22771 function_new_expected_env->Equals(info.GetIsolate()->GetCurrentContext(),
22772 info.Data())
22773 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022774 info.GetReturnValue().Set(17);
22775}
22776
22777
22778THREADED_TEST(FunctionNew) {
22779 LocalContext env;
22780 v8::Isolate* isolate = env->GetIsolate();
22781 v8::HandleScope scope(isolate);
22782 Local<Object> data = v8::Object::New(isolate);
22783 function_new_expected_env = data;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022784 Local<Function> func =
22785 Function::New(env.local(), FunctionNewCallback, data).ToLocalChecked();
22786 CHECK(env->Global()->Set(env.local(), v8_str("func"), func).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022787 Local<Value> result = CompileRun("func();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022788 CHECK(v8::Integer::New(isolate, 17)->Equals(env.local(), result).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022789 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022790 // Verify function not cached
22791 auto serial_number = handle(
22792 i::Smi::cast(i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(*func))
22793 ->shared()
22794 ->get_api_func_data()
22795 ->serial_number()),
22796 i_isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +010022797 auto cache = i_isolate->template_instantiations_cache();
Ben Murdochda12d292016-06-02 14:46:10 +010022798 CHECK(cache->FindEntry(static_cast<uint32_t>(serial_number->value())) ==
22799 i::UnseededNumberDictionary::kNotFound);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022800 // Verify that each Function::New creates a new function instance
22801 Local<Object> data2 = v8::Object::New(isolate);
22802 function_new_expected_env = data2;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022803 Local<Function> func2 =
22804 Function::New(env.local(), FunctionNewCallback, data2).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022805 CHECK(!func2->IsNull());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022806 CHECK(!func->Equals(env.local(), func2).FromJust());
22807 CHECK(env->Global()->Set(env.local(), v8_str("func2"), func2).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022808 Local<Value> result2 = CompileRun("func2();");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022809 CHECK(v8::Integer::New(isolate, 17)->Equals(env.local(), result2).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022810}
22811
22812
22813TEST(EscapeableHandleScope) {
22814 HandleScope outer_scope(CcTest::isolate());
22815 LocalContext context;
22816 const int runs = 10;
22817 Local<String> values[runs];
22818 for (int i = 0; i < runs; i++) {
22819 v8::EscapableHandleScope inner_scope(CcTest::isolate());
22820 Local<String> value;
22821 if (i != 0) value = v8_str("escape value");
22822 values[i] = inner_scope.Escape(value);
22823 }
22824 for (int i = 0; i < runs; i++) {
22825 Local<String> expected;
22826 if (i != 0) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022827 CHECK(v8_str("escape value")
22828 ->Equals(context.local(), values[i])
22829 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022830 } else {
22831 CHECK(values[i].IsEmpty());
22832 }
22833 }
22834}
22835
22836
22837static void SetterWhichExpectsThisAndHolderToDiffer(
22838 Local<String>, Local<Value>, const v8::PropertyCallbackInfo<void>& info) {
22839 CHECK(info.Holder() != info.This());
22840}
22841
22842
22843TEST(Regress239669) {
22844 LocalContext context;
22845 v8::Isolate* isolate = context->GetIsolate();
22846 v8::HandleScope scope(isolate);
22847 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
22848 templ->SetAccessor(v8_str("x"), 0, SetterWhichExpectsThisAndHolderToDiffer);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022849 CHECK(context->Global()
22850 ->Set(context.local(), v8_str("P"),
22851 templ->NewInstance(context.local()).ToLocalChecked())
22852 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022853 CompileRun(
22854 "function C1() {"
22855 " this.x = 23;"
22856 "};"
22857 "C1.prototype = P;"
22858 "for (var i = 0; i < 4; i++ ) {"
22859 " new C1();"
22860 "}");
22861}
22862
22863
22864class ApiCallOptimizationChecker {
22865 private:
22866 static Local<Object> data;
22867 static Local<Object> receiver;
22868 static Local<Object> holder;
22869 static Local<Object> callee;
22870 static int count;
22871
22872 static void OptimizationCallback(
22873 const v8::FunctionCallbackInfo<v8::Value>& info) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022874 CHECK(data == info.Data());
22875 CHECK(receiver == info.This());
22876 if (info.Length() == 1) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022877 CHECK(v8_num(1)
22878 ->Equals(info.GetIsolate()->GetCurrentContext(), info[0])
22879 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022880 }
22881 CHECK(holder == info.Holder());
22882 count++;
22883 info.GetReturnValue().Set(v8_str("returned"));
22884 }
22885
22886 public:
22887 enum SignatureType {
22888 kNoSignature,
22889 kSignatureOnReceiver,
22890 kSignatureOnPrototype
22891 };
22892
22893 void RunAll() {
22894 SignatureType signature_types[] =
22895 {kNoSignature, kSignatureOnReceiver, kSignatureOnPrototype};
22896 for (unsigned i = 0; i < arraysize(signature_types); i++) {
22897 SignatureType signature_type = signature_types[i];
22898 for (int j = 0; j < 2; j++) {
22899 bool global = j == 0;
22900 int key = signature_type +
22901 arraysize(signature_types) * (global ? 1 : 0);
22902 Run(signature_type, global, key);
22903 }
22904 }
22905 }
22906
22907 void Run(SignatureType signature_type, bool global, int key) {
22908 v8::Isolate* isolate = CcTest::isolate();
22909 v8::HandleScope scope(isolate);
22910 // Build a template for signature checks.
22911 Local<v8::ObjectTemplate> signature_template;
22912 Local<v8::Signature> signature;
22913 {
22914 Local<v8::FunctionTemplate> parent_template =
22915 FunctionTemplate::New(isolate);
22916 parent_template->SetHiddenPrototype(true);
22917 Local<v8::FunctionTemplate> function_template
22918 = FunctionTemplate::New(isolate);
22919 function_template->Inherit(parent_template);
22920 switch (signature_type) {
22921 case kNoSignature:
22922 break;
22923 case kSignatureOnReceiver:
22924 signature = v8::Signature::New(isolate, function_template);
22925 break;
22926 case kSignatureOnPrototype:
22927 signature = v8::Signature::New(isolate, parent_template);
22928 break;
22929 }
22930 signature_template = function_template->InstanceTemplate();
22931 }
22932 // Global object must pass checks.
22933 Local<v8::Context> context =
22934 v8::Context::New(isolate, NULL, signature_template);
22935 v8::Context::Scope context_scope(context);
22936 // Install regular object that can pass signature checks.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022937 Local<Object> function_receiver =
22938 signature_template->NewInstance(context).ToLocalChecked();
22939 CHECK(context->Global()
22940 ->Set(context, v8_str("function_receiver"), function_receiver)
22941 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022942 // Get the holder objects.
22943 Local<Object> inner_global =
22944 Local<Object>::Cast(context->Global()->GetPrototype());
22945 // Install functions on hidden prototype object if there is one.
22946 data = Object::New(isolate);
22947 Local<FunctionTemplate> function_template = FunctionTemplate::New(
22948 isolate, OptimizationCallback, data, signature);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022949 Local<Function> function =
22950 function_template->GetFunction(context).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022951 Local<Object> global_holder = inner_global;
22952 Local<Object> function_holder = function_receiver;
22953 if (signature_type == kSignatureOnPrototype) {
22954 function_holder = Local<Object>::Cast(function_holder->GetPrototype());
22955 global_holder = Local<Object>::Cast(global_holder->GetPrototype());
22956 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022957 global_holder->Set(context, v8_str("g_f"), function).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022958 global_holder->SetAccessorProperty(v8_str("g_acc"), function, function);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022959 function_holder->Set(context, v8_str("f"), function).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022960 function_holder->SetAccessorProperty(v8_str("acc"), function, function);
22961 // Initialize expected values.
22962 callee = function;
22963 count = 0;
22964 if (global) {
22965 receiver = context->Global();
22966 holder = inner_global;
22967 } else {
22968 holder = function_receiver;
22969 // If not using a signature, add something else to the prototype chain
22970 // to test the case that holder != receiver
22971 if (signature_type == kNoSignature) {
22972 receiver = Local<Object>::Cast(CompileRun(
22973 "var receiver_subclass = {};\n"
22974 "receiver_subclass.__proto__ = function_receiver;\n"
22975 "receiver_subclass"));
22976 } else {
22977 receiver = Local<Object>::Cast(CompileRun(
22978 "var receiver_subclass = function_receiver;\n"
22979 "receiver_subclass"));
22980 }
22981 }
22982 // With no signature, the holder is not set.
22983 if (signature_type == kNoSignature) holder = receiver;
22984 // build wrap_function
22985 i::ScopedVector<char> wrap_function(200);
22986 if (global) {
22987 i::SNPrintF(
22988 wrap_function,
22989 "function wrap_f_%d() { var f = g_f; return f(); }\n"
22990 "function wrap_get_%d() { return this.g_acc; }\n"
22991 "function wrap_set_%d() { return this.g_acc = 1; }\n",
22992 key, key, key);
22993 } else {
22994 i::SNPrintF(
22995 wrap_function,
22996 "function wrap_f_%d() { return receiver_subclass.f(); }\n"
22997 "function wrap_get_%d() { return receiver_subclass.acc; }\n"
22998 "function wrap_set_%d() { return receiver_subclass.acc = 1; }\n",
22999 key, key, key);
23000 }
23001 // build source string
23002 i::ScopedVector<char> source(1000);
23003 i::SNPrintF(
23004 source,
23005 "%s\n" // wrap functions
23006 "function wrap_f() { return wrap_f_%d(); }\n"
23007 "function wrap_get() { return wrap_get_%d(); }\n"
23008 "function wrap_set() { return wrap_set_%d(); }\n"
23009 "check = function(returned) {\n"
23010 " if (returned !== 'returned') { throw returned; }\n"
23011 "}\n"
23012 "\n"
23013 "check(wrap_f());\n"
23014 "check(wrap_f());\n"
23015 "%%OptimizeFunctionOnNextCall(wrap_f_%d);\n"
23016 "check(wrap_f());\n"
23017 "\n"
23018 "check(wrap_get());\n"
23019 "check(wrap_get());\n"
23020 "%%OptimizeFunctionOnNextCall(wrap_get_%d);\n"
23021 "check(wrap_get());\n"
23022 "\n"
23023 "check = function(returned) {\n"
23024 " if (returned !== 1) { throw returned; }\n"
23025 "}\n"
23026 "check(wrap_set());\n"
23027 "check(wrap_set());\n"
23028 "%%OptimizeFunctionOnNextCall(wrap_set_%d);\n"
23029 "check(wrap_set());\n",
23030 wrap_function.start(), key, key, key, key, key, key);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023031 v8::TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023032 CompileRun(source.start());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023033 CHECK(!try_catch.HasCaught());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023034 CHECK_EQ(9, count);
23035 }
23036};
23037
23038
23039Local<Object> ApiCallOptimizationChecker::data;
23040Local<Object> ApiCallOptimizationChecker::receiver;
23041Local<Object> ApiCallOptimizationChecker::holder;
23042Local<Object> ApiCallOptimizationChecker::callee;
23043int ApiCallOptimizationChecker::count = 0;
23044
23045
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023046TEST(FunctionCallOptimization) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023047 i::FLAG_allow_natives_syntax = true;
23048 ApiCallOptimizationChecker checker;
23049 checker.RunAll();
23050}
23051
23052
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023053TEST(FunctionCallOptimizationMultipleArgs) {
23054 i::FLAG_allow_natives_syntax = true;
23055 LocalContext context;
23056 v8::Isolate* isolate = context->GetIsolate();
23057 v8::HandleScope scope(isolate);
23058 Local<Object> global = context->Global();
23059 Local<v8::Function> function =
23060 Function::New(context.local(), Returns42).ToLocalChecked();
23061 global->Set(context.local(), v8_str("x"), function).FromJust();
23062 CompileRun(
23063 "function x_wrap() {\n"
23064 " for (var i = 0; i < 5; i++) {\n"
23065 " x(1,2,3);\n"
23066 " }\n"
23067 "}\n"
23068 "x_wrap();\n"
23069 "%OptimizeFunctionOnNextCall(x_wrap);"
23070 "x_wrap();\n");
23071}
23072
23073
23074static void ReturnsSymbolCallback(
23075 const v8::FunctionCallbackInfo<v8::Value>& info) {
23076 info.GetReturnValue().Set(v8::Symbol::New(info.GetIsolate()));
23077}
23078
23079
23080TEST(ApiCallbackCanReturnSymbols) {
23081 i::FLAG_allow_natives_syntax = true;
23082 LocalContext context;
23083 v8::Isolate* isolate = context->GetIsolate();
23084 v8::HandleScope scope(isolate);
23085 Local<Object> global = context->Global();
23086 Local<v8::Function> function =
23087 Function::New(context.local(), ReturnsSymbolCallback).ToLocalChecked();
23088 global->Set(context.local(), v8_str("x"), function).FromJust();
23089 CompileRun(
23090 "function x_wrap() {\n"
23091 " for (var i = 0; i < 5; i++) {\n"
23092 " x();\n"
23093 " }\n"
23094 "}\n"
23095 "x_wrap();\n"
23096 "%OptimizeFunctionOnNextCall(x_wrap);"
23097 "x_wrap();\n");
23098}
23099
23100
23101TEST(EmptyApiCallback) {
23102 LocalContext context;
23103 auto isolate = context->GetIsolate();
23104 v8::HandleScope scope(isolate);
23105 auto global = context->Global();
23106 auto function = FunctionTemplate::New(isolate)
23107 ->GetFunction(context.local())
23108 .ToLocalChecked();
23109 global->Set(context.local(), v8_str("x"), function).FromJust();
23110
23111 auto result = CompileRun("x()");
23112 CHECK(v8::Utils::OpenHandle(*result)->IsJSGlobalProxy());
23113
23114 result = CompileRun("x(1,2,3)");
23115 CHECK(v8::Utils::OpenHandle(*result)->IsJSGlobalProxy());
23116
23117 result = CompileRun("x.call(undefined)");
23118 CHECK(v8::Utils::OpenHandle(*result)->IsJSGlobalProxy());
23119
23120 result = CompileRun("x.call(null)");
23121 CHECK(v8::Utils::OpenHandle(*result)->IsJSGlobalProxy());
23122
23123 result = CompileRun("7 + x.call(3) + 11");
23124 CHECK(result->IsInt32());
23125 CHECK_EQ(21, result->Int32Value(context.local()).FromJust());
23126
23127 result = CompileRun("7 + x.call(3, 101, 102, 103, 104) + 11");
23128 CHECK(result->IsInt32());
23129 CHECK_EQ(21, result->Int32Value(context.local()).FromJust());
23130
23131 result = CompileRun("var y = []; x.call(y)");
23132 CHECK(result->IsArray());
23133
23134 result = CompileRun("x.call(y, 1, 2, 3, 4)");
23135 CHECK(result->IsArray());
23136}
23137
23138
23139TEST(SimpleSignatureCheck) {
23140 LocalContext context;
23141 auto isolate = context->GetIsolate();
23142 v8::HandleScope scope(isolate);
23143 auto global = context->Global();
23144 auto sig_obj = FunctionTemplate::New(isolate);
23145 auto sig = v8::Signature::New(isolate, sig_obj);
23146 auto x = FunctionTemplate::New(isolate, Returns42, Local<Value>(), sig);
23147 global->Set(context.local(), v8_str("sig_obj"),
23148 sig_obj->GetFunction(context.local()).ToLocalChecked())
23149 .FromJust();
23150 global->Set(context.local(), v8_str("x"),
23151 x->GetFunction(context.local()).ToLocalChecked())
23152 .FromJust();
23153 CompileRun("var s = new sig_obj();");
23154 {
23155 TryCatch try_catch(isolate);
23156 CompileRun("x()");
23157 CHECK(try_catch.HasCaught());
23158 }
23159 {
23160 TryCatch try_catch(isolate);
23161 CompileRun("x.call(1)");
23162 CHECK(try_catch.HasCaught());
23163 }
23164 {
23165 TryCatch try_catch(isolate);
23166 auto result = CompileRun("s.x = x; s.x()");
23167 CHECK(!try_catch.HasCaught());
23168 CHECK_EQ(42, result->Int32Value(context.local()).FromJust());
23169 }
23170 {
23171 TryCatch try_catch(isolate);
23172 auto result = CompileRun("x.call(s)");
23173 CHECK(!try_catch.HasCaught());
23174 CHECK_EQ(42, result->Int32Value(context.local()).FromJust());
23175 }
23176}
23177
23178
23179TEST(ChainSignatureCheck) {
23180 LocalContext context;
23181 auto isolate = context->GetIsolate();
23182 v8::HandleScope scope(isolate);
23183 auto global = context->Global();
23184 auto sig_obj = FunctionTemplate::New(isolate);
23185 auto sig = v8::Signature::New(isolate, sig_obj);
23186 for (int i = 0; i < 4; ++i) {
23187 auto temp = FunctionTemplate::New(isolate);
23188 temp->Inherit(sig_obj);
23189 sig_obj = temp;
23190 }
23191 auto x = FunctionTemplate::New(isolate, Returns42, Local<Value>(), sig);
23192 global->Set(context.local(), v8_str("sig_obj"),
23193 sig_obj->GetFunction(context.local()).ToLocalChecked())
23194 .FromJust();
23195 global->Set(context.local(), v8_str("x"),
23196 x->GetFunction(context.local()).ToLocalChecked())
23197 .FromJust();
23198 CompileRun("var s = new sig_obj();");
23199 {
23200 TryCatch try_catch(isolate);
23201 CompileRun("x()");
23202 CHECK(try_catch.HasCaught());
23203 }
23204 {
23205 TryCatch try_catch(isolate);
23206 CompileRun("x.call(1)");
23207 CHECK(try_catch.HasCaught());
23208 }
23209 {
23210 TryCatch try_catch(isolate);
23211 auto result = CompileRun("s.x = x; s.x()");
23212 CHECK(!try_catch.HasCaught());
23213 CHECK_EQ(42, result->Int32Value(context.local()).FromJust());
23214 }
23215 {
23216 TryCatch try_catch(isolate);
23217 auto result = CompileRun("x.call(s)");
23218 CHECK(!try_catch.HasCaught());
23219 CHECK_EQ(42, result->Int32Value(context.local()).FromJust());
23220 }
23221}
23222
23223
23224TEST(PrototypeSignatureCheck) {
23225 LocalContext context;
23226 auto isolate = context->GetIsolate();
23227 v8::HandleScope scope(isolate);
23228 auto global = context->Global();
23229 auto sig_obj = FunctionTemplate::New(isolate);
23230 sig_obj->SetHiddenPrototype(true);
23231 auto sig = v8::Signature::New(isolate, sig_obj);
23232 auto x = FunctionTemplate::New(isolate, Returns42, Local<Value>(), sig);
23233 global->Set(context.local(), v8_str("sig_obj"),
23234 sig_obj->GetFunction(context.local()).ToLocalChecked())
23235 .FromJust();
23236 global->Set(context.local(), v8_str("x"),
23237 x->GetFunction(context.local()).ToLocalChecked())
23238 .FromJust();
23239 CompileRun("s = {}; s.__proto__ = new sig_obj();");
23240 {
23241 TryCatch try_catch(isolate);
23242 CompileRun("x()");
23243 CHECK(try_catch.HasCaught());
23244 }
23245 {
23246 TryCatch try_catch(isolate);
23247 CompileRun("x.call(1)");
23248 CHECK(try_catch.HasCaught());
23249 }
23250 {
23251 TryCatch try_catch(isolate);
23252 auto result = CompileRun("s.x = x; s.x()");
23253 CHECK(!try_catch.HasCaught());
23254 CHECK_EQ(42, result->Int32Value(context.local()).FromJust());
23255 }
23256 {
23257 TryCatch try_catch(isolate);
23258 auto result = CompileRun("x.call(s)");
23259 CHECK(!try_catch.HasCaught());
23260 CHECK_EQ(42, result->Int32Value(context.local()).FromJust());
23261 }
23262}
23263
23264
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023265static const char* last_event_message;
23266static int last_event_status;
23267void StoringEventLoggerCallback(const char* message, int status) {
23268 last_event_message = message;
23269 last_event_status = status;
23270}
23271
23272
23273TEST(EventLogging) {
23274 v8::Isolate* isolate = CcTest::isolate();
23275 isolate->SetEventLogger(StoringEventLoggerCallback);
23276 v8::internal::HistogramTimer histogramTimer(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023277 "V8.Test", 0, 10000, v8::internal::HistogramTimer::MILLISECOND, 50,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023278 reinterpret_cast<v8::internal::Isolate*>(isolate));
23279 histogramTimer.Start();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023280 CHECK_EQ(0, strcmp("V8.Test", last_event_message));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023281 CHECK_EQ(0, last_event_status);
23282 histogramTimer.Stop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023283 CHECK_EQ(0, strcmp("V8.Test", last_event_message));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023284 CHECK_EQ(1, last_event_status);
23285}
23286
23287
23288TEST(Promises) {
23289 LocalContext context;
23290 v8::Isolate* isolate = context->GetIsolate();
23291 v8::HandleScope scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023292
23293 // Creation.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023294 Local<v8::Promise::Resolver> pr =
23295 v8::Promise::Resolver::New(context.local()).ToLocalChecked();
23296 Local<v8::Promise::Resolver> rr =
23297 v8::Promise::Resolver::New(context.local()).ToLocalChecked();
23298 Local<v8::Promise> p = pr->GetPromise();
23299 Local<v8::Promise> r = rr->GetPromise();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023300
23301 // IsPromise predicate.
23302 CHECK(p->IsPromise());
23303 CHECK(r->IsPromise());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023304 Local<Value> o = v8::Object::New(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023305 CHECK(!o->IsPromise());
23306
23307 // Resolution and rejection.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023308 pr->Resolve(context.local(), v8::Integer::New(isolate, 1)).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023309 CHECK(p->IsPromise());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023310 rr->Reject(context.local(), v8::Integer::New(isolate, 2)).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023311 CHECK(r->IsPromise());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023312}
23313
23314
23315TEST(PromiseThen) {
23316 LocalContext context;
23317 v8::Isolate* isolate = context->GetIsolate();
23318 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023319 Local<Object> global = context->Global();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023320
23321 // Creation.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023322 Local<v8::Promise::Resolver> pr =
23323 v8::Promise::Resolver::New(context.local()).ToLocalChecked();
23324 Local<v8::Promise::Resolver> qr =
23325 v8::Promise::Resolver::New(context.local()).ToLocalChecked();
23326 Local<v8::Promise> p = pr->GetPromise();
23327 Local<v8::Promise> q = qr->GetPromise();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023328
23329 CHECK(p->IsPromise());
23330 CHECK(q->IsPromise());
23331
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023332 pr->Resolve(context.local(), v8::Integer::New(isolate, 1)).FromJust();
23333 qr->Resolve(context.local(), p).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023334
23335 // Chaining non-pending promises.
23336 CompileRun(
23337 "var x1 = 0;\n"
23338 "var x2 = 0;\n"
23339 "function f1(x) { x1 = x; return x+1 };\n"
23340 "function f2(x) { x2 = x; return x+1 };\n");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023341 Local<Function> f1 = Local<Function>::Cast(
23342 global->Get(context.local(), v8_str("f1")).ToLocalChecked());
23343 Local<Function> f2 = Local<Function>::Cast(
23344 global->Get(context.local(), v8_str("f2")).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023345
23346 // Then
23347 CompileRun("x1 = x2 = 0;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023348 q->Then(context.local(), f1).ToLocalChecked();
23349 CHECK_EQ(0, global->Get(context.local(), v8_str("x1"))
23350 .ToLocalChecked()
23351 ->Int32Value(context.local())
23352 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023353 isolate->RunMicrotasks();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023354 CHECK_EQ(1, global->Get(context.local(), v8_str("x1"))
23355 .ToLocalChecked()
23356 ->Int32Value(context.local())
23357 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023358
23359 // Then
23360 CompileRun("x1 = x2 = 0;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023361 pr = v8::Promise::Resolver::New(context.local()).ToLocalChecked();
23362 qr = v8::Promise::Resolver::New(context.local()).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023363
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023364 qr->Resolve(context.local(), pr).FromJust();
23365 qr->GetPromise()
23366 ->Then(context.local(), f1)
23367 .ToLocalChecked()
23368 ->Then(context.local(), f2)
23369 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023370
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023371 CHECK_EQ(0, global->Get(context.local(), v8_str("x1"))
23372 .ToLocalChecked()
23373 ->Int32Value(context.local())
23374 .FromJust());
23375 CHECK_EQ(0, global->Get(context.local(), v8_str("x2"))
23376 .ToLocalChecked()
23377 ->Int32Value(context.local())
23378 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023379 isolate->RunMicrotasks();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023380 CHECK_EQ(0, global->Get(context.local(), v8_str("x1"))
23381 .ToLocalChecked()
23382 ->Int32Value(context.local())
23383 .FromJust());
23384 CHECK_EQ(0, global->Get(context.local(), v8_str("x2"))
23385 .ToLocalChecked()
23386 ->Int32Value(context.local())
23387 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023388
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023389 pr->Resolve(context.local(), v8::Integer::New(isolate, 3)).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023390
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023391 CHECK_EQ(0, global->Get(context.local(), v8_str("x1"))
23392 .ToLocalChecked()
23393 ->Int32Value(context.local())
23394 .FromJust());
23395 CHECK_EQ(0, global->Get(context.local(), v8_str("x2"))
23396 .ToLocalChecked()
23397 ->Int32Value(context.local())
23398 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023399 isolate->RunMicrotasks();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023400 CHECK_EQ(3, global->Get(context.local(), v8_str("x1"))
23401 .ToLocalChecked()
23402 ->Int32Value(context.local())
23403 .FromJust());
23404 CHECK_EQ(4, global->Get(context.local(), v8_str("x2"))
23405 .ToLocalChecked()
23406 ->Int32Value(context.local())
23407 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023408}
23409
23410
23411TEST(DisallowJavascriptExecutionScope) {
23412 LocalContext context;
23413 v8::Isolate* isolate = context->GetIsolate();
23414 v8::HandleScope scope(isolate);
23415 v8::Isolate::DisallowJavascriptExecutionScope no_js(
23416 isolate, v8::Isolate::DisallowJavascriptExecutionScope::CRASH_ON_FAILURE);
23417 CompileRun("2+2");
23418}
23419
23420
23421TEST(AllowJavascriptExecutionScope) {
23422 LocalContext context;
23423 v8::Isolate* isolate = context->GetIsolate();
23424 v8::HandleScope scope(isolate);
23425 v8::Isolate::DisallowJavascriptExecutionScope no_js(
23426 isolate, v8::Isolate::DisallowJavascriptExecutionScope::CRASH_ON_FAILURE);
23427 v8::Isolate::DisallowJavascriptExecutionScope throw_js(
23428 isolate, v8::Isolate::DisallowJavascriptExecutionScope::THROW_ON_FAILURE);
23429 { v8::Isolate::AllowJavascriptExecutionScope yes_js(isolate);
23430 CompileRun("1+1");
23431 }
23432}
23433
23434
23435TEST(ThrowOnJavascriptExecution) {
23436 LocalContext context;
23437 v8::Isolate* isolate = context->GetIsolate();
23438 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023439 v8::TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023440 v8::Isolate::DisallowJavascriptExecutionScope throw_js(
23441 isolate, v8::Isolate::DisallowJavascriptExecutionScope::THROW_ON_FAILURE);
23442 CompileRun("1+1");
23443 CHECK(try_catch.HasCaught());
23444}
23445
23446
23447TEST(Regress354123) {
23448 LocalContext current;
23449 v8::Isolate* isolate = current->GetIsolate();
23450 v8::HandleScope scope(isolate);
23451
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023452 v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
23453 templ->SetAccessCheckCallback(AccessCounter);
23454 CHECK(current->Global()
23455 ->Set(current.local(), v8_str("friend"),
23456 templ->NewInstance(current.local()).ToLocalChecked())
23457 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023458
23459 // Test access using __proto__ from the prototype chain.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023460 access_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023461 CompileRun("friend.__proto__ = {};");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023462 CHECK_EQ(2, access_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023463 CompileRun("friend.__proto__;");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023464 CHECK_EQ(4, access_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023465
23466 // Test access using __proto__ as a hijacked function (A).
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023467 access_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023468 CompileRun("var p = Object.prototype;"
23469 "var f = Object.getOwnPropertyDescriptor(p, '__proto__').set;"
23470 "f.call(friend, {});");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023471 CHECK_EQ(1, access_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023472 CompileRun("var p = Object.prototype;"
23473 "var f = Object.getOwnPropertyDescriptor(p, '__proto__').get;"
23474 "f.call(friend);");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023475 CHECK_EQ(2, access_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023476
23477 // Test access using __proto__ as a hijacked function (B).
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023478 access_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023479 CompileRun("var f = Object.prototype.__lookupSetter__('__proto__');"
23480 "f.call(friend, {});");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023481 CHECK_EQ(1, access_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023482 CompileRun("var f = Object.prototype.__lookupGetter__('__proto__');"
23483 "f.call(friend);");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023484 CHECK_EQ(2, access_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023485
23486 // Test access using Object.setPrototypeOf reflective method.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023487 access_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023488 CompileRun("Object.setPrototypeOf(friend, {});");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023489 CHECK_EQ(1, access_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023490 CompileRun("Object.getPrototypeOf(friend);");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023491 CHECK_EQ(2, access_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023492}
23493
23494
23495TEST(CaptureStackTraceForStackOverflow) {
23496 v8::internal::FLAG_stack_size = 150;
23497 LocalContext current;
23498 v8::Isolate* isolate = current->GetIsolate();
23499 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023500 isolate->SetCaptureStackTraceForUncaughtExceptions(true, 10,
23501 v8::StackTrace::kDetailed);
23502 v8::TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023503 CompileRun("(function f(x) { f(x+1); })(0)");
23504 CHECK(try_catch.HasCaught());
23505}
23506
23507
23508TEST(ScriptNameAndLineNumber) {
23509 LocalContext env;
23510 v8::Isolate* isolate = env->GetIsolate();
23511 v8::HandleScope scope(isolate);
23512 const char* url = "http://www.foo.com/foo.js";
23513 v8::ScriptOrigin origin(v8_str(url), v8::Integer::New(isolate, 13));
23514 v8::ScriptCompiler::Source script_source(v8_str("var foo;"), origin);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023515 Local<Script> script =
23516 v8::ScriptCompiler::Compile(env.local(), &script_source).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023517 Local<Value> script_name = script->GetUnboundScript()->GetScriptName();
23518 CHECK(!script_name.IsEmpty());
23519 CHECK(script_name->IsString());
23520 String::Utf8Value utf8_name(script_name);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023521 CHECK_EQ(0, strcmp(url, *utf8_name));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023522 int line_number = script->GetUnboundScript()->GetLineNumber(0);
23523 CHECK_EQ(13, line_number);
23524}
23525
Ben Murdoch61f157c2016-09-16 13:49:30 +010023526TEST(ScriptPositionInfo) {
23527 LocalContext env;
23528 v8::Isolate* isolate = env->GetIsolate();
23529 v8::HandleScope scope(isolate);
23530 const char* url = "http://www.foo.com/foo.js";
23531 v8::ScriptOrigin origin(v8_str(url), v8::Integer::New(isolate, 13));
23532 v8::ScriptCompiler::Source script_source(v8_str("var foo;\n"
23533 "var bar;\n"
23534 "var fisk = foo + bar;\n"),
23535 origin);
23536 Local<Script> script =
23537 v8::ScriptCompiler::Compile(env.local(), &script_source).ToLocalChecked();
23538
23539 i::Handle<i::SharedFunctionInfo> obj = i::Handle<i::SharedFunctionInfo>::cast(
23540 v8::Utils::OpenHandle(*script->GetUnboundScript()));
23541 CHECK(obj->script()->IsScript());
23542
23543 i::Handle<i::Script> script1(i::Script::cast(obj->script()));
23544
23545 v8::internal::Script::PositionInfo info;
23546
23547 // With offset.
23548
23549 // Behave as if 0 was passed if position is negative.
23550 CHECK(script1->GetPositionInfo(-1, &info, script1->WITH_OFFSET));
23551 CHECK_EQ(13, info.line);
23552 CHECK_EQ(0, info.column);
23553 CHECK_EQ(0, info.line_start);
23554 CHECK_EQ(8, info.line_end);
23555
23556 CHECK(script1->GetPositionInfo(0, &info, script1->WITH_OFFSET));
23557 CHECK_EQ(13, info.line);
23558 CHECK_EQ(0, info.column);
23559 CHECK_EQ(0, info.line_start);
23560 CHECK_EQ(8, info.line_end);
23561
23562 CHECK(script1->GetPositionInfo(8, &info, script1->WITH_OFFSET));
23563 CHECK_EQ(13, info.line);
23564 CHECK_EQ(8, info.column);
23565 CHECK_EQ(0, info.line_start);
23566 CHECK_EQ(8, info.line_end);
23567
23568 CHECK(script1->GetPositionInfo(9, &info, script1->WITH_OFFSET));
23569 CHECK_EQ(14, info.line);
23570 CHECK_EQ(0, info.column);
23571 CHECK_EQ(9, info.line_start);
23572 CHECK_EQ(17, info.line_end);
23573
23574 // Fail when position is larger than script size.
23575 CHECK(!script1->GetPositionInfo(220384, &info, script1->WITH_OFFSET));
23576
23577 // Without offset.
23578
23579 // Behave as if 0 was passed if position is negative.
23580 CHECK(script1->GetPositionInfo(-1, &info, script1->NO_OFFSET));
23581 CHECK_EQ(0, info.line);
23582 CHECK_EQ(0, info.column);
23583 CHECK_EQ(0, info.line_start);
23584 CHECK_EQ(8, info.line_end);
23585
23586 CHECK(script1->GetPositionInfo(0, &info, script1->NO_OFFSET));
23587 CHECK_EQ(0, info.line);
23588 CHECK_EQ(0, info.column);
23589 CHECK_EQ(0, info.line_start);
23590 CHECK_EQ(8, info.line_end);
23591
23592 CHECK(script1->GetPositionInfo(8, &info, script1->NO_OFFSET));
23593 CHECK_EQ(0, info.line);
23594 CHECK_EQ(8, info.column);
23595 CHECK_EQ(0, info.line_start);
23596 CHECK_EQ(8, info.line_end);
23597
23598 CHECK(script1->GetPositionInfo(9, &info, script1->NO_OFFSET));
23599 CHECK_EQ(1, info.line);
23600 CHECK_EQ(0, info.column);
23601 CHECK_EQ(9, info.line_start);
23602 CHECK_EQ(17, info.line_end);
23603
23604 // Fail when position is larger than script size.
23605 CHECK(!script1->GetPositionInfo(220384, &info, script1->NO_OFFSET));
23606}
23607
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023608void CheckMagicComments(Local<Script> script, const char* expected_source_url,
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023609 const char* expected_source_mapping_url) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023610 if (expected_source_url != NULL) {
23611 v8::String::Utf8Value url(script->GetUnboundScript()->GetSourceURL());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023612 CHECK_EQ(0, strcmp(expected_source_url, *url));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023613 } else {
23614 CHECK(script->GetUnboundScript()->GetSourceURL()->IsUndefined());
23615 }
23616 if (expected_source_mapping_url != NULL) {
23617 v8::String::Utf8Value url(
23618 script->GetUnboundScript()->GetSourceMappingURL());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023619 CHECK_EQ(0, strcmp(expected_source_mapping_url, *url));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023620 } else {
23621 CHECK(script->GetUnboundScript()->GetSourceMappingURL()->IsUndefined());
23622 }
23623}
23624
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023625void SourceURLHelper(const char* source, const char* expected_source_url,
23626 const char* expected_source_mapping_url) {
23627 Local<Script> script = v8_compile(source);
23628 CheckMagicComments(script, expected_source_url, expected_source_mapping_url);
23629}
23630
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023631
23632TEST(ScriptSourceURLAndSourceMappingURL) {
23633 LocalContext env;
23634 v8::Isolate* isolate = env->GetIsolate();
23635 v8::HandleScope scope(isolate);
23636 SourceURLHelper("function foo() {}\n"
23637 "//# sourceURL=bar1.js\n", "bar1.js", NULL);
23638 SourceURLHelper("function foo() {}\n"
23639 "//# sourceMappingURL=bar2.js\n", NULL, "bar2.js");
23640
23641 // Both sourceURL and sourceMappingURL.
23642 SourceURLHelper("function foo() {}\n"
23643 "//# sourceURL=bar3.js\n"
23644 "//# sourceMappingURL=bar4.js\n", "bar3.js", "bar4.js");
23645
23646 // Two source URLs; the first one is ignored.
23647 SourceURLHelper("function foo() {}\n"
23648 "//# sourceURL=ignoreme.js\n"
23649 "//# sourceURL=bar5.js\n", "bar5.js", NULL);
23650 SourceURLHelper("function foo() {}\n"
23651 "//# sourceMappingURL=ignoreme.js\n"
23652 "//# sourceMappingURL=bar6.js\n", NULL, "bar6.js");
23653
23654 // SourceURL or sourceMappingURL in the middle of the script.
23655 SourceURLHelper("function foo() {}\n"
23656 "//# sourceURL=bar7.js\n"
23657 "function baz() {}\n", "bar7.js", NULL);
23658 SourceURLHelper("function foo() {}\n"
23659 "//# sourceMappingURL=bar8.js\n"
23660 "function baz() {}\n", NULL, "bar8.js");
23661
23662 // Too much whitespace.
23663 SourceURLHelper("function foo() {}\n"
23664 "//# sourceURL=bar9.js\n"
23665 "//# sourceMappingURL=bar10.js\n", NULL, NULL);
23666 SourceURLHelper("function foo() {}\n"
23667 "//# sourceURL =bar11.js\n"
23668 "//# sourceMappingURL =bar12.js\n", NULL, NULL);
23669
23670 // Disallowed characters in value.
23671 SourceURLHelper("function foo() {}\n"
23672 "//# sourceURL=bar13 .js \n"
23673 "//# sourceMappingURL=bar14 .js \n",
23674 NULL, NULL);
23675 SourceURLHelper("function foo() {}\n"
23676 "//# sourceURL=bar15\t.js \n"
23677 "//# sourceMappingURL=bar16\t.js \n",
23678 NULL, NULL);
23679 SourceURLHelper("function foo() {}\n"
23680 "//# sourceURL=bar17'.js \n"
23681 "//# sourceMappingURL=bar18'.js \n",
23682 NULL, NULL);
23683 SourceURLHelper("function foo() {}\n"
23684 "//# sourceURL=bar19\".js \n"
23685 "//# sourceMappingURL=bar20\".js \n",
23686 NULL, NULL);
23687
23688 // Not too much whitespace.
23689 SourceURLHelper("function foo() {}\n"
23690 "//# sourceURL= bar21.js \n"
23691 "//# sourceMappingURL= bar22.js \n", "bar21.js", "bar22.js");
23692}
23693
23694
23695TEST(GetOwnPropertyDescriptor) {
23696 LocalContext env;
23697 v8::Isolate* isolate = env->GetIsolate();
23698 v8::HandleScope scope(isolate);
23699 CompileRun(
23700 "var x = { value : 13};"
23701 "Object.defineProperty(x, 'p0', {value : 12});"
23702 "Object.defineProperty(x, 'p1', {"
23703 " set : function(value) { this.value = value; },"
23704 " get : function() { return this.value; },"
23705 "});");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023706 Local<Object> x = Local<Object>::Cast(
23707 env->Global()->Get(env.local(), v8_str("x")).ToLocalChecked());
23708 Local<Value> desc =
23709 x->GetOwnPropertyDescriptor(env.local(), v8_str("no_prop"))
23710 .ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023711 CHECK(desc->IsUndefined());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023712 desc =
23713 x->GetOwnPropertyDescriptor(env.local(), v8_str("p0")).ToLocalChecked();
23714 CHECK(v8_num(12)
23715 ->Equals(env.local(), Local<Object>::Cast(desc)
23716 ->Get(env.local(), v8_str("value"))
23717 .ToLocalChecked())
23718 .FromJust());
23719 desc =
23720 x->GetOwnPropertyDescriptor(env.local(), v8_str("p1")).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023721 Local<Function> set =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023722 Local<Function>::Cast(Local<Object>::Cast(desc)
23723 ->Get(env.local(), v8_str("set"))
23724 .ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023725 Local<Function> get =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023726 Local<Function>::Cast(Local<Object>::Cast(desc)
23727 ->Get(env.local(), v8_str("get"))
23728 .ToLocalChecked());
23729 CHECK(v8_num(13)
23730 ->Equals(env.local(),
23731 get->Call(env.local(), x, 0, NULL).ToLocalChecked())
23732 .FromJust());
23733 Local<Value> args[] = {v8_num(14)};
23734 set->Call(env.local(), x, 1, args).ToLocalChecked();
23735 CHECK(v8_num(14)
23736 ->Equals(env.local(),
23737 get->Call(env.local(), x, 0, NULL).ToLocalChecked())
23738 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023739}
23740
23741
23742TEST(Regress411877) {
23743 v8::Isolate* isolate = CcTest::isolate();
23744 v8::HandleScope handle_scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023745 v8::Local<v8::ObjectTemplate> object_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023746 v8::ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023747 object_template->SetAccessCheckCallback(AccessCounter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023748
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023749 v8::Local<Context> context = Context::New(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023750 v8::Context::Scope context_scope(context);
23751
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023752 CHECK(context->Global()
23753 ->Set(context, v8_str("o"),
23754 object_template->NewInstance(context).ToLocalChecked())
23755 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023756 CompileRun("Object.getOwnPropertyNames(o)");
23757}
23758
23759
23760TEST(GetHiddenPropertyTableAfterAccessCheck) {
23761 v8::Isolate* isolate = CcTest::isolate();
23762 v8::HandleScope handle_scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023763 v8::Local<v8::ObjectTemplate> object_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023764 v8::ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023765 object_template->SetAccessCheckCallback(AccessCounter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023766
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023767 v8::Local<Context> context = Context::New(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023768 v8::Context::Scope context_scope(context);
23769
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023770 v8::Local<v8::Object> obj =
23771 object_template->NewInstance(context).ToLocalChecked();
23772 obj->Set(context, v8_str("key"), v8_str("value")).FromJust();
23773 obj->Delete(context, v8_str("key")).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023774
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023775 obj->SetPrivate(context, v8::Private::New(isolate, v8_str("hidden key 2")),
23776 v8_str("hidden value 2"))
23777 .FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023778}
23779
23780
23781TEST(Regress411793) {
23782 v8::Isolate* isolate = CcTest::isolate();
23783 v8::HandleScope handle_scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023784 v8::Local<v8::ObjectTemplate> object_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023785 v8::ObjectTemplate::New(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023786 object_template->SetAccessCheckCallback(AccessCounter);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023787
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023788 v8::Local<Context> context = Context::New(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023789 v8::Context::Scope context_scope(context);
23790
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023791 CHECK(context->Global()
23792 ->Set(context, v8_str("o"),
23793 object_template->NewInstance(context).ToLocalChecked())
23794 .FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023795 CompileRun(
23796 "Object.defineProperty(o, 'key', "
23797 " { get: function() {}, set: function() {} });");
23798}
23799
23800class TestSourceStream : public v8::ScriptCompiler::ExternalSourceStream {
23801 public:
23802 explicit TestSourceStream(const char** chunks) : chunks_(chunks), index_(0) {}
23803
23804 virtual size_t GetMoreData(const uint8_t** src) {
23805 // Unlike in real use cases, this function will never block.
23806 if (chunks_[index_] == NULL) {
23807 return 0;
23808 }
23809 // Copy the data, since the caller takes ownership of it.
23810 size_t len = strlen(chunks_[index_]);
23811 // We don't need to zero-terminate since we return the length.
23812 uint8_t* copy = new uint8_t[len];
23813 memcpy(copy, chunks_[index_], len);
23814 *src = copy;
23815 ++index_;
23816 return len;
23817 }
23818
23819 // Helper for constructing a string from chunks (the compilation needs it
23820 // too).
23821 static char* FullSourceString(const char** chunks) {
23822 size_t total_len = 0;
23823 for (size_t i = 0; chunks[i] != NULL; ++i) {
23824 total_len += strlen(chunks[i]);
23825 }
23826 char* full_string = new char[total_len + 1];
23827 size_t offset = 0;
23828 for (size_t i = 0; chunks[i] != NULL; ++i) {
23829 size_t len = strlen(chunks[i]);
23830 memcpy(full_string + offset, chunks[i], len);
23831 offset += len;
23832 }
23833 full_string[total_len] = 0;
23834 return full_string;
23835 }
23836
23837 private:
23838 const char** chunks_;
23839 unsigned index_;
23840};
23841
23842
23843// Helper function for running streaming tests.
23844void RunStreamingTest(const char** chunks,
23845 v8::ScriptCompiler::StreamedSource::Encoding encoding =
23846 v8::ScriptCompiler::StreamedSource::ONE_BYTE,
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023847 bool expected_success = true,
23848 const char* expected_source_url = NULL,
23849 const char* expected_source_mapping_url = NULL) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023850 LocalContext env;
23851 v8::Isolate* isolate = env->GetIsolate();
23852 v8::HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023853 v8::TryCatch try_catch(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023854
23855 v8::ScriptCompiler::StreamedSource source(new TestSourceStream(chunks),
23856 encoding);
23857 v8::ScriptCompiler::ScriptStreamingTask* task =
23858 v8::ScriptCompiler::StartStreamingScript(isolate, &source);
23859
23860 // TestSourceStream::GetMoreData won't block, so it's OK to just run the
23861 // task here in the main thread.
23862 task->Run();
23863 delete task;
23864
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023865 // Possible errors are only produced while compiling.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023866 CHECK_EQ(false, try_catch.HasCaught());
23867
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023868 v8::ScriptOrigin origin(v8_str("http://foo.com"));
23869 char* full_source = TestSourceStream::FullSourceString(chunks);
23870 v8::MaybeLocal<Script> script = v8::ScriptCompiler::Compile(
23871 env.local(), &source, v8_str(full_source), origin);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023872 if (expected_success) {
23873 CHECK(!script.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023874 v8::Local<Value> result(
23875 script.ToLocalChecked()->Run(env.local()).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023876 // All scripts are supposed to return the fixed value 13 when ran.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023877 CHECK_EQ(13, result->Int32Value(env.local()).FromJust());
23878 CheckMagicComments(script.ToLocalChecked(), expected_source_url,
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023879 expected_source_mapping_url);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023880 } else {
23881 CHECK(script.IsEmpty());
23882 CHECK(try_catch.HasCaught());
23883 }
23884 delete[] full_source;
23885}
23886
23887
23888TEST(StreamingSimpleScript) {
23889 // This script is unrealistically small, since no one chunk is enough to fill
23890 // the backing buffer of Scanner, let alone overflow it.
23891 const char* chunks[] = {"function foo() { ret", "urn 13; } f", "oo(); ",
23892 NULL};
23893 RunStreamingTest(chunks);
23894}
23895
23896
23897TEST(StreamingBiggerScript) {
23898 const char* chunk1 =
23899 "function foo() {\n"
23900 " // Make this chunk sufficiently long so that it will overflow the\n"
23901 " // backing buffer of the Scanner.\n"
23902 " var i = 0;\n"
23903 " var result = 0;\n"
23904 " for (i = 0; i < 13; ++i) { result = result + 1; }\n"
23905 " result = 0;\n"
23906 " for (i = 0; i < 13; ++i) { result = result + 1; }\n"
23907 " result = 0;\n"
23908 " for (i = 0; i < 13; ++i) { result = result + 1; }\n"
23909 " result = 0;\n"
23910 " for (i = 0; i < 13; ++i) { result = result + 1; }\n"
23911 " return result;\n"
23912 "}\n";
23913 const char* chunks[] = {chunk1, "foo(); ", NULL};
23914 RunStreamingTest(chunks);
23915}
23916
23917
23918TEST(StreamingScriptWithParseError) {
23919 // Test that parse errors from streamed scripts are propagated correctly.
23920 {
23921 char chunk1[] =
23922 " // This will result in a parse error.\n"
23923 " var if else then foo";
23924 char chunk2[] = " 13\n";
23925 const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
23926
23927 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::ONE_BYTE,
23928 false);
23929 }
23930 // Test that the next script succeeds normally.
23931 {
23932 char chunk1[] =
23933 " // This will be parsed successfully.\n"
23934 " function foo() { return ";
23935 char chunk2[] = " 13; }\n";
23936 const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
23937
23938 RunStreamingTest(chunks);
23939 }
23940}
23941
23942
23943TEST(StreamingUtf8Script) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023944 // We'd want to write \uc481 instead of \xec\x92\x81, but Windows compilers
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023945 // don't like it.
23946 const char* chunk1 =
23947 "function foo() {\n"
23948 " // This function will contain an UTF-8 character which is not in\n"
23949 " // ASCII.\n"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023950 " var foob\xec\x92\x81r = 13;\n"
23951 " return foob\xec\x92\x81r;\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023952 "}\n";
23953 const char* chunks[] = {chunk1, "foo(); ", NULL};
23954 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
23955}
23956
23957
23958TEST(StreamingUtf8ScriptWithSplitCharactersSanityCheck) {
23959 // A sanity check to prove that the approach of splitting UTF-8
23960 // characters is correct. Here is an UTF-8 character which will take three
23961 // bytes.
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023962 const char* reference = "\xec\x92\x81";
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023963 CHECK(3u == strlen(reference)); // NOLINT - no CHECK_EQ for unsigned.
23964
23965 char chunk1[] =
23966 "function foo() {\n"
23967 " // This function will contain an UTF-8 character which is not in\n"
23968 " // ASCII.\n"
23969 " var foob";
23970 char chunk2[] =
23971 "XXXr = 13;\n"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023972 " return foob\xec\x92\x81r;\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023973 "}\n";
23974 for (int i = 0; i < 3; ++i) {
23975 chunk2[i] = reference[i];
23976 }
23977 const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
23978 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
23979}
23980
23981
23982TEST(StreamingUtf8ScriptWithSplitCharacters) {
23983 // Stream data where a multi-byte UTF-8 character is split between two data
23984 // chunks.
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023985 const char* reference = "\xec\x92\x81";
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023986 char chunk1[] =
23987 "function foo() {\n"
23988 " // This function will contain an UTF-8 character which is not in\n"
23989 " // ASCII.\n"
23990 " var foobX";
23991 char chunk2[] =
23992 "XXr = 13;\n"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023993 " return foob\xec\x92\x81r;\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023994 "}\n";
23995 chunk1[strlen(chunk1) - 1] = reference[0];
23996 chunk2[0] = reference[1];
23997 chunk2[1] = reference[2];
23998 const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
23999 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
24000}
24001
24002
24003TEST(StreamingUtf8ScriptWithSplitCharactersValidEdgeCases) {
24004 // Tests edge cases which should still be decoded correctly.
24005
24006 // Case 1: a chunk contains only bytes for a split character (and no other
24007 // data). This kind of a chunk would be exceptionally small, but we should
24008 // still decode it correctly.
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024009 const char* reference = "\xec\x92\x81";
Ben Murdochb8a8cc12014-11-26 15:28:44 +000024010 // The small chunk is at the beginning of the split character
24011 {
24012 char chunk1[] =
24013 "function foo() {\n"
24014 " // This function will contain an UTF-8 character which is not in\n"
24015 " // ASCII.\n"
24016 " var foob";
24017 char chunk2[] = "XX";
24018 char chunk3[] =
24019 "Xr = 13;\n"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024020 " return foob\xec\x92\x81r;\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000024021 "}\n";
24022 chunk2[0] = reference[0];
24023 chunk2[1] = reference[1];
24024 chunk3[0] = reference[2];
24025 const char* chunks[] = {chunk1, chunk2, chunk3, "foo();", NULL};
24026 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
24027 }
24028 // The small chunk is at the end of a character
24029 {
24030 char chunk1[] =
24031 "function foo() {\n"
24032 " // This function will contain an UTF-8 character which is not in\n"
24033 " // ASCII.\n"
24034 " var foobX";
24035 char chunk2[] = "XX";
24036 char chunk3[] =
24037 "r = 13;\n"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024038 " return foob\xec\x92\x81r;\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000024039 "}\n";
24040 chunk1[strlen(chunk1) - 1] = reference[0];
24041 chunk2[0] = reference[1];
24042 chunk2[1] = reference[2];
24043 const char* chunks[] = {chunk1, chunk2, chunk3, "foo();", NULL};
24044 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
24045 }
24046 // Case 2: the script ends with a multi-byte character. Make sure that it's
24047 // decoded correctly and not just ignored.
24048 {
24049 char chunk1[] =
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024050 "var foob\xec\x92\x81 = 13;\n"
24051 "foob\xec\x92\x81";
Ben Murdochb8a8cc12014-11-26 15:28:44 +000024052 const char* chunks[] = {chunk1, NULL};
24053 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
24054 }
24055}
24056
24057
24058TEST(StreamingUtf8ScriptWithSplitCharactersInvalidEdgeCases) {
24059 // Test cases where a UTF-8 character is split over several chunks. Those
24060 // cases are not supported (the embedder should give the data in big enough
24061 // chunks), but we shouldn't crash, just produce a parse error.
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024062 const char* reference = "\xec\x92\x81";
Ben Murdochb8a8cc12014-11-26 15:28:44 +000024063 char chunk1[] =
24064 "function foo() {\n"
24065 " // This function will contain an UTF-8 character which is not in\n"
24066 " // ASCII.\n"
24067 " var foobX";
24068 char chunk2[] = "X";
24069 char chunk3[] =
24070 "Xr = 13;\n"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024071 " return foob\xec\x92\x81r;\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000024072 "}\n";
24073 chunk1[strlen(chunk1) - 1] = reference[0];
24074 chunk2[0] = reference[1];
24075 chunk3[0] = reference[2];
24076 const char* chunks[] = {chunk1, chunk2, chunk3, "foo();", NULL};
24077
24078 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, false);
24079}
24080
24081
24082TEST(StreamingProducesParserCache) {
24083 i::FLAG_min_preparse_length = 0;
24084 const char* chunks[] = {"function foo() { ret", "urn 13; } f", "oo(); ",
24085 NULL};
24086
24087 LocalContext env;
24088 v8::Isolate* isolate = env->GetIsolate();
24089 v8::HandleScope scope(isolate);
24090
24091 v8::ScriptCompiler::StreamedSource source(
24092 new TestSourceStream(chunks),
24093 v8::ScriptCompiler::StreamedSource::ONE_BYTE);
24094 v8::ScriptCompiler::ScriptStreamingTask* task =
24095 v8::ScriptCompiler::StartStreamingScript(
24096 isolate, &source, v8::ScriptCompiler::kProduceParserCache);
24097
24098 // TestSourceStream::GetMoreData won't block, so it's OK to just run the
24099 // task here in the main thread.
24100 task->Run();
24101 delete task;
24102
24103 const v8::ScriptCompiler::CachedData* cached_data = source.GetCachedData();
24104 CHECK(cached_data != NULL);
24105 CHECK(cached_data->data != NULL);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024106 CHECK(!cached_data->rejected);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000024107 CHECK_GT(cached_data->length, 0);
24108}
24109
24110
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024111TEST(StreamingWithDebuggingEnabledLate) {
24112 // The streaming parser can only parse lazily, i.e. inner functions are not
24113 // fully parsed. However, we may compile inner functions eagerly when
24114 // debugging. Make sure that we can deal with this when turning on debugging
24115 // after streaming parser has already finished parsing.
24116 i::FLAG_min_preparse_length = 0;
24117 const char* chunks[] = {"with({x:1}) {",
24118 " var foo = function foo(y) {",
24119 " return x + y;",
24120 " };",
24121 " foo(2);",
24122 "}",
24123 NULL};
24124
24125 LocalContext env;
24126 v8::Isolate* isolate = env->GetIsolate();
24127 v8::HandleScope scope(isolate);
24128 v8::TryCatch try_catch(isolate);
24129
24130 v8::ScriptCompiler::StreamedSource source(
24131 new TestSourceStream(chunks),
24132 v8::ScriptCompiler::StreamedSource::ONE_BYTE);
24133 v8::ScriptCompiler::ScriptStreamingTask* task =
24134 v8::ScriptCompiler::StartStreamingScript(isolate, &source);
24135
24136 task->Run();
24137 delete task;
24138
24139 CHECK(!try_catch.HasCaught());
24140
24141 v8::ScriptOrigin origin(v8_str("http://foo.com"));
24142 char* full_source = TestSourceStream::FullSourceString(chunks);
24143
24144 EnableDebugger(isolate);
24145
24146 v8::Local<Script> script =
24147 v8::ScriptCompiler::Compile(env.local(), &source, v8_str(full_source),
24148 origin)
24149 .ToLocalChecked();
24150
24151 Maybe<uint32_t> result =
24152 script->Run(env.local()).ToLocalChecked()->Uint32Value(env.local());
24153 CHECK_EQ(3U, result.FromMaybe(0));
24154
24155 delete[] full_source;
24156
24157 DisableDebugger(isolate);
24158}
24159
24160
Ben Murdochb8a8cc12014-11-26 15:28:44 +000024161TEST(StreamingScriptWithInvalidUtf8) {
24162 // Regression test for a crash: test that invalid UTF-8 bytes in the end of a
24163 // chunk don't produce a crash.
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024164 const char* reference = "\xec\x92\x81\x80\x80";
Ben Murdochb8a8cc12014-11-26 15:28:44 +000024165 char chunk1[] =
24166 "function foo() {\n"
24167 " // This function will contain an UTF-8 character which is not in\n"
24168 " // ASCII.\n"
24169 " var foobXXXXX"; // Too many bytes which look like incomplete chars!
24170 char chunk2[] =
24171 "r = 13;\n"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024172 " return foob\xec\x92\x81\x80\x80r;\n"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000024173 "}\n";
24174 for (int i = 0; i < 5; ++i) chunk1[strlen(chunk1) - 5 + i] = reference[i];
24175
24176 const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
24177 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, false);
24178}
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024179
24180
24181TEST(StreamingUtf8ScriptWithMultipleMultibyteCharactersSomeSplit) {
24182 // Regression test: Stream data where there are several multi-byte UTF-8
24183 // characters in a sequence and one of them is split between two data chunks.
24184 const char* reference = "\xec\x92\x81";
24185 char chunk1[] =
24186 "function foo() {\n"
24187 " // This function will contain an UTF-8 character which is not in\n"
24188 " // ASCII.\n"
24189 " var foob\xec\x92\x81X";
24190 char chunk2[] =
24191 "XXr = 13;\n"
24192 " return foob\xec\x92\x81\xec\x92\x81r;\n"
24193 "}\n";
24194 chunk1[strlen(chunk1) - 1] = reference[0];
24195 chunk2[0] = reference[1];
24196 chunk2[1] = reference[2];
24197 const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
24198 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
24199}
24200
24201
24202TEST(StreamingUtf8ScriptWithMultipleMultibyteCharactersSomeSplit2) {
24203 // Another regression test, similar to the previous one. The difference is
24204 // that the split character is not the last one in the sequence.
24205 const char* reference = "\xec\x92\x81";
24206 char chunk1[] =
24207 "function foo() {\n"
24208 " // This function will contain an UTF-8 character which is not in\n"
24209 " // ASCII.\n"
24210 " var foobX";
24211 char chunk2[] =
24212 "XX\xec\x92\x81r = 13;\n"
24213 " return foob\xec\x92\x81\xec\x92\x81r;\n"
24214 "}\n";
24215 chunk1[strlen(chunk1) - 1] = reference[0];
24216 chunk2[0] = reference[1];
24217 chunk2[1] = reference[2];
24218 const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
24219 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
24220}
24221
24222
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024223TEST(StreamingWithHarmonyScopes) {
24224 // Don't use RunStreamingTest here so that both scripts get to use the same
24225 // LocalContext and HandleScope.
24226 LocalContext env;
24227 v8::Isolate* isolate = env->GetIsolate();
24228 v8::HandleScope scope(isolate);
24229
24230 // First, run a script with a let variable.
24231 CompileRun("\"use strict\"; let x = 1;");
24232
24233 // Then stream a script which (erroneously) tries to introduce the same
24234 // variable again.
24235 const char* chunks[] = {"\"use strict\"; let x = 2;", NULL};
24236
24237 v8::TryCatch try_catch(isolate);
24238 v8::ScriptCompiler::StreamedSource source(
24239 new TestSourceStream(chunks),
24240 v8::ScriptCompiler::StreamedSource::ONE_BYTE);
24241 v8::ScriptCompiler::ScriptStreamingTask* task =
24242 v8::ScriptCompiler::StartStreamingScript(isolate, &source);
24243 task->Run();
24244 delete task;
24245
24246 // Parsing should succeed (the script will be parsed and compiled in a context
24247 // independent way, so the error is not detected).
24248 CHECK_EQ(false, try_catch.HasCaught());
24249
24250 v8::ScriptOrigin origin(v8_str("http://foo.com"));
24251 char* full_source = TestSourceStream::FullSourceString(chunks);
24252 v8::Local<Script> script =
24253 v8::ScriptCompiler::Compile(env.local(), &source, v8_str(full_source),
24254 origin)
24255 .ToLocalChecked();
24256 CHECK(!script.IsEmpty());
24257 CHECK_EQ(false, try_catch.HasCaught());
24258
24259 // Running the script exposes the error.
24260 CHECK(script->Run(env.local()).IsEmpty());
24261 CHECK(try_catch.HasCaught());
24262 delete[] full_source;
24263}
24264
24265
24266TEST(CodeCache) {
24267 v8::Isolate::CreateParams create_params;
24268 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
24269
24270 const char* source = "Math.sqrt(4)";
24271 const char* origin = "code cache test";
24272 v8::ScriptCompiler::CachedData* cache;
24273
24274 v8::Isolate* isolate1 = v8::Isolate::New(create_params);
24275 {
24276 v8::Isolate::Scope iscope(isolate1);
24277 v8::HandleScope scope(isolate1);
24278 v8::Local<v8::Context> context = v8::Context::New(isolate1);
24279 v8::Context::Scope cscope(context);
24280 v8::Local<v8::String> source_string = v8_str(source);
24281 v8::ScriptOrigin script_origin(v8_str(origin));
24282 v8::ScriptCompiler::Source source(source_string, script_origin);
24283 v8::ScriptCompiler::CompileOptions option =
24284 v8::ScriptCompiler::kProduceCodeCache;
24285 v8::ScriptCompiler::Compile(context, &source, option).ToLocalChecked();
24286 int length = source.GetCachedData()->length;
24287 uint8_t* cache_data = new uint8_t[length];
24288 memcpy(cache_data, source.GetCachedData()->data, length);
24289 cache = new v8::ScriptCompiler::CachedData(
24290 cache_data, length, v8::ScriptCompiler::CachedData::BufferOwned);
24291 }
24292 isolate1->Dispose();
24293
24294 v8::Isolate* isolate2 = v8::Isolate::New(create_params);
24295 {
24296 v8::Isolate::Scope iscope(isolate2);
24297 v8::HandleScope scope(isolate2);
24298 v8::Local<v8::Context> context = v8::Context::New(isolate2);
24299 v8::Context::Scope cscope(context);
24300 v8::Local<v8::String> source_string = v8_str(source);
24301 v8::ScriptOrigin script_origin(v8_str(origin));
24302 v8::ScriptCompiler::Source source(source_string, script_origin, cache);
24303 v8::ScriptCompiler::CompileOptions option =
24304 v8::ScriptCompiler::kConsumeCodeCache;
24305 v8::Local<v8::Script> script;
24306 {
24307 i::DisallowCompilation no_compile(
24308 reinterpret_cast<i::Isolate*>(isolate2));
24309 script = v8::ScriptCompiler::Compile(context, &source, option)
24310 .ToLocalChecked();
24311 }
24312 CHECK_EQ(2, script->Run(context)
24313 .ToLocalChecked()
24314 ->ToInt32(context)
24315 .ToLocalChecked()
24316 ->Int32Value(context)
24317 .FromJust());
24318 }
24319 isolate2->Dispose();
24320}
24321
24322
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024323void TestInvalidCacheData(v8::ScriptCompiler::CompileOptions option) {
24324 const char* garbage = "garbage garbage garbage garbage garbage garbage";
24325 const uint8_t* data = reinterpret_cast<const uint8_t*>(garbage);
24326 int length = 16;
24327 v8::ScriptCompiler::CachedData* cached_data =
24328 new v8::ScriptCompiler::CachedData(data, length);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024329 CHECK(!cached_data->rejected);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024330 v8::ScriptOrigin origin(v8_str("origin"));
24331 v8::ScriptCompiler::Source source(v8_str("42"), origin, cached_data);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024332 v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
24333 v8::Local<v8::Script> script =
24334 v8::ScriptCompiler::Compile(context, &source, option).ToLocalChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024335 CHECK(cached_data->rejected);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024336 CHECK_EQ(
24337 42,
24338 script->Run(context).ToLocalChecked()->Int32Value(context).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024339}
24340
Ben Murdochc5610432016-08-08 18:44:38 +010024341TEST(InvalidParserCacheData) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024342 v8::V8::Initialize();
24343 v8::HandleScope scope(CcTest::isolate());
24344 LocalContext context;
Ben Murdochda12d292016-06-02 14:46:10 +010024345 if (i::FLAG_lazy && !(i::FLAG_ignition && i::FLAG_ignition_eager)) {
24346 // Cached parser data is not consumed while parsing eagerly.
24347 TestInvalidCacheData(v8::ScriptCompiler::kConsumeParserCache);
24348 }
Ben Murdochc5610432016-08-08 18:44:38 +010024349}
24350
24351TEST(InvalidCodeCacheData) {
24352 v8::V8::Initialize();
24353 v8::HandleScope scope(CcTest::isolate());
24354 LocalContext context;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024355 TestInvalidCacheData(v8::ScriptCompiler::kConsumeCodeCache);
24356}
24357
24358
24359TEST(ParserCacheRejectedGracefully) {
Ben Murdochda12d292016-06-02 14:46:10 +010024360 // Producing cached parser data while parsing eagerly is not supported.
24361 if (!i::FLAG_lazy || (i::FLAG_ignition && i::FLAG_ignition_eager)) return;
24362
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024363 i::FLAG_min_preparse_length = 0;
24364 v8::V8::Initialize();
24365 v8::HandleScope scope(CcTest::isolate());
24366 LocalContext context;
24367 // Produce valid cached data.
24368 v8::ScriptOrigin origin(v8_str("origin"));
24369 v8::Local<v8::String> source_str = v8_str("function foo() {}");
24370 v8::ScriptCompiler::Source source(source_str, origin);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024371 v8::Local<v8::Script> script =
24372 v8::ScriptCompiler::Compile(context.local(), &source,
24373 v8::ScriptCompiler::kProduceParserCache)
24374 .ToLocalChecked();
24375 USE(script);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024376 const v8::ScriptCompiler::CachedData* original_cached_data =
24377 source.GetCachedData();
24378 CHECK(original_cached_data != NULL);
24379 CHECK(original_cached_data->data != NULL);
24380 CHECK(!original_cached_data->rejected);
24381 CHECK_GT(original_cached_data->length, 0);
24382 // Recompiling the same script with it won't reject the data.
24383 {
24384 v8::ScriptCompiler::Source source_with_cached_data(
24385 source_str, origin,
24386 new v8::ScriptCompiler::CachedData(original_cached_data->data,
24387 original_cached_data->length));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024388 v8::Local<v8::Script> script =
24389 v8::ScriptCompiler::Compile(context.local(), &source_with_cached_data,
24390 v8::ScriptCompiler::kConsumeParserCache)
24391 .ToLocalChecked();
24392 USE(script);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024393 const v8::ScriptCompiler::CachedData* new_cached_data =
24394 source_with_cached_data.GetCachedData();
24395 CHECK(new_cached_data != NULL);
24396 CHECK(!new_cached_data->rejected);
24397 }
24398 // Compile an incompatible script with the cached data. The new script doesn't
24399 // have the same starting position for the function as the old one, so the old
24400 // cached data will be incompatible with it and will be rejected.
24401 {
24402 v8::Local<v8::String> incompatible_source_str =
24403 v8_str(" function foo() {}");
24404 v8::ScriptCompiler::Source source_with_cached_data(
24405 incompatible_source_str, origin,
24406 new v8::ScriptCompiler::CachedData(original_cached_data->data,
24407 original_cached_data->length));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024408 v8::Local<v8::Script> script =
24409 v8::ScriptCompiler::Compile(context.local(), &source_with_cached_data,
24410 v8::ScriptCompiler::kConsumeParserCache)
24411 .ToLocalChecked();
24412 USE(script);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024413 const v8::ScriptCompiler::CachedData* new_cached_data =
24414 source_with_cached_data.GetCachedData();
24415 CHECK(new_cached_data != NULL);
24416 CHECK(new_cached_data->rejected);
24417 }
24418}
24419
24420
24421TEST(StringConcatOverflow) {
24422 v8::V8::Initialize();
24423 v8::HandleScope scope(CcTest::isolate());
24424 RandomLengthOneByteResource* r =
24425 new RandomLengthOneByteResource(i::String::kMaxLength);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024426 v8::Local<v8::String> str =
24427 v8::String::NewExternalOneByte(CcTest::isolate(), r).ToLocalChecked();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024428 CHECK(!str.IsEmpty());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024429 v8::TryCatch try_catch(CcTest::isolate());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024430 v8::Local<v8::String> result = v8::String::Concat(str, str);
24431 CHECK(result.IsEmpty());
24432 CHECK(!try_catch.HasCaught());
24433}
24434
24435
24436TEST(TurboAsmDisablesNeuter) {
Ben Murdochc5610432016-08-08 18:44:38 +010024437 i::FLAG_allow_natives_syntax = true;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024438 v8::V8::Initialize();
24439 v8::HandleScope scope(CcTest::isolate());
24440 LocalContext context;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024441 bool should_be_neuterable = !i::FLAG_turbo_asm;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024442 const char* load =
24443 "function Module(stdlib, foreign, heap) {"
24444 " 'use asm';"
24445 " var MEM32 = new stdlib.Int32Array(heap);"
24446 " function load() { return MEM32[0]; }"
24447 " return { load: load };"
24448 "}"
24449 "var buffer = new ArrayBuffer(4);"
Ben Murdochc5610432016-08-08 18:44:38 +010024450 "var module = Module(this, {}, buffer);"
24451 "%OptimizeFunctionOnNextCall(module.load);"
24452 "module.load();"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024453 "buffer";
24454
24455 v8::Local<v8::ArrayBuffer> result = CompileRun(load).As<v8::ArrayBuffer>();
24456 CHECK_EQ(should_be_neuterable, result->IsNeuterable());
24457
24458 const char* store =
24459 "function Module(stdlib, foreign, heap) {"
24460 " 'use asm';"
24461 " var MEM32 = new stdlib.Int32Array(heap);"
24462 " function store() { MEM32[0] = 0; }"
24463 " return { store: store };"
24464 "}"
24465 "var buffer = new ArrayBuffer(4);"
Ben Murdochc5610432016-08-08 18:44:38 +010024466 "var module = Module(this, {}, buffer);"
24467 "%OptimizeFunctionOnNextCall(module.store);"
24468 "module.store();"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024469 "buffer";
24470
24471 result = CompileRun(store).As<v8::ArrayBuffer>();
24472 CHECK_EQ(should_be_neuterable, result->IsNeuterable());
24473}
24474
24475
24476TEST(GetPrototypeAccessControl) {
24477 i::FLAG_allow_natives_syntax = true;
24478 v8::Isolate* isolate = CcTest::isolate();
24479 v8::HandleScope handle_scope(isolate);
24480 LocalContext env;
24481
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024482 v8::Local<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New(isolate);
24483 obj_template->SetAccessCheckCallback(AccessAlwaysBlocked);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024484
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024485 CHECK(env->Global()
24486 ->Set(env.local(), v8_str("prohibited"),
24487 obj_template->NewInstance(env.local()).ToLocalChecked())
24488 .FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024489
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024490 CHECK(CompileRun(
24491 "function f() { return %_GetPrototype(prohibited); }"
24492 "%OptimizeFunctionOnNextCall(f);"
24493 "f();")->IsNull());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024494}
24495
24496
24497TEST(GetPrototypeHidden) {
24498 i::FLAG_allow_natives_syntax = true;
24499 v8::Isolate* isolate = CcTest::isolate();
24500 v8::HandleScope handle_scope(isolate);
24501 LocalContext env;
24502
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024503 Local<FunctionTemplate> t = FunctionTemplate::New(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024504 t->SetHiddenPrototype(true);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024505 Local<Object> proto = t->GetFunction(env.local())
24506 .ToLocalChecked()
24507 ->NewInstance(env.local())
24508 .ToLocalChecked();
24509 Local<Object> object = Object::New(isolate);
24510 Local<Object> proto2 = Object::New(isolate);
24511 object->SetPrototype(env.local(), proto).FromJust();
24512 proto->SetPrototype(env.local(), proto2).FromJust();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024513
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024514 CHECK(env->Global()->Set(env.local(), v8_str("object"), object).FromJust());
24515 CHECK(env->Global()->Set(env.local(), v8_str("proto"), proto).FromJust());
24516 CHECK(env->Global()->Set(env.local(), v8_str("proto2"), proto2).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024517
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024518 v8::Local<v8::Value> result = CompileRun("%_GetPrototype(object)");
24519 CHECK(result->Equals(env.local(), proto2).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024520
24521 result = CompileRun(
24522 "function f() { return %_GetPrototype(object); }"
24523 "%OptimizeFunctionOnNextCall(f);"
24524 "f()");
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024525 CHECK(result->Equals(env.local(), proto2).FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024526}
24527
24528
24529TEST(ClassPrototypeCreationContext) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024530 v8::Isolate* isolate = CcTest::isolate();
24531 v8::HandleScope handle_scope(isolate);
24532 LocalContext env;
24533
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024534 Local<Object> result = Local<Object>::Cast(
Emily Bernierd0a1eb72015-03-24 16:35:39 -040024535 CompileRun("'use strict'; class Example { }; Example.prototype"));
24536 CHECK(env.local() == result->CreationContext());
24537}
24538
24539
24540TEST(SimpleStreamingScriptWithSourceURL) {
24541 const char* chunks[] = {"function foo() { ret", "urn 13; } f", "oo();\n",
24542 "//# sourceURL=bar2.js\n", NULL};
24543 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, true,
24544 "bar2.js");
24545}
24546
24547
24548TEST(StreamingScriptWithSplitSourceURL) {
24549 const char* chunks[] = {"function foo() { ret", "urn 13; } f",
24550 "oo();\n//# sourceURL=b", "ar2.js\n", NULL};
24551 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, true,
24552 "bar2.js");
24553}
24554
24555
24556TEST(StreamingScriptWithSourceMappingURLInTheMiddle) {
24557 const char* chunks[] = {"function foo() { ret", "urn 13; }\n//#",
24558 " sourceMappingURL=bar2.js\n", "foo();", NULL};
24559 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, true, NULL,
24560 "bar2.js");
24561}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024562
24563
24564TEST(NewStringRangeError) {
24565 v8::Isolate* isolate = CcTest::isolate();
24566 v8::HandleScope handle_scope(isolate);
24567 const int length = i::String::kMaxLength + 1;
24568 const int buffer_size = length * sizeof(uint16_t);
24569 void* buffer = malloc(buffer_size);
24570 if (buffer == NULL) return;
24571 memset(buffer, 'A', buffer_size);
24572 {
24573 v8::TryCatch try_catch(isolate);
24574 char* data = reinterpret_cast<char*>(buffer);
24575 CHECK(v8::String::NewFromUtf8(isolate, data, v8::NewStringType::kNormal,
24576 length)
24577 .IsEmpty());
24578 CHECK(!try_catch.HasCaught());
24579 }
24580 {
24581 v8::TryCatch try_catch(isolate);
24582 uint8_t* data = reinterpret_cast<uint8_t*>(buffer);
24583 CHECK(v8::String::NewFromOneByte(isolate, data, v8::NewStringType::kNormal,
24584 length)
24585 .IsEmpty());
24586 CHECK(!try_catch.HasCaught());
24587 }
24588 {
24589 v8::TryCatch try_catch(isolate);
24590 uint16_t* data = reinterpret_cast<uint16_t*>(buffer);
24591 CHECK(v8::String::NewFromTwoByte(isolate, data, v8::NewStringType::kNormal,
24592 length)
24593 .IsEmpty());
24594 CHECK(!try_catch.HasCaught());
24595 }
24596 free(buffer);
24597}
24598
24599
24600TEST(SealHandleScope) {
24601 v8::Isolate* isolate = CcTest::isolate();
24602 v8::HandleScope handle_scope(isolate);
24603 LocalContext env;
24604
24605 v8::SealHandleScope seal(isolate);
24606
24607 // Should fail
24608 v8::Local<v8::Object> obj = v8::Object::New(isolate);
24609
24610 USE(obj);
24611}
24612
24613
24614TEST(SealHandleScopeNested) {
24615 v8::Isolate* isolate = CcTest::isolate();
24616 v8::HandleScope handle_scope(isolate);
24617 LocalContext env;
24618
24619 v8::SealHandleScope seal(isolate);
24620
24621 {
24622 v8::HandleScope handle_scope(isolate);
24623
24624 // Should work
24625 v8::Local<v8::Object> obj = v8::Object::New(isolate);
24626
24627 USE(obj);
24628 }
24629}
24630
24631
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024632static void ExtrasBindingTestRuntimeFunction(
24633 const v8::FunctionCallbackInfo<v8::Value>& args) {
24634 CHECK_EQ(
24635 3,
24636 args[0]->Int32Value(args.GetIsolate()->GetCurrentContext()).FromJust());
24637 args.GetReturnValue().Set(v8_num(7));
24638}
24639
Ben Murdoch097c5b22016-05-18 11:27:45 +010024640TEST(ExtrasFunctionSource) {
24641 v8::Isolate* isolate = CcTest::isolate();
24642 v8::HandleScope handle_scope(isolate);
24643 LocalContext env;
24644
24645 v8::Local<v8::Object> binding = env->GetExtrasBindingObject();
24646
24647 // Functions defined in extras do not expose source code.
24648 auto func = binding->Get(env.local(), v8_str("testFunctionToString"))
24649 .ToLocalChecked()
24650 .As<v8::Function>();
24651 auto undefined = v8::Undefined(isolate);
24652 auto result = func->Call(env.local(), undefined, 0, {})
24653 .ToLocalChecked()
24654 .As<v8::String>();
24655 CHECK(result->StrictEquals(v8_str("function foo() { [native code] }")));
24656
24657 // Functions defined in extras do not show up in the stack trace.
24658 auto wrapper = binding->Get(env.local(), v8_str("testStackTrace"))
24659 .ToLocalChecked()
24660 .As<v8::Function>();
24661 CHECK(env->Global()->Set(env.local(), v8_str("wrapper"), wrapper).FromJust());
24662 ExpectString(
24663 "function f(x) { return wrapper(x) }"
24664 "function g() { return new Error().stack; }"
24665 "f(g)",
24666 "Error\n"
24667 " at g (<anonymous>:1:58)\n"
24668 " at f (<anonymous>:1:24)\n"
24669 " at <anonymous>:1:78");
24670}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024671
24672TEST(ExtrasBindingObject) {
24673 v8::Isolate* isolate = CcTest::isolate();
24674 v8::HandleScope handle_scope(isolate);
24675 LocalContext env;
24676
24677 // standalone.gypi ensures we include the test-extra.js file, which should
24678 // export the tested functions.
24679 v8::Local<v8::Object> binding = env->GetExtrasBindingObject();
24680
24681 auto func = binding->Get(env.local(), v8_str("testExtraShouldReturnFive"))
24682 .ToLocalChecked()
24683 .As<v8::Function>();
24684 auto undefined = v8::Undefined(isolate);
24685 auto result = func->Call(env.local(), undefined, 0, {})
24686 .ToLocalChecked()
24687 .As<v8::Number>();
24688 CHECK_EQ(5, result->Int32Value(env.local()).FromJust());
24689
24690 v8::Local<v8::FunctionTemplate> runtimeFunction =
24691 v8::FunctionTemplate::New(isolate, ExtrasBindingTestRuntimeFunction);
24692 binding->Set(env.local(), v8_str("runtime"),
24693 runtimeFunction->GetFunction(env.local()).ToLocalChecked())
24694 .FromJust();
24695 func = binding->Get(env.local(), v8_str("testExtraShouldCallToRuntime"))
24696 .ToLocalChecked()
24697 .As<v8::Function>();
24698 result = func->Call(env.local(), undefined, 0, {})
24699 .ToLocalChecked()
24700 .As<v8::Number>();
24701 CHECK_EQ(7, result->Int32Value(env.local()).FromJust());
24702}
24703
24704
24705TEST(ExperimentalExtras) {
24706 i::FLAG_experimental_extras = true;
24707
24708 v8::Isolate* isolate = CcTest::isolate();
24709 v8::HandleScope handle_scope(isolate);
24710 LocalContext env;
24711
24712 // standalone.gypi ensures we include the test-experimental-extra.js file,
24713 // which should export the tested functions.
24714 v8::Local<v8::Object> binding = env->GetExtrasBindingObject();
24715
24716 auto func =
24717 binding->Get(env.local(), v8_str("testExperimentalExtraShouldReturnTen"))
24718 .ToLocalChecked()
24719 .As<v8::Function>();
24720 auto undefined = v8::Undefined(isolate);
24721 auto result = func->Call(env.local(), undefined, 0, {})
24722 .ToLocalChecked()
24723 .As<v8::Number>();
24724 CHECK_EQ(10, result->Int32Value(env.local()).FromJust());
24725
24726 v8::Local<v8::FunctionTemplate> runtimeFunction =
24727 v8::FunctionTemplate::New(isolate, ExtrasBindingTestRuntimeFunction);
24728 binding->Set(env.local(), v8_str("runtime"),
24729 runtimeFunction->GetFunction(env.local()).ToLocalChecked())
24730 .FromJust();
24731 func = binding->Get(env.local(),
24732 v8_str("testExperimentalExtraShouldCallToRuntime"))
24733 .ToLocalChecked()
24734 .As<v8::Function>();
24735 result = func->Call(env.local(), undefined, 0, {})
24736 .ToLocalChecked()
24737 .As<v8::Number>();
24738 CHECK_EQ(7, result->Int32Value(env.local()).FromJust());
24739}
24740
24741
24742TEST(ExtrasUtilsObject) {
24743 LocalContext context;
24744 v8::Isolate* isolate = context->GetIsolate();
24745 v8::HandleScope handle_scope(isolate);
24746
24747 LocalContext env;
24748 v8::Local<v8::Object> binding = env->GetExtrasBindingObject();
24749
24750 auto func = binding->Get(env.local(), v8_str("testExtraCanUseUtils"))
24751 .ToLocalChecked()
24752 .As<v8::Function>();
24753 auto undefined = v8::Undefined(isolate);
24754 auto result = func->Call(env.local(), undefined, 0, {})
24755 .ToLocalChecked()
24756 .As<v8::Object>();
24757
24758 auto private_symbol = result->Get(env.local(), v8_str("privateSymbol"))
24759 .ToLocalChecked()
24760 .As<v8::Symbol>();
24761 i::Handle<i::Symbol> ips = v8::Utils::OpenHandle(*private_symbol);
24762 CHECK_EQ(true, ips->IsPrivate());
24763
24764 CompileRun("var result = 0; function store(x) { result = x; }");
24765 auto store = CompileRun("store").As<v8::Function>();
24766
24767 auto fulfilled_promise = result->Get(env.local(), v8_str("fulfilledPromise"))
24768 .ToLocalChecked()
24769 .As<v8::Promise>();
24770 fulfilled_promise->Then(env.local(), store).ToLocalChecked();
24771 isolate->RunMicrotasks();
24772 CHECK_EQ(1, CompileRun("result")->Int32Value(env.local()).FromJust());
24773
24774 auto fulfilled_promise_2 =
24775 result->Get(env.local(), v8_str("fulfilledPromise2"))
24776 .ToLocalChecked()
24777 .As<v8::Promise>();
24778 fulfilled_promise_2->Then(env.local(), store).ToLocalChecked();
24779 isolate->RunMicrotasks();
24780 CHECK_EQ(2, CompileRun("result")->Int32Value(env.local()).FromJust());
24781
24782 auto rejected_promise = result->Get(env.local(), v8_str("rejectedPromise"))
24783 .ToLocalChecked()
24784 .As<v8::Promise>();
24785 rejected_promise->Catch(env.local(), store).ToLocalChecked();
24786 isolate->RunMicrotasks();
24787 CHECK_EQ(3, CompileRun("result")->Int32Value(env.local()).FromJust());
24788}
24789
24790
24791TEST(Map) {
24792 v8::Isolate* isolate = CcTest::isolate();
24793 v8::HandleScope handle_scope(isolate);
24794 LocalContext env;
24795
24796 v8::Local<v8::Map> map = v8::Map::New(isolate);
24797 CHECK(map->IsObject());
24798 CHECK(map->IsMap());
24799 CHECK(map->GetPrototype()->StrictEquals(CompileRun("Map.prototype")));
24800 CHECK_EQ(0U, map->Size());
24801
24802 v8::Local<v8::Value> val = CompileRun("new Map([[1, 2], [3, 4]])");
24803 CHECK(val->IsMap());
24804 map = v8::Local<v8::Map>::Cast(val);
24805 CHECK_EQ(2U, map->Size());
24806
24807 v8::Local<v8::Array> contents = map->AsArray();
24808 CHECK_EQ(4U, contents->Length());
24809 CHECK_EQ(
24810 1,
24811 contents->Get(env.local(), 0).ToLocalChecked().As<v8::Int32>()->Value());
24812 CHECK_EQ(
24813 2,
24814 contents->Get(env.local(), 1).ToLocalChecked().As<v8::Int32>()->Value());
24815 CHECK_EQ(
24816 3,
24817 contents->Get(env.local(), 2).ToLocalChecked().As<v8::Int32>()->Value());
24818 CHECK_EQ(
24819 4,
24820 contents->Get(env.local(), 3).ToLocalChecked().As<v8::Int32>()->Value());
24821
24822 CHECK_EQ(2U, map->Size());
24823
24824 CHECK(map->Has(env.local(), v8::Integer::New(isolate, 1)).FromJust());
24825 CHECK(map->Has(env.local(), v8::Integer::New(isolate, 3)).FromJust());
24826
24827 CHECK(!map->Has(env.local(), v8::Integer::New(isolate, 2)).FromJust());
24828 CHECK(!map->Has(env.local(), map).FromJust());
24829
24830 CHECK_EQ(2, map->Get(env.local(), v8::Integer::New(isolate, 1))
24831 .ToLocalChecked()
24832 ->Int32Value(env.local())
24833 .FromJust());
24834 CHECK_EQ(4, map->Get(env.local(), v8::Integer::New(isolate, 3))
24835 .ToLocalChecked()
24836 ->Int32Value(env.local())
24837 .FromJust());
24838
24839 CHECK(map->Get(env.local(), v8::Integer::New(isolate, 42))
24840 .ToLocalChecked()
24841 ->IsUndefined());
24842
24843 CHECK(!map->Set(env.local(), map, map).IsEmpty());
24844 CHECK_EQ(3U, map->Size());
24845 CHECK(map->Has(env.local(), map).FromJust());
24846
24847 CHECK(map->Delete(env.local(), map).FromJust());
24848 CHECK_EQ(2U, map->Size());
24849 CHECK(!map->Has(env.local(), map).FromJust());
24850 CHECK(!map->Delete(env.local(), map).FromJust());
24851
24852 map->Clear();
24853 CHECK_EQ(0U, map->Size());
24854}
24855
24856
24857TEST(Set) {
24858 v8::Isolate* isolate = CcTest::isolate();
24859 v8::HandleScope handle_scope(isolate);
24860 LocalContext env;
24861
24862 v8::Local<v8::Set> set = v8::Set::New(isolate);
24863 CHECK(set->IsObject());
24864 CHECK(set->IsSet());
24865 CHECK(set->GetPrototype()->StrictEquals(CompileRun("Set.prototype")));
24866 CHECK_EQ(0U, set->Size());
24867
24868 v8::Local<v8::Value> val = CompileRun("new Set([1, 2])");
24869 CHECK(val->IsSet());
24870 set = v8::Local<v8::Set>::Cast(val);
24871 CHECK_EQ(2U, set->Size());
24872
24873 v8::Local<v8::Array> keys = set->AsArray();
24874 CHECK_EQ(2U, keys->Length());
24875 CHECK_EQ(1,
24876 keys->Get(env.local(), 0).ToLocalChecked().As<v8::Int32>()->Value());
24877 CHECK_EQ(2,
24878 keys->Get(env.local(), 1).ToLocalChecked().As<v8::Int32>()->Value());
24879
24880 CHECK_EQ(2U, set->Size());
24881
24882 CHECK(set->Has(env.local(), v8::Integer::New(isolate, 1)).FromJust());
24883 CHECK(set->Has(env.local(), v8::Integer::New(isolate, 2)).FromJust());
24884
24885 CHECK(!set->Has(env.local(), v8::Integer::New(isolate, 3)).FromJust());
24886 CHECK(!set->Has(env.local(), set).FromJust());
24887
24888 CHECK(!set->Add(env.local(), set).IsEmpty());
24889 CHECK_EQ(3U, set->Size());
24890 CHECK(set->Has(env.local(), set).FromJust());
24891
24892 CHECK(set->Delete(env.local(), set).FromJust());
24893 CHECK_EQ(2U, set->Size());
24894 CHECK(!set->Has(env.local(), set).FromJust());
24895 CHECK(!set->Delete(env.local(), set).FromJust());
24896
24897 set->Clear();
24898 CHECK_EQ(0U, set->Size());
24899}
24900
Ben Murdochc5610432016-08-08 18:44:38 +010024901TEST(SetDeleteThenAsArray) {
24902 // https://bugs.chromium.org/p/v8/issues/detail?id=4946
24903 v8::Isolate* isolate = CcTest::isolate();
24904 v8::HandleScope handle_scope(isolate);
24905 LocalContext env;
24906
24907 // make a Set
24908 v8::Local<v8::Value> val = CompileRun("new Set([1, 2, 3])");
24909 v8::Local<v8::Set> set = v8::Local<v8::Set>::Cast(val);
24910 CHECK_EQ(3U, set->Size());
24911
24912 // delete the "middle" element (using AsArray to
24913 // determine which element is the "middle" element)
24914 v8::Local<v8::Array> array1 = set->AsArray();
24915 CHECK_EQ(3U, array1->Length());
24916 CHECK(set->Delete(env.local(), array1->Get(env.local(), 1).ToLocalChecked())
24917 .FromJust());
24918
24919 // make sure there are no undefined values when we convert to an array again.
24920 v8::Local<v8::Array> array2 = set->AsArray();
24921 uint32_t length = array2->Length();
24922 CHECK_EQ(2U, length);
24923 for (uint32_t i = 0; i < length; i++) {
24924 CHECK(!array2->Get(env.local(), i).ToLocalChecked()->IsUndefined());
24925 }
24926}
24927
24928TEST(MapDeleteThenAsArray) {
24929 // https://bugs.chromium.org/p/v8/issues/detail?id=4946
24930 v8::Isolate* isolate = CcTest::isolate();
24931 v8::HandleScope handle_scope(isolate);
24932 LocalContext env;
24933
24934 // make a Map
24935 v8::Local<v8::Value> val = CompileRun("new Map([[1, 2], [3, 4], [5, 6]])");
24936 v8::Local<v8::Map> map = v8::Local<v8::Map>::Cast(val);
24937 CHECK_EQ(3U, map->Size());
24938
24939 // delete the "middle" element (using AsArray to
24940 // determine which element is the "middle" element)
24941 v8::Local<v8::Array> array1 = map->AsArray();
24942 CHECK_EQ(6U, array1->Length());
24943 // Map::AsArray returns a flat array, so the second key is at index 2.
24944 v8::Local<v8::Value> key = array1->Get(env.local(), 2).ToLocalChecked();
24945 CHECK(map->Delete(env.local(), key).FromJust());
24946
24947 // make sure there are no undefined values when we convert to an array again.
24948 v8::Local<v8::Array> array2 = map->AsArray();
24949 uint32_t length = array2->Length();
24950 CHECK_EQ(4U, length);
24951 for (uint32_t i = 0; i < length; i++) {
24952 CHECK(!array2->Get(env.local(), i).ToLocalChecked()->IsUndefined());
24953 }
24954}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024955
24956TEST(CompatibleReceiverCheckOnCachedICHandler) {
24957 v8::Isolate* isolate = CcTest::isolate();
24958 v8::HandleScope scope(isolate);
24959 v8::Local<v8::FunctionTemplate> parent = FunctionTemplate::New(isolate);
24960 v8::Local<v8::Signature> signature = v8::Signature::New(isolate, parent);
24961 auto returns_42 =
24962 v8::FunctionTemplate::New(isolate, Returns42, Local<Value>(), signature);
24963 parent->PrototypeTemplate()->SetAccessorProperty(v8_str("age"), returns_42);
24964 v8::Local<v8::FunctionTemplate> child = v8::FunctionTemplate::New(isolate);
24965 child->Inherit(parent);
24966 LocalContext env;
24967 CHECK(env->Global()
24968 ->Set(env.local(), v8_str("Child"),
24969 child->GetFunction(env.local()).ToLocalChecked())
24970 .FromJust());
24971
24972 // Make sure there's a compiled stub for "Child.prototype.age" in the cache.
24973 CompileRun(
24974 "var real = new Child();\n"
24975 "for (var i = 0; i < 3; ++i) {\n"
24976 " real.age;\n"
24977 "}\n");
24978
24979 // Check that the cached stub is never used.
24980 ExpectInt32(
24981 "var fake = Object.create(Child.prototype);\n"
24982 "var result = 0;\n"
24983 "function test(d) {\n"
24984 " if (d == 3) return;\n"
24985 " try {\n"
24986 " fake.age;\n"
24987 " result = 1;\n"
24988 " } catch (e) {\n"
24989 " }\n"
24990 " test(d+1);\n"
24991 "}\n"
24992 "test(0);\n"
24993 "result;\n",
24994 0);
24995}
24996
Ben Murdochda12d292016-06-02 14:46:10 +010024997THREADED_TEST(ReceiverConversionForAccessors) {
24998 LocalContext env;
24999 v8::Isolate* isolate = CcTest::isolate();
25000 v8::HandleScope scope(isolate);
25001 Local<v8::FunctionTemplate> acc =
25002 v8::FunctionTemplate::New(isolate, Returns42);
25003 CHECK(env->Global()
25004 ->Set(env.local(), v8_str("acc"),
25005 acc->GetFunction(env.local()).ToLocalChecked())
25006 .FromJust());
25007
25008 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
25009 templ->SetAccessorProperty(v8_str("acc"), acc, acc);
25010 Local<v8::Object> instance = templ->NewInstance(env.local()).ToLocalChecked();
25011
25012 CHECK(env->Global()->Set(env.local(), v8_str("p"), instance).FromJust());
25013 CHECK(CompileRun("(p.acc == 42)")->BooleanValue(env.local()).FromJust());
25014 CHECK(CompileRun("(p.acc = 7) == 7")->BooleanValue(env.local()).FromJust());
25015
25016 CHECK(!CompileRun("Number.prototype.__proto__ = p;"
25017 "var a = 1;")
25018 .IsEmpty());
25019 CHECK(CompileRun("(a.acc == 42)")->BooleanValue(env.local()).FromJust());
25020 CHECK(CompileRun("(a.acc = 7) == 7")->BooleanValue(env.local()).FromJust());
25021
25022 CHECK(!CompileRun("Boolean.prototype.__proto__ = p;"
25023 "var a = true;")
25024 .IsEmpty());
25025 CHECK(CompileRun("(a.acc == 42)")->BooleanValue(env.local()).FromJust());
25026 CHECK(CompileRun("(a.acc = 7) == 7")->BooleanValue(env.local()).FromJust());
25027
25028 CHECK(!CompileRun("String.prototype.__proto__ = p;"
25029 "var a = 'foo';")
25030 .IsEmpty());
25031 CHECK(CompileRun("(a.acc == 42)")->BooleanValue(env.local()).FromJust());
25032 CHECK(CompileRun("(a.acc = 7) == 7")->BooleanValue(env.local()).FromJust());
25033
25034 CHECK(CompileRun("acc.call(1) == 42")->BooleanValue(env.local()).FromJust());
25035 CHECK(CompileRun("acc.call(true)==42")->BooleanValue(env.local()).FromJust());
25036 CHECK(CompileRun("acc.call('aa')==42")->BooleanValue(env.local()).FromJust());
25037 CHECK(
25038 CompileRun("acc.call(null) == 42")->BooleanValue(env.local()).FromJust());
25039 CHECK(CompileRun("acc.call(undefined) == 42")
25040 ->BooleanValue(env.local())
25041 .FromJust());
25042}
25043
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000025044class FutexInterruptionThread : public v8::base::Thread {
25045 public:
25046 explicit FutexInterruptionThread(v8::Isolate* isolate)
25047 : Thread(Options("FutexInterruptionThread")), isolate_(isolate) {}
25048
25049 virtual void Run() {
25050 // Wait a bit before terminating.
25051 v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(100));
25052 isolate_->TerminateExecution();
25053 }
25054
25055 private:
25056 v8::Isolate* isolate_;
25057};
25058
25059
25060TEST(FutexInterruption) {
25061 i::FLAG_harmony_sharedarraybuffer = true;
25062 v8::Isolate* isolate = CcTest::isolate();
25063 v8::HandleScope scope(isolate);
25064 LocalContext env;
25065
25066 FutexInterruptionThread timeout_thread(isolate);
25067
25068 v8::TryCatch try_catch(CcTest::isolate());
25069 timeout_thread.Start();
25070
25071 CompileRun(
25072 "var ab = new SharedArrayBuffer(4);"
25073 "var i32a = new Int32Array(ab);"
25074 "Atomics.futexWait(i32a, 0, 0);");
25075 CHECK(try_catch.HasTerminated());
25076 timeout_thread.Join();
25077}
25078
25079
25080TEST(EstimatedContextSize) {
25081 v8::Isolate* isolate = CcTest::isolate();
25082 v8::HandleScope scope(isolate);
25083 LocalContext env;
25084 CHECK(50000 < env->EstimatedSize());
25085}
25086
25087
25088static int nb_uncaught_exception_callback_calls = 0;
25089
25090
25091bool NoAbortOnUncaughtException(v8::Isolate* isolate) {
25092 ++nb_uncaught_exception_callback_calls;
25093 return false;
25094}
25095
25096
25097TEST(AbortOnUncaughtExceptionNoAbort) {
25098 v8::Isolate* isolate = CcTest::isolate();
25099 v8::HandleScope handle_scope(isolate);
25100 v8::Local<v8::ObjectTemplate> global_template =
25101 v8::ObjectTemplate::New(isolate);
25102 LocalContext env(NULL, global_template);
25103
25104 i::FLAG_abort_on_uncaught_exception = true;
25105 isolate->SetAbortOnUncaughtExceptionCallback(NoAbortOnUncaughtException);
25106
25107 CompileRun("function boom() { throw new Error(\"boom\") }");
25108
25109 v8::Local<v8::Object> global_object = env->Global();
25110 v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
25111 global_object->Get(env.local(), v8_str("boom")).ToLocalChecked());
25112
25113 CHECK(foo->Call(env.local(), global_object, 0, NULL).IsEmpty());
25114
25115 CHECK_EQ(1, nb_uncaught_exception_callback_calls);
25116}
25117
25118
25119TEST(AccessCheckedIsConcatSpreadable) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000025120 v8::Isolate* isolate = CcTest::isolate();
25121 HandleScope scope(isolate);
25122 LocalContext env;
25123
25124 // Object with access check
25125 Local<ObjectTemplate> spreadable_template = v8::ObjectTemplate::New(isolate);
25126 spreadable_template->SetAccessCheckCallback(AccessBlocker);
25127 spreadable_template->Set(v8::Symbol::GetIsConcatSpreadable(isolate),
25128 v8::Boolean::New(isolate, true));
25129 Local<Object> object =
25130 spreadable_template->NewInstance(env.local()).ToLocalChecked();
25131
25132 allowed_access = true;
25133 CHECK(env->Global()->Set(env.local(), v8_str("object"), object).FromJust());
25134 object->Set(env.local(), v8_str("length"), v8_num(2)).FromJust();
25135 object->Set(env.local(), 0U, v8_str("a")).FromJust();
25136 object->Set(env.local(), 1U, v8_str("b")).FromJust();
25137
25138 // Access check is allowed, and the object is spread
25139 CompileRun("var result = [].concat(object)");
25140 ExpectTrue("Array.isArray(result)");
25141 ExpectString("result[0]", "a");
25142 ExpectString("result[1]", "b");
25143 ExpectTrue("result.length === 2");
25144 ExpectTrue("object[Symbol.isConcatSpreadable]");
25145
25146 // If access check fails, the value of @@isConcatSpreadable is ignored
25147 allowed_access = false;
25148 CompileRun("var result = [].concat(object)");
25149 ExpectTrue("Array.isArray(result)");
25150 ExpectTrue("result[0] === object");
25151 ExpectTrue("result.length === 1");
25152 ExpectTrue("object[Symbol.isConcatSpreadable] === undefined");
25153}
25154
25155
25156TEST(AccessCheckedToStringTag) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000025157 v8::Isolate* isolate = CcTest::isolate();
25158 HandleScope scope(isolate);
25159 LocalContext env;
25160
25161 // Object with access check
25162 Local<ObjectTemplate> object_template = v8::ObjectTemplate::New(isolate);
25163 object_template->SetAccessCheckCallback(AccessBlocker);
25164 Local<Object> object =
25165 object_template->NewInstance(env.local()).ToLocalChecked();
25166
25167 allowed_access = true;
25168 env->Global()->Set(env.local(), v8_str("object"), object).FromJust();
25169 object->Set(env.local(), v8::Symbol::GetToStringTag(isolate), v8_str("hello"))
25170 .FromJust();
25171
25172 // Access check is allowed, and the toStringTag is read
25173 CompileRun("var result = Object.prototype.toString.call(object)");
25174 ExpectString("result", "[object hello]");
25175 ExpectString("object[Symbol.toStringTag]", "hello");
25176
25177 // ToString through the API should succeed too.
25178 String::Utf8Value result_allowed(
25179 object->ObjectProtoToString(env.local()).ToLocalChecked());
25180 CHECK_EQ(0, strcmp(*result_allowed, "[object hello]"));
25181
25182 // If access check fails, the value of @@toStringTag is ignored
25183 allowed_access = false;
25184 CompileRun("var result = Object.prototype.toString.call(object)");
25185 ExpectString("result", "[object Object]");
25186 ExpectTrue("object[Symbol.toStringTag] === undefined");
25187
25188 // ToString through the API should also fail.
25189 String::Utf8Value result_denied(
25190 object->ObjectProtoToString(env.local()).ToLocalChecked());
25191 CHECK_EQ(0, strcmp(*result_denied, "[object Object]"));
25192}
25193
25194
25195TEST(ObjectTemplateIntrinsics) {
25196 v8::Isolate* isolate = CcTest::isolate();
25197 v8::HandleScope scope(isolate);
25198 LocalContext env;
25199
25200 Local<ObjectTemplate> object_template = v8::ObjectTemplate::New(isolate);
25201 object_template->SetIntrinsicDataProperty(v8_str("values"),
25202 v8::kArrayProto_values);
25203 Local<Object> object =
25204 object_template->NewInstance(env.local()).ToLocalChecked();
25205
25206 CHECK(env->Global()->Set(env.local(), v8_str("obj1"), object).FromJust());
25207 ExpectString("typeof obj1.values", "function");
25208
25209 auto values = Local<Function>::Cast(
25210 object->Get(env.local(), v8_str("values")).ToLocalChecked());
25211 auto fn = i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(*values));
25212 auto ctx = v8::Utils::OpenHandle(*env.local());
25213 CHECK_EQ(fn->GetCreationContext(), *ctx);
25214
25215 {
25216 LocalContext env2;
25217 Local<Object> object2 =
25218 object_template->NewInstance(env2.local()).ToLocalChecked();
25219 CHECK(
25220 env2->Global()->Set(env2.local(), v8_str("obj2"), object2).FromJust());
25221 ExpectString("typeof obj2.values", "function");
25222 CHECK_NE(*object->Get(env2.local(), v8_str("values")).ToLocalChecked(),
25223 *object2->Get(env2.local(), v8_str("values")).ToLocalChecked());
25224
25225 auto values2 = Local<Function>::Cast(
25226 object2->Get(env2.local(), v8_str("values")).ToLocalChecked());
25227 auto fn2 = i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(*values2));
25228 auto ctx2 = v8::Utils::OpenHandle(*env2.local());
25229 CHECK_EQ(fn2->GetCreationContext(), *ctx2);
25230 }
25231}
25232
25233
25234TEST(Proxy) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000025235 LocalContext context;
25236 v8::Isolate* isolate = CcTest::isolate();
25237 v8::HandleScope scope(isolate);
25238 v8::Local<v8::Object> target = CompileRun("({})").As<v8::Object>();
25239 v8::Local<v8::Object> handler = CompileRun("({})").As<v8::Object>();
25240
25241 v8::Local<v8::Proxy> proxy =
25242 v8::Proxy::New(context.local(), target, handler).ToLocalChecked();
25243 CHECK(proxy->IsProxy());
25244 CHECK(!target->IsProxy());
25245 CHECK(!proxy->IsRevoked());
25246 CHECK(proxy->GetTarget()->SameValue(target));
25247 CHECK(proxy->GetHandler()->SameValue(handler));
25248
25249 proxy->Revoke();
25250 CHECK(proxy->IsProxy());
25251 CHECK(!target->IsProxy());
25252 CHECK(proxy->IsRevoked());
25253 CHECK(proxy->GetTarget()->SameValue(target));
25254 CHECK(proxy->GetHandler()->IsNull());
25255}
Ben Murdochda12d292016-06-02 14:46:10 +010025256
25257WeakCallCounterAndPersistent<Value>* CreateGarbageWithWeakCallCounter(
25258 v8::Isolate* isolate, WeakCallCounter* counter) {
25259 v8::Locker locker(isolate);
25260 LocalContext env;
25261 HandleScope scope(isolate);
25262 WeakCallCounterAndPersistent<Value>* val =
25263 new WeakCallCounterAndPersistent<Value>(counter);
25264 val->handle.Reset(isolate, Object::New(isolate));
25265 val->handle.SetWeak(val, &WeakPointerCallback,
25266 v8::WeakCallbackType::kParameter);
25267 return val;
25268}
25269
25270class MemoryPressureThread : public v8::base::Thread {
25271 public:
25272 explicit MemoryPressureThread(v8::Isolate* isolate,
25273 v8::MemoryPressureLevel level)
25274 : Thread(Options("MemoryPressureThread")),
25275 isolate_(isolate),
25276 level_(level) {}
25277
25278 virtual void Run() { isolate_->MemoryPressureNotification(level_); }
25279
25280 private:
25281 v8::Isolate* isolate_;
25282 v8::MemoryPressureLevel level_;
25283};
25284
25285TEST(MemoryPressure) {
25286 v8::Isolate* isolate = CcTest::isolate();
25287 WeakCallCounter counter(1234);
25288
25289 // Check that critical memory pressure notification sets GC interrupt.
25290 auto garbage = CreateGarbageWithWeakCallCounter(isolate, &counter);
25291 CHECK(!v8::Locker::IsLocked(isolate));
25292 {
25293 v8::Locker locker(isolate);
25294 v8::HandleScope scope(isolate);
25295 LocalContext env;
25296 MemoryPressureThread memory_pressure_thread(
25297 isolate, v8::MemoryPressureLevel::kCritical);
25298 memory_pressure_thread.Start();
25299 memory_pressure_thread.Join();
25300 // This should trigger GC.
25301 CHECK_EQ(0, counter.NumberOfWeakCalls());
25302 CompileRun("(function noop() { return 0; })()");
25303 CHECK_EQ(1, counter.NumberOfWeakCalls());
25304 }
25305 delete garbage;
25306 // Check that critical memory pressure notification triggers GC.
25307 garbage = CreateGarbageWithWeakCallCounter(isolate, &counter);
25308 {
25309 v8::Locker locker(isolate);
25310 // If isolate is locked, memory pressure notification should trigger GC.
25311 CHECK_EQ(1, counter.NumberOfWeakCalls());
25312 isolate->MemoryPressureNotification(v8::MemoryPressureLevel::kCritical);
25313 CHECK_EQ(2, counter.NumberOfWeakCalls());
25314 }
25315 delete garbage;
25316 // Check that moderate memory pressure notification sets GC into memory
25317 // optimizing mode.
25318 isolate->MemoryPressureNotification(v8::MemoryPressureLevel::kModerate);
25319 CHECK(CcTest::i_isolate()->heap()->ShouldOptimizeForMemoryUsage());
25320 // Check that disabling memory pressure returns GC into normal mode.
25321 isolate->MemoryPressureNotification(v8::MemoryPressureLevel::kNone);
25322 CHECK(!CcTest::i_isolate()->heap()->ShouldOptimizeForMemoryUsage());
25323}
25324
25325TEST(SetIntegrityLevel) {
25326 LocalContext context;
25327 v8::Isolate* isolate = CcTest::isolate();
25328 v8::HandleScope scope(isolate);
25329
25330 v8::Local<v8::Object> obj = v8::Object::New(isolate);
25331 CHECK(context->Global()->Set(context.local(), v8_str("o"), obj).FromJust());
25332
25333 v8::Local<v8::Value> is_frozen = CompileRun("Object.isFrozen(o)");
25334 CHECK(!is_frozen->BooleanValue(context.local()).FromJust());
25335
25336 CHECK(obj->SetIntegrityLevel(context.local(), v8::IntegrityLevel::kFrozen)
25337 .FromJust());
25338
25339 is_frozen = CompileRun("Object.isFrozen(o)");
25340 CHECK(is_frozen->BooleanValue(context.local()).FromJust());
25341}
25342
25343TEST(PrivateForApiIsNumber) {
25344 LocalContext context;
25345 v8::Isolate* isolate = CcTest::isolate();
25346 v8::HandleScope scope(isolate);
25347
25348 // Shouldn't crash.
25349 v8::Private::ForApi(isolate, v8_str("42"));
25350}