blob: c0ba7fd397902bb3c97edc700ddd51964e349761 [file] [log] [blame]
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001// Copyright 2012 the V8 project authors. All rights reserved.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +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
verwaest@chromium.org662436e2013-08-28 08:41:27 +000028#include <climits>
29#include <csignal>
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000030#include <string>
31#include <map>
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000032
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000033#include "v8.h"
34
verwaest@chromium.org662436e2013-08-28 08:41:27 +000035#if V8_OS_POSIX
36#include <unistd.h> // NOLINT
37#endif
38
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000039#include "api.h"
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +000040#include "arguments.h"
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000041#include "cctest.h"
machenbach@chromium.orgc1789ee2013-07-05 07:09:57 +000042#include "compilation-cache.h"
43#include "cpu-profiler.h"
44#include "execution.h"
45#include "isolate.h"
46#include "objects.h"
ager@chromium.org5b2fbee2010-09-08 06:38:15 +000047#include "parser.h"
machenbach@chromium.orgc1789ee2013-07-05 07:09:57 +000048#include "platform.h"
49#include "snapshot.h"
erik.corry@gmail.com4a6c3272010-11-18 12:04:40 +000050#include "unicode-inl.h"
machenbach@chromium.orgc1789ee2013-07-05 07:09:57 +000051#include "utils.h"
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +000052#include "vm-state.h"
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000053
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +000054static const bool kLogThreading = false;
ager@chromium.orgc4c92722009-11-18 14:12:51 +000055
danno@chromium.orgd3c42102013-08-01 16:58:23 +000056using ::v8::Boolean;
57using ::v8::BooleanObject;
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +000058using ::v8::Context;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000059using ::v8::Extension;
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +000060using ::v8::Function;
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000061using ::v8::FunctionTemplate;
62using ::v8::Handle;
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +000063using ::v8::HandleScope;
64using ::v8::Local;
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000065using ::v8::Message;
66using ::v8::MessageCallback;
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +000067using ::v8::Object;
68using ::v8::ObjectTemplate;
69using ::v8::Persistent;
70using ::v8::Script;
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000071using ::v8::StackTrace;
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +000072using ::v8::String;
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000073using ::v8::TryCatch;
74using ::v8::Undefined;
danno@chromium.orgca29dd82013-04-26 11:59:48 +000075using ::v8::UniqueId;
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +000076using ::v8::V8;
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000077using ::v8::Value;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000078
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000079
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000080#define THREADED_PROFILED_TEST(Name) \
81 static void Test##Name(); \
82 TEST(Name##WithProfiler) { \
83 RunWithProfiler(&Test##Name); \
84 } \
85 THREADED_TEST(Name)
machenbach@chromium.org528ce022013-09-23 14:09:36 +000086
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000087
88void RunWithProfiler(void (*test)()) {
89 LocalContext env;
90 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000091 v8::Local<v8::String> profile_name =
92 v8::String::NewFromUtf8(env->GetIsolate(), "my_profile1");
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000093 v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler();
94
95 cpu_profiler->StartCpuProfiling(profile_name);
96 (*test)();
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000097 reinterpret_cast<i::CpuProfiler*>(cpu_profiler)->DeleteAllProfiles();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000098}
99
100
kasperl@chromium.orgeac059f2010-01-25 11:02:06 +0000101static void ExpectString(const char* code, const char* expected) {
102 Local<Value> result = CompileRun(code);
103 CHECK(result->IsString());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +0000104 String::Utf8Value utf8(result);
105 CHECK_EQ(expected, *utf8);
kasperl@chromium.orgeac059f2010-01-25 11:02:06 +0000106}
107
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000108
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000109static void ExpectInt32(const char* code, int expected) {
110 Local<Value> result = CompileRun(code);
111 CHECK(result->IsInt32());
112 CHECK_EQ(expected, result->Int32Value());
113}
kasperl@chromium.orgeac059f2010-01-25 11:02:06 +0000114
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000115
kasperl@chromium.orgeac059f2010-01-25 11:02:06 +0000116static void ExpectBoolean(const char* code, bool expected) {
117 Local<Value> result = CompileRun(code);
118 CHECK(result->IsBoolean());
119 CHECK_EQ(expected, result->BooleanValue());
120}
121
122
kmillikin@chromium.org9155e252010-05-26 13:27:57 +0000123static void ExpectTrue(const char* code) {
124 ExpectBoolean(code, true);
125}
126
127
ager@chromium.orgea4f62e2010-08-16 16:28:43 +0000128static void ExpectFalse(const char* code) {
129 ExpectBoolean(code, false);
130}
131
132
kasperl@chromium.orgeac059f2010-01-25 11:02:06 +0000133static void ExpectObject(const char* code, Local<Value> expected) {
134 Local<Value> result = CompileRun(code);
135 CHECK(result->Equals(expected));
136}
137
138
ager@chromium.orgea4f62e2010-08-16 16:28:43 +0000139static void ExpectUndefined(const char* code) {
140 Local<Value> result = CompileRun(code);
141 CHECK(result->IsUndefined());
142}
143
144
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000145static int signature_callback_count;
jkummerow@chromium.org2c9426b2013-09-05 16:31:13 +0000146static Local<Value> signature_expected_receiver;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000147static void IncrementingSignatureCallback(
148 const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000149 ApiTestFuzzer::Fuzz();
150 signature_callback_count++;
jkummerow@chromium.org2c9426b2013-09-05 16:31:13 +0000151 CHECK_EQ(signature_expected_receiver, args.Holder());
152 CHECK_EQ(signature_expected_receiver, args.This());
machenbach@chromium.org9f18d912013-11-28 13:42:41 +0000153 v8::Handle<v8::Array> result =
154 v8::Array::New(args.GetIsolate(), args.Length());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000155 for (int i = 0; i < args.Length(); i++)
ulan@chromium.org0f13e742014-01-03 15:51:11 +0000156 result->Set(v8::Integer::New(args.GetIsolate(), i), args[i]);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000157 args.GetReturnValue().Set(result);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000158}
159
160
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000161static void SignatureCallback(
162 const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000163 ApiTestFuzzer::Fuzz();
machenbach@chromium.org9f18d912013-11-28 13:42:41 +0000164 v8::Handle<v8::Array> result =
165 v8::Array::New(args.GetIsolate(), args.Length());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000166 for (int i = 0; i < args.Length(); i++) {
ulan@chromium.org0f13e742014-01-03 15:51:11 +0000167 result->Set(v8::Integer::New(args.GetIsolate(), i), args[i]);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000168 }
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000169 args.GetReturnValue().Set(result);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000170}
171
172
dslomov@chromium.org639bac02013-09-09 11:58:54 +0000173// Tests that call v8::V8::Dispose() cannot be threaded.
174TEST(InitializeAndDisposeOnce) {
175 CHECK(v8::V8::Initialize());
176 CHECK(v8::V8::Dispose());
177}
178
179
180// Tests that call v8::V8::Dispose() cannot be threaded.
181TEST(InitializeAndDisposeMultiple) {
182 for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
183 for (int i = 0; i < 3; ++i) CHECK(v8::V8::Initialize());
184 for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
185 // TODO(mstarzinger): This should fail gracefully instead of asserting.
186 // for (int i = 0; i < 3; ++i) CHECK(v8::V8::Initialize());
187 for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
188}
189
190
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000191THREADED_TEST(Handles) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000192 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000193 Local<Context> local_env;
194 {
195 LocalContext env;
196 local_env = env.local();
197 }
198
199 // Local context should still be live.
200 CHECK(!local_env.IsEmpty());
201 local_env->Enter();
202
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +0000203 v8::Handle<v8::Primitive> undef = v8::Undefined(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000204 CHECK(!undef.IsEmpty());
205 CHECK(undef->IsUndefined());
206
207 const char* c_source = "1 + 2 + 3";
machenbach@chromium.orgf9841892013-11-25 12:01:13 +0000208 Local<String> source = String::NewFromUtf8(CcTest::isolate(), c_source);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000209 Local<Script> script = Script::Compile(source);
210 CHECK_EQ(6, script->Run()->Int32Value());
211
212 local_env->Exit();
213}
214
215
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000216THREADED_TEST(IsolateOfContext) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000217 v8::HandleScope scope(CcTest::isolate());
218 v8::Handle<Context> env = Context::New(CcTest::isolate());
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000219
machenbach@chromium.orgf9841892013-11-25 12:01:13 +0000220 CHECK(!env->GetIsolate()->InContext());
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000221 CHECK(env->GetIsolate() == CcTest::isolate());
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000222 env->Enter();
machenbach@chromium.orgf9841892013-11-25 12:01:13 +0000223 CHECK(env->GetIsolate()->InContext());
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000224 CHECK(env->GetIsolate() == CcTest::isolate());
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000225 env->Exit();
machenbach@chromium.orgf9841892013-11-25 12:01:13 +0000226 CHECK(!env->GetIsolate()->InContext());
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000227 CHECK(env->GetIsolate() == CcTest::isolate());
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000228}
229
230
dslomov@chromium.org639bac02013-09-09 11:58:54 +0000231static void TestSignature(const char* loop_js, Local<Value> receiver) {
232 i::ScopedVector<char> source(200);
233 i::OS::SNPrintF(source,
234 "for (var i = 0; i < 10; i++) {"
235 " %s"
236 "}",
237 loop_js);
238 signature_callback_count = 0;
239 signature_expected_receiver = receiver;
240 bool expected_to_throw = receiver.IsEmpty();
241 v8::TryCatch try_catch;
242 CompileRun(source.start());
243 CHECK_EQ(expected_to_throw, try_catch.HasCaught());
244 if (!expected_to_throw) {
245 CHECK_EQ(10, signature_callback_count);
246 } else {
247 CHECK_EQ(v8_str("TypeError: Illegal invocation"),
248 try_catch.Exception()->ToString());
249 }
250}
251
252
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000253THREADED_TEST(ReceiverSignature) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000254 LocalContext env;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +0000255 v8::Isolate* isolate = env->GetIsolate();
256 v8::HandleScope scope(isolate);
dslomov@chromium.org639bac02013-09-09 11:58:54 +0000257 // Setup templates.
hpayer@chromium.org4f99be92013-12-18 16:23:55 +0000258 v8::Handle<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(isolate);
259 v8::Handle<v8::Signature> sig = v8::Signature::New(isolate, fun);
dslomov@chromium.org639bac02013-09-09 11:58:54 +0000260 v8::Handle<v8::FunctionTemplate> callback_sig =
261 v8::FunctionTemplate::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +0000262 isolate, IncrementingSignatureCallback, Local<Value>(), sig);
dslomov@chromium.org639bac02013-09-09 11:58:54 +0000263 v8::Handle<v8::FunctionTemplate> callback =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +0000264 v8::FunctionTemplate::New(isolate, IncrementingSignatureCallback);
265 v8::Handle<v8::FunctionTemplate> sub_fun = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000266 sub_fun->Inherit(fun);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +0000267 v8::Handle<v8::FunctionTemplate> unrel_fun =
268 v8::FunctionTemplate::New(isolate);
dslomov@chromium.org639bac02013-09-09 11:58:54 +0000269 // Install properties.
270 v8::Handle<v8::ObjectTemplate> fun_proto = fun->PrototypeTemplate();
271 fun_proto->Set(v8_str("prop_sig"), callback_sig);
272 fun_proto->Set(v8_str("prop"), callback);
273 fun_proto->SetAccessorProperty(
274 v8_str("accessor_sig"), callback_sig, callback_sig);
275 fun_proto->SetAccessorProperty(v8_str("accessor"), callback, callback);
276 // Instantiate templates.
277 Local<Value> fun_instance = fun->InstanceTemplate()->NewInstance();
278 Local<Value> sub_fun_instance = sub_fun->InstanceTemplate()->NewInstance();
279 // Setup global variables.
280 env->Global()->Set(v8_str("Fun"), fun->GetFunction());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000281 env->Global()->Set(v8_str("UnrelFun"), unrel_fun->GetFunction());
dslomov@chromium.org639bac02013-09-09 11:58:54 +0000282 env->Global()->Set(v8_str("fun_instance"), fun_instance);
283 env->Global()->Set(v8_str("sub_fun_instance"), sub_fun_instance);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000284 CompileRun(
dslomov@chromium.org639bac02013-09-09 11:58:54 +0000285 "var accessor_sig_key = 'accessor_sig';"
286 "var accessor_key = 'accessor';"
287 "var prop_sig_key = 'prop_sig';"
288 "var prop_key = 'prop';"
289 ""
290 "function copy_props(obj) {"
291 " var keys = [accessor_sig_key, accessor_key, prop_sig_key, prop_key];"
292 " var source = Fun.prototype;"
293 " for (var i in keys) {"
294 " var key = keys[i];"
295 " var desc = Object.getOwnPropertyDescriptor(source, key);"
296 " Object.defineProperty(obj, key, desc);"
297 " }"
298 "}"
299 ""
300 "var obj = {};"
301 "copy_props(obj);"
302 "var unrel = new UnrelFun();"
303 "copy_props(unrel);");
304 // Test with and without ICs
305 const char* test_objects[] = {
306 "fun_instance", "sub_fun_instance", "obj", "unrel" };
307 unsigned bad_signature_start_offset = 2;
308 for (unsigned i = 0; i < ARRAY_SIZE(test_objects); i++) {
309 i::ScopedVector<char> source(200);
310 i::OS::SNPrintF(
311 source, "var test_object = %s; test_object", test_objects[i]);
312 Local<Value> test_object = CompileRun(source.start());
313 TestSignature("test_object.prop();", test_object);
314 TestSignature("test_object.accessor;", test_object);
315 TestSignature("test_object[accessor_key];", test_object);
316 TestSignature("test_object.accessor = 1;", test_object);
317 TestSignature("test_object[accessor_key] = 1;", test_object);
318 if (i >= bad_signature_start_offset) test_object = Local<Value>();
319 TestSignature("test_object.prop_sig();", test_object);
320 TestSignature("test_object.accessor_sig;", test_object);
321 TestSignature("test_object[accessor_sig_key];", test_object);
322 TestSignature("test_object.accessor_sig = 1;", test_object);
323 TestSignature("test_object[accessor_sig_key] = 1;", test_object);
324 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000325}
326
327
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000328THREADED_TEST(ArgumentSignature) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000329 LocalContext env;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +0000330 v8::Isolate* isolate = env->GetIsolate();
331 v8::HandleScope scope(isolate);
332 v8::Handle<v8::FunctionTemplate> cons = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000333 cons->SetClassName(v8_str("Cons"));
machenbach@chromium.org9f18d912013-11-28 13:42:41 +0000334 v8::Handle<v8::Signature> sig = v8::Signature::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +0000335 isolate, v8::Handle<v8::FunctionTemplate>(), 1, &cons);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000336 v8::Handle<v8::FunctionTemplate> fun =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +0000337 v8::FunctionTemplate::New(isolate,
338 SignatureCallback,
339 v8::Handle<Value>(),
340 sig);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000341 env->Global()->Set(v8_str("Cons"), cons->GetFunction());
342 env->Global()->Set(v8_str("Fun1"), fun->GetFunction());
343
344 v8::Handle<Value> value1 = CompileRun("Fun1(4) == '';");
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000345 CHECK(value1->IsTrue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000346
347 v8::Handle<Value> value2 = CompileRun("Fun1(new Cons()) == '[object Cons]';");
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000348 CHECK(value2->IsTrue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000349
350 v8::Handle<Value> value3 = CompileRun("Fun1() == '';");
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000351 CHECK(value3->IsTrue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000352
hpayer@chromium.org4f99be92013-12-18 16:23:55 +0000353 v8::Handle<v8::FunctionTemplate> cons1 = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000354 cons1->SetClassName(v8_str("Cons1"));
hpayer@chromium.org4f99be92013-12-18 16:23:55 +0000355 v8::Handle<v8::FunctionTemplate> cons2 = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000356 cons2->SetClassName(v8_str("Cons2"));
hpayer@chromium.org4f99be92013-12-18 16:23:55 +0000357 v8::Handle<v8::FunctionTemplate> cons3 = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000358 cons3->SetClassName(v8_str("Cons3"));
359
360 v8::Handle<v8::FunctionTemplate> args[3] = { cons1, cons2, cons3 };
machenbach@chromium.org9f18d912013-11-28 13:42:41 +0000361 v8::Handle<v8::Signature> wsig = v8::Signature::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +0000362 isolate, v8::Handle<v8::FunctionTemplate>(), 3, args);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000363 v8::Handle<v8::FunctionTemplate> fun2 =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +0000364 v8::FunctionTemplate::New(isolate,
365 SignatureCallback,
366 v8::Handle<Value>(),
367 wsig);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000368
369 env->Global()->Set(v8_str("Cons1"), cons1->GetFunction());
370 env->Global()->Set(v8_str("Cons2"), cons2->GetFunction());
371 env->Global()->Set(v8_str("Cons3"), cons3->GetFunction());
372 env->Global()->Set(v8_str("Fun2"), fun2->GetFunction());
373 v8::Handle<Value> value4 = CompileRun(
374 "Fun2(new Cons1(), new Cons2(), new Cons3()) =="
375 "'[object Cons1],[object Cons2],[object Cons3]'");
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000376 CHECK(value4->IsTrue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000377
378 v8::Handle<Value> value5 = CompileRun(
379 "Fun2(new Cons1(), new Cons2(), 5) == '[object Cons1],[object Cons2],'");
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000380 CHECK(value5->IsTrue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000381
382 v8::Handle<Value> value6 = CompileRun(
383 "Fun2(new Cons3(), new Cons2(), new Cons1()) == ',[object Cons2],'");
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000384 CHECK(value6->IsTrue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000385
386 v8::Handle<Value> value7 = CompileRun(
387 "Fun2(new Cons1(), new Cons2(), new Cons3(), 'd') == "
388 "'[object Cons1],[object Cons2],[object Cons3],d';");
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000389 CHECK(value7->IsTrue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000390
391 v8::Handle<Value> value8 = CompileRun(
392 "Fun2(new Cons1(), new Cons2()) == '[object Cons1],[object Cons2]'");
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000393 CHECK(value8->IsTrue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000394}
395
396
397THREADED_TEST(HulIgennem) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000398 LocalContext env;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +0000399 v8::Isolate* isolate = env->GetIsolate();
400 v8::HandleScope scope(isolate);
401 v8::Handle<v8::Primitive> undef = v8::Undefined(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000402 Local<String> undef_str = undef->ToString();
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000403 char* value = i::NewArray<char>(undef_str->Utf8Length() + 1);
404 undef_str->WriteUtf8(value);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000405 CHECK_EQ(0, strcmp(value, "undefined"));
406 i::DeleteArray(value);
407}
408
409
410THREADED_TEST(Access) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000411 LocalContext env;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +0000412 v8::Isolate* isolate = env->GetIsolate();
413 v8::HandleScope scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +0000414 Local<v8::Object> obj = v8::Object::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000415 Local<Value> foo_before = obj->Get(v8_str("foo"));
416 CHECK(foo_before->IsUndefined());
417 Local<String> bar_str = v8_str("bar");
418 obj->Set(v8_str("foo"), bar_str);
419 Local<Value> foo_after = obj->Get(v8_str("foo"));
420 CHECK(!foo_after->IsUndefined());
421 CHECK(foo_after->IsString());
422 CHECK_EQ(bar_str, foo_after);
423}
424
425
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000426THREADED_TEST(AccessElement) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000427 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000428 v8::HandleScope scope(env->GetIsolate());
ulan@chromium.org0f13e742014-01-03 15:51:11 +0000429 Local<v8::Object> obj = v8::Object::New(env->GetIsolate());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000430 Local<Value> before = obj->Get(1);
431 CHECK(before->IsUndefined());
432 Local<String> bar_str = v8_str("bar");
433 obj->Set(1, bar_str);
434 Local<Value> after = obj->Get(1);
435 CHECK(!after->IsUndefined());
436 CHECK(after->IsString());
437 CHECK_EQ(bar_str, after);
438
439 Local<v8::Array> value = CompileRun("[\"a\", \"b\"]").As<v8::Array>();
440 CHECK_EQ(v8_str("a"), value->Get(0));
441 CHECK_EQ(v8_str("b"), value->Get(1));
442}
443
444
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000445THREADED_TEST(Script) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000446 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000447 v8::HandleScope scope(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000448 const char* c_source = "1 + 2 + 3";
machenbach@chromium.orgf9841892013-11-25 12:01:13 +0000449 Local<String> source = String::NewFromUtf8(env->GetIsolate(), c_source);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000450 Local<Script> script = Script::Compile(source);
451 CHECK_EQ(6, script->Run()->Int32Value());
452}
453
454
455static uint16_t* AsciiToTwoByteString(const char* source) {
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000456 int array_length = i::StrLength(source) + 1;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000457 uint16_t* converted = i::NewArray<uint16_t>(array_length);
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000458 for (int i = 0; i < array_length; i++) converted[i] = source[i];
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000459 return converted;
460}
461
462
463class TestResource: public String::ExternalStringResource {
464 public:
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000465 explicit TestResource(uint16_t* data, int* counter = NULL)
466 : data_(data), length_(0), counter_(counter) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000467 while (data[length_]) ++length_;
468 }
469
470 ~TestResource() {
471 i::DeleteArray(data_);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000472 if (counter_ != NULL) ++*counter_;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000473 }
474
475 const uint16_t* data() const {
476 return data_;
477 }
478
479 size_t length() const {
480 return length_;
481 }
482 private:
483 uint16_t* data_;
484 size_t length_;
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000485 int* counter_;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000486};
487
488
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000489class TestAsciiResource: public String::ExternalAsciiStringResource {
490 public:
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000491 explicit TestAsciiResource(const char* data, int* counter = NULL)
492 : data_(data), length_(strlen(data)), counter_(counter) { }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000493
494 ~TestAsciiResource() {
495 i::DeleteArray(data_);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000496 if (counter_ != NULL) ++*counter_;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000497 }
498
499 const char* data() const {
500 return data_;
501 }
502
503 size_t length() const {
504 return length_;
505 }
506 private:
ager@chromium.org5ec48922009-05-05 07:25:34 +0000507 const char* data_;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000508 size_t length_;
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000509 int* counter_;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000510};
511
512
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000513THREADED_TEST(ScriptUsingStringResource) {
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000514 int dispose_count = 0;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000515 const char* c_source = "1 + 2 * 3";
516 uint16_t* two_byte_source = AsciiToTwoByteString(c_source);
517 {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000518 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000519 v8::HandleScope scope(env->GetIsolate());
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000520 TestResource* resource = new TestResource(two_byte_source, &dispose_count);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +0000521 Local<String> source = String::NewExternal(env->GetIsolate(), resource);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000522 Local<Script> script = Script::Compile(source);
523 Local<Value> value = script->Run();
524 CHECK(value->IsNumber());
525 CHECK_EQ(7, value->Int32Value());
526 CHECK(source->IsExternal());
527 CHECK_EQ(resource,
528 static_cast<TestResource*>(source->GetExternalStringResource()));
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000529 String::Encoding encoding = String::UNKNOWN_ENCODING;
530 CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
531 source->GetExternalStringResourceBase(&encoding));
532 CHECK_EQ(String::TWO_BYTE_ENCODING, encoding);
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000533 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000534 CHECK_EQ(0, dispose_count);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000535 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000536 CcTest::i_isolate()->compilation_cache()->Clear();
537 CcTest::heap()->CollectAllAvailableGarbage();
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000538 CHECK_EQ(1, dispose_count);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000539}
540
541
542THREADED_TEST(ScriptUsingAsciiStringResource) {
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000543 int dispose_count = 0;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000544 const char* c_source = "1 + 2 * 3";
545 {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000546 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000547 v8::HandleScope scope(env->GetIsolate());
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000548 TestAsciiResource* resource = new TestAsciiResource(i::StrDup(c_source),
549 &dispose_count);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +0000550 Local<String> source = String::NewExternal(env->GetIsolate(), resource);
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000551 CHECK(source->IsExternalAscii());
552 CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
553 source->GetExternalAsciiStringResource());
554 String::Encoding encoding = String::UNKNOWN_ENCODING;
555 CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
556 source->GetExternalStringResourceBase(&encoding));
557 CHECK_EQ(String::ASCII_ENCODING, encoding);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000558 Local<Script> script = Script::Compile(source);
559 Local<Value> value = script->Run();
560 CHECK(value->IsNumber());
561 CHECK_EQ(7, value->Int32Value());
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000562 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000563 CHECK_EQ(0, dispose_count);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000564 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000565 CcTest::i_isolate()->compilation_cache()->Clear();
566 CcTest::heap()->CollectAllAvailableGarbage();
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000567 CHECK_EQ(1, dispose_count);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000568}
569
570
ager@chromium.org6f10e412009-02-13 10:11:16 +0000571THREADED_TEST(ScriptMakingExternalString) {
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000572 int dispose_count = 0;
ager@chromium.org6f10e412009-02-13 10:11:16 +0000573 uint16_t* two_byte_source = AsciiToTwoByteString("1 + 2 * 3");
574 {
ager@chromium.org6f10e412009-02-13 10:11:16 +0000575 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000576 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.orgf9841892013-11-25 12:01:13 +0000577 Local<String> source =
578 String::NewFromTwoByte(env->GetIsolate(), two_byte_source);
ager@chromium.org5c838252010-02-19 08:53:10 +0000579 // Trigger GCs so that the newly allocated string moves to old gen.
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000580 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
581 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000582 CHECK_EQ(source->IsExternal(), false);
583 CHECK_EQ(source->IsExternalAscii(), false);
584 String::Encoding encoding = String::UNKNOWN_ENCODING;
585 CHECK_EQ(NULL, source->GetExternalStringResourceBase(&encoding));
586 CHECK_EQ(String::ASCII_ENCODING, encoding);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000587 bool success = source->MakeExternal(new TestResource(two_byte_source,
588 &dispose_count));
ager@chromium.org6f10e412009-02-13 10:11:16 +0000589 CHECK(success);
590 Local<Script> script = Script::Compile(source);
591 Local<Value> value = script->Run();
592 CHECK(value->IsNumber());
593 CHECK_EQ(7, value->Int32Value());
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000594 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000595 CHECK_EQ(0, dispose_count);
ager@chromium.org6f10e412009-02-13 10:11:16 +0000596 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000597 CcTest::i_isolate()->compilation_cache()->Clear();
598 CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000599 CHECK_EQ(1, dispose_count);
ager@chromium.org6f10e412009-02-13 10:11:16 +0000600}
601
602
603THREADED_TEST(ScriptMakingExternalAsciiString) {
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000604 int dispose_count = 0;
ager@chromium.org6f10e412009-02-13 10:11:16 +0000605 const char* c_source = "1 + 2 * 3";
606 {
ager@chromium.org6f10e412009-02-13 10:11:16 +0000607 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000608 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org6f10e412009-02-13 10:11:16 +0000609 Local<String> source = v8_str(c_source);
ager@chromium.org5c838252010-02-19 08:53:10 +0000610 // Trigger GCs so that the newly allocated string moves to old gen.
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000611 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
612 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
ager@chromium.org6f10e412009-02-13 10:11:16 +0000613 bool success = source->MakeExternal(
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000614 new TestAsciiResource(i::StrDup(c_source), &dispose_count));
ager@chromium.org6f10e412009-02-13 10:11:16 +0000615 CHECK(success);
616 Local<Script> script = Script::Compile(source);
617 Local<Value> value = script->Run();
618 CHECK(value->IsNumber());
619 CHECK_EQ(7, value->Int32Value());
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000620 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000621 CHECK_EQ(0, dispose_count);
ager@chromium.org6f10e412009-02-13 10:11:16 +0000622 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000623 CcTest::i_isolate()->compilation_cache()->Clear();
624 CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000625 CHECK_EQ(1, dispose_count);
ager@chromium.org6f10e412009-02-13 10:11:16 +0000626}
627
628
ager@chromium.org5c838252010-02-19 08:53:10 +0000629TEST(MakingExternalStringConditions) {
ager@chromium.org5c838252010-02-19 08:53:10 +0000630 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000631 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org5c838252010-02-19 08:53:10 +0000632
633 // Free some space in the new space so that we can check freshness.
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000634 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
635 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
ager@chromium.org5c838252010-02-19 08:53:10 +0000636
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000637 uint16_t* two_byte_string = AsciiToTwoByteString("s1");
machenbach@chromium.orgf9841892013-11-25 12:01:13 +0000638 Local<String> small_string =
639 String::NewFromTwoByte(env->GetIsolate(), two_byte_string);
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000640 i::DeleteArray(two_byte_string);
641
ager@chromium.org5c838252010-02-19 08:53:10 +0000642 // We should refuse to externalize newly created small string.
643 CHECK(!small_string->CanMakeExternal());
644 // Trigger GCs so that the newly allocated string moves to old gen.
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000645 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
646 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
ager@chromium.org5c838252010-02-19 08:53:10 +0000647 // Old space strings should be accepted.
648 CHECK(small_string->CanMakeExternal());
649
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000650 two_byte_string = AsciiToTwoByteString("small string 2");
machenbach@chromium.orgf9841892013-11-25 12:01:13 +0000651 small_string = String::NewFromTwoByte(env->GetIsolate(), two_byte_string);
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000652 i::DeleteArray(two_byte_string);
653
ager@chromium.org5c838252010-02-19 08:53:10 +0000654 // We should refuse externalizing newly created small string.
655 CHECK(!small_string->CanMakeExternal());
656 for (int i = 0; i < 100; i++) {
657 String::Value value(small_string);
658 }
659 // Frequently used strings should be accepted.
660 CHECK(small_string->CanMakeExternal());
661
662 const int buf_size = 10 * 1024;
663 char* buf = i::NewArray<char>(buf_size);
664 memset(buf, 'a', buf_size);
665 buf[buf_size - 1] = '\0';
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000666
667 two_byte_string = AsciiToTwoByteString(buf);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +0000668 Local<String> large_string =
669 String::NewFromTwoByte(env->GetIsolate(), two_byte_string);
ager@chromium.org5c838252010-02-19 08:53:10 +0000670 i::DeleteArray(buf);
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000671 i::DeleteArray(two_byte_string);
ager@chromium.org5c838252010-02-19 08:53:10 +0000672 // Large strings should be immediately accepted.
673 CHECK(large_string->CanMakeExternal());
674}
675
676
677TEST(MakingExternalAsciiStringConditions) {
ager@chromium.org5c838252010-02-19 08:53:10 +0000678 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000679 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org5c838252010-02-19 08:53:10 +0000680
681 // Free some space in the new space so that we can check freshness.
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000682 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
683 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
ager@chromium.org5c838252010-02-19 08:53:10 +0000684
machenbach@chromium.orgf9841892013-11-25 12:01:13 +0000685 Local<String> small_string = String::NewFromUtf8(env->GetIsolate(), "s1");
ager@chromium.org5c838252010-02-19 08:53:10 +0000686 // We should refuse to externalize newly created small string.
687 CHECK(!small_string->CanMakeExternal());
688 // Trigger GCs so that the newly allocated string moves to old gen.
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000689 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
690 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
ager@chromium.org5c838252010-02-19 08:53:10 +0000691 // Old space strings should be accepted.
692 CHECK(small_string->CanMakeExternal());
693
machenbach@chromium.orgf9841892013-11-25 12:01:13 +0000694 small_string = String::NewFromUtf8(env->GetIsolate(), "small string 2");
ager@chromium.org5c838252010-02-19 08:53:10 +0000695 // We should refuse externalizing newly created small string.
696 CHECK(!small_string->CanMakeExternal());
697 for (int i = 0; i < 100; i++) {
698 String::Value value(small_string);
699 }
700 // Frequently used strings should be accepted.
701 CHECK(small_string->CanMakeExternal());
702
703 const int buf_size = 10 * 1024;
704 char* buf = i::NewArray<char>(buf_size);
705 memset(buf, 'a', buf_size);
706 buf[buf_size - 1] = '\0';
machenbach@chromium.orgf9841892013-11-25 12:01:13 +0000707 Local<String> large_string = String::NewFromUtf8(env->GetIsolate(), buf);
ager@chromium.org5c838252010-02-19 08:53:10 +0000708 i::DeleteArray(buf);
709 // Large strings should be immediately accepted.
710 CHECK(large_string->CanMakeExternal());
711}
712
713
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000714TEST(MakingExternalUnalignedAsciiString) {
715 LocalContext env;
716 v8::HandleScope scope(env->GetIsolate());
717
718 CompileRun("function cons(a, b) { return a + b; }"
719 "function slice(a) { return a.substring(1); }");
720 // Create a cons string that will land in old pointer space.
721 Local<String> cons = Local<String>::Cast(CompileRun(
722 "cons('abcdefghijklm', 'nopqrstuvwxyz');"));
723 // Create a sliced string that will land in old pointer space.
724 Local<String> slice = Local<String>::Cast(CompileRun(
725 "slice('abcdefghijklmnopqrstuvwxyz');"));
726
727 // Trigger GCs so that the newly allocated string moves to old gen.
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000728 SimulateFullSpace(CcTest::heap()->old_pointer_space());
729 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
730 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000731
732 // Turn into external string with unaligned resource data.
733 int dispose_count = 0;
734 const char* c_cons = "_abcdefghijklmnopqrstuvwxyz";
735 bool success = cons->MakeExternal(
736 new TestAsciiResource(i::StrDup(c_cons) + 1, &dispose_count));
737 CHECK(success);
738 const char* c_slice = "_bcdefghijklmnopqrstuvwxyz";
739 success = slice->MakeExternal(
740 new TestAsciiResource(i::StrDup(c_slice) + 1, &dispose_count));
741 CHECK(success);
742
743 // Trigger GCs and force evacuation.
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000744 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
745 CcTest::heap()->CollectAllGarbage(i::Heap::kReduceMemoryFootprintMask);
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000746}
747
748
ager@chromium.org6f10e412009-02-13 10:11:16 +0000749THREADED_TEST(UsingExternalString) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000750 i::Factory* factory = CcTest::i_isolate()->factory();
ager@chromium.orge2902be2009-06-08 12:21:35 +0000751 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000752 v8::HandleScope scope(CcTest::isolate());
ager@chromium.orge2902be2009-06-08 12:21:35 +0000753 uint16_t* two_byte_string = AsciiToTwoByteString("test string");
machenbach@chromium.org9f18d912013-11-28 13:42:41 +0000754 Local<String> string = String::NewExternal(
755 CcTest::isolate(), new TestResource(two_byte_string));
ager@chromium.orge2902be2009-06-08 12:21:35 +0000756 i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
757 // Trigger GCs so that the newly allocated string moves to old gen.
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000758 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
759 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000760 i::Handle<i::String> isymbol =
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000761 factory->InternalizedStringFromString(istring);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000762 CHECK(isymbol->IsInternalizedString());
ager@chromium.orge2902be2009-06-08 12:21:35 +0000763 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000764 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
765 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org6f10e412009-02-13 10:11:16 +0000766}
767
768
769THREADED_TEST(UsingExternalAsciiString) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000770 i::Factory* factory = CcTest::i_isolate()->factory();
ager@chromium.orge2902be2009-06-08 12:21:35 +0000771 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000772 v8::HandleScope scope(CcTest::isolate());
ager@chromium.orge2902be2009-06-08 12:21:35 +0000773 const char* one_byte_string = "test string";
774 Local<String> string = String::NewExternal(
machenbach@chromium.org9f18d912013-11-28 13:42:41 +0000775 CcTest::isolate(), new TestAsciiResource(i::StrDup(one_byte_string)));
ager@chromium.orge2902be2009-06-08 12:21:35 +0000776 i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
777 // Trigger GCs so that the newly allocated string moves to old gen.
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000778 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
779 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000780 i::Handle<i::String> isymbol =
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000781 factory->InternalizedStringFromString(istring);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000782 CHECK(isymbol->IsInternalizedString());
ager@chromium.orge2902be2009-06-08 12:21:35 +0000783 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000784 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
785 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org6f10e412009-02-13 10:11:16 +0000786}
787
788
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000789THREADED_TEST(ScavengeExternalString) {
svenpanne@chromium.org83130cf2012-11-30 10:13:25 +0000790 i::FLAG_stress_compaction = false;
791 i::FLAG_gc_global = false;
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000792 int dispose_count = 0;
lrn@chromium.orgc34f5802010-04-28 12:53:43 +0000793 bool in_new_space = false;
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000794 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000795 v8::HandleScope scope(CcTest::isolate());
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000796 uint16_t* two_byte_string = AsciiToTwoByteString("test string");
machenbach@chromium.org9f18d912013-11-28 13:42:41 +0000797 Local<String> string = String::NewExternal(
798 CcTest::isolate(), new TestResource(two_byte_string, &dispose_count));
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000799 i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000800 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
801 in_new_space = CcTest::heap()->InNewSpace(*istring);
802 CHECK(in_new_space || CcTest::heap()->old_data_space()->Contains(*istring));
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000803 CHECK_EQ(0, dispose_count);
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000804 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000805 CcTest::heap()->CollectGarbage(
806 in_new_space ? i::NEW_SPACE : i::OLD_DATA_SPACE);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000807 CHECK_EQ(1, dispose_count);
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000808}
809
810
811THREADED_TEST(ScavengeExternalAsciiString) {
svenpanne@chromium.org83130cf2012-11-30 10:13:25 +0000812 i::FLAG_stress_compaction = false;
813 i::FLAG_gc_global = false;
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000814 int dispose_count = 0;
lrn@chromium.orgc34f5802010-04-28 12:53:43 +0000815 bool in_new_space = false;
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000816 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000817 v8::HandleScope scope(CcTest::isolate());
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000818 const char* one_byte_string = "test string";
819 Local<String> string = String::NewExternal(
machenbach@chromium.org9f18d912013-11-28 13:42:41 +0000820 CcTest::isolate(),
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000821 new TestAsciiResource(i::StrDup(one_byte_string), &dispose_count));
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000822 i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000823 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
824 in_new_space = CcTest::heap()->InNewSpace(*istring);
825 CHECK(in_new_space || CcTest::heap()->old_data_space()->Contains(*istring));
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000826 CHECK_EQ(0, dispose_count);
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000827 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000828 CcTest::heap()->CollectGarbage(
829 in_new_space ? i::NEW_SPACE : i::OLD_DATA_SPACE);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000830 CHECK_EQ(1, dispose_count);
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000831}
832
833
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000834class TestAsciiResourceWithDisposeControl: public TestAsciiResource {
835 public:
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000836 // Only used by non-threaded tests, so it can use static fields.
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000837 static int dispose_calls;
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000838 static int dispose_count;
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000839
840 TestAsciiResourceWithDisposeControl(const char* data, bool dispose)
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000841 : TestAsciiResource(data, &dispose_count),
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000842 dispose_(dispose) { }
843
844 void Dispose() {
845 ++dispose_calls;
846 if (dispose_) delete this;
847 }
848 private:
849 bool dispose_;
850};
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000851
852
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000853int TestAsciiResourceWithDisposeControl::dispose_count = 0;
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000854int TestAsciiResourceWithDisposeControl::dispose_calls = 0;
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000855
856
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000857TEST(ExternalStringWithDisposeHandling) {
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000858 const char* c_source = "1 + 2 * 3";
859
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000860 // Use a stack allocated external string resource allocated object.
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000861 TestAsciiResourceWithDisposeControl::dispose_count = 0;
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000862 TestAsciiResourceWithDisposeControl::dispose_calls = 0;
863 TestAsciiResourceWithDisposeControl res_stack(i::StrDup(c_source), false);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000864 {
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000865 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000866 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org9f18d912013-11-28 13:42:41 +0000867 Local<String> source = String::NewExternal(env->GetIsolate(), &res_stack);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000868 Local<Script> script = Script::Compile(source);
869 Local<Value> value = script->Run();
870 CHECK(value->IsNumber());
871 CHECK_EQ(7, value->Int32Value());
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000872 CcTest::heap()->CollectAllAvailableGarbage();
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000873 CHECK_EQ(0, TestAsciiResourceWithDisposeControl::dispose_count);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000874 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000875 CcTest::i_isolate()->compilation_cache()->Clear();
876 CcTest::heap()->CollectAllAvailableGarbage();
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000877 CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_calls);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000878 CHECK_EQ(0, TestAsciiResourceWithDisposeControl::dispose_count);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000879
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000880 // Use a heap allocated external string resource allocated object.
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000881 TestAsciiResourceWithDisposeControl::dispose_count = 0;
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000882 TestAsciiResourceWithDisposeControl::dispose_calls = 0;
883 TestAsciiResource* res_heap =
884 new TestAsciiResourceWithDisposeControl(i::StrDup(c_source), true);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000885 {
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000886 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000887 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org9f18d912013-11-28 13:42:41 +0000888 Local<String> source = String::NewExternal(env->GetIsolate(), res_heap);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000889 Local<Script> script = Script::Compile(source);
890 Local<Value> value = script->Run();
891 CHECK(value->IsNumber());
892 CHECK_EQ(7, value->Int32Value());
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000893 CcTest::heap()->CollectAllAvailableGarbage();
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000894 CHECK_EQ(0, TestAsciiResourceWithDisposeControl::dispose_count);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000895 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000896 CcTest::i_isolate()->compilation_cache()->Clear();
897 CcTest::heap()->CollectAllAvailableGarbage();
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000898 CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_calls);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000899 CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_count);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000900}
901
902
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000903THREADED_TEST(StringConcat) {
904 {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000905 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000906 v8::HandleScope scope(env->GetIsolate());
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000907 const char* one_byte_string_1 = "function a_times_t";
908 const char* two_byte_string_1 = "wo_plus_b(a, b) {return ";
909 const char* one_byte_extern_1 = "a * 2 + b;} a_times_two_plus_b(4, 8) + ";
910 const char* two_byte_extern_1 = "a_times_two_plus_b(4, 8) + ";
911 const char* one_byte_string_2 = "a_times_two_plus_b(4, 8) + ";
912 const char* two_byte_string_2 = "a_times_two_plus_b(4, 8) + ";
913 const char* two_byte_extern_2 = "a_times_two_plus_b(1, 2);";
914 Local<String> left = v8_str(one_byte_string_1);
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000915
916 uint16_t* two_byte_source = AsciiToTwoByteString(two_byte_string_1);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +0000917 Local<String> right =
918 String::NewFromTwoByte(env->GetIsolate(), two_byte_source);
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000919 i::DeleteArray(two_byte_source);
920
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000921 Local<String> source = String::Concat(left, right);
922 right = String::NewExternal(
machenbach@chromium.org9f18d912013-11-28 13:42:41 +0000923 env->GetIsolate(), new TestAsciiResource(i::StrDup(one_byte_extern_1)));
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000924 source = String::Concat(source, right);
925 right = String::NewExternal(
machenbach@chromium.org9f18d912013-11-28 13:42:41 +0000926 env->GetIsolate(),
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000927 new TestResource(AsciiToTwoByteString(two_byte_extern_1)));
928 source = String::Concat(source, right);
929 right = v8_str(one_byte_string_2);
930 source = String::Concat(source, right);
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000931
932 two_byte_source = AsciiToTwoByteString(two_byte_string_2);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +0000933 right = String::NewFromTwoByte(env->GetIsolate(), two_byte_source);
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000934 i::DeleteArray(two_byte_source);
935
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000936 source = String::Concat(source, right);
937 right = String::NewExternal(
machenbach@chromium.org9f18d912013-11-28 13:42:41 +0000938 env->GetIsolate(),
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000939 new TestResource(AsciiToTwoByteString(two_byte_extern_2)));
940 source = String::Concat(source, right);
941 Local<Script> script = Script::Compile(source);
942 Local<Value> value = script->Run();
943 CHECK(value->IsNumber());
944 CHECK_EQ(68, value->Int32Value());
945 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000946 CcTest::i_isolate()->compilation_cache()->Clear();
947 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
948 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000949}
950
951
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000952THREADED_TEST(GlobalProperties) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000953 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000954 v8::HandleScope scope(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000955 v8::Handle<v8::Object> global = env->Global();
956 global->Set(v8_str("pi"), v8_num(3.1415926));
957 Local<Value> pi = global->Get(v8_str("pi"));
958 CHECK_EQ(3.1415926, pi->NumberValue());
959}
960
961
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +0000962template<typename T>
dslomov@chromium.orgb752d402013-06-18 11:54:54 +0000963static void CheckReturnValue(const T& t, i::Address callback) {
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +0000964 v8::ReturnValue<v8::Value> rv = t.GetReturnValue();
965 i::Object** o = *reinterpret_cast<i::Object***>(&rv);
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000966 CHECK_EQ(CcTest::isolate(), t.GetIsolate());
svenpanne@chromium.org53ad1752013-05-27 12:20:38 +0000967 CHECK_EQ(t.GetIsolate(), rv.GetIsolate());
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +0000968 CHECK((*o)->IsTheHole() || (*o)->IsUndefined());
verwaest@chromium.org8a00e822013-06-10 15:11:22 +0000969 // Verify reset
970 bool is_runtime = (*o)->IsTheHole();
971 rv.Set(true);
972 CHECK(!(*o)->IsTheHole() && !(*o)->IsUndefined());
973 rv.Set(v8::Handle<v8::Object>());
974 CHECK((*o)->IsTheHole() || (*o)->IsUndefined());
975 CHECK_EQ(is_runtime, (*o)->IsTheHole());
dslomov@chromium.orgb752d402013-06-18 11:54:54 +0000976
977 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(t.GetIsolate());
978 // If CPU profiler is active check that when API callback is invoked
979 // VMState is set to EXTERNAL.
980 if (isolate->cpu_profiler()->is_profiling()) {
981 CHECK_EQ(i::EXTERNAL, isolate->current_vm_state());
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +0000982 CHECK(isolate->external_callback_scope());
983 CHECK_EQ(callback, isolate->external_callback_scope()->callback());
dslomov@chromium.orgb752d402013-06-18 11:54:54 +0000984 }
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +0000985}
986
dslomov@chromium.orgb752d402013-06-18 11:54:54 +0000987
988static void handle_callback_impl(const v8::FunctionCallbackInfo<Value>& info,
989 i::Address callback) {
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +0000990 ApiTestFuzzer::Fuzz();
dslomov@chromium.orgb752d402013-06-18 11:54:54 +0000991 CheckReturnValue(info, callback);
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +0000992 info.GetReturnValue().Set(v8_str("bad value"));
993 info.GetReturnValue().Set(v8_num(102));
994}
995
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000996
dslomov@chromium.orgb752d402013-06-18 11:54:54 +0000997static void handle_callback(const v8::FunctionCallbackInfo<Value>& info) {
998 return handle_callback_impl(info, FUNCTION_ADDR(handle_callback));
999}
1000
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001001
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00001002static void handle_callback_2(const v8::FunctionCallbackInfo<Value>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001003 return handle_callback_impl(info, FUNCTION_ADDR(handle_callback_2));
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00001004}
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001005
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001006static void construct_callback(
1007 const v8::FunctionCallbackInfo<Value>& info) {
1008 ApiTestFuzzer::Fuzz();
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001009 CheckReturnValue(info, FUNCTION_ADDR(construct_callback));
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001010 info.This()->Set(v8_str("x"), v8_num(1));
1011 info.This()->Set(v8_str("y"), v8_num(2));
1012 info.GetReturnValue().Set(v8_str("bad value"));
1013 info.GetReturnValue().Set(info.This());
ager@chromium.orgb61a0d12010-10-13 08:35:23 +00001014}
1015
1016
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001017static void Return239Callback(
1018 Local<String> name, const v8::PropertyCallbackInfo<Value>& info) {
1019 ApiTestFuzzer::Fuzz();
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001020 CheckReturnValue(info, FUNCTION_ADDR(Return239Callback));
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001021 info.GetReturnValue().Set(v8_str("bad value"));
1022 info.GetReturnValue().Set(v8_num(239));
1023}
1024
1025
1026template<typename Handler>
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00001027static void TestFunctionTemplateInitializer(Handler handler,
1028 Handler handler_2) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001029 // Test constructor calls.
1030 {
1031 LocalContext env;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001032 v8::Isolate* isolate = env->GetIsolate();
1033 v8::HandleScope scope(isolate);
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001034
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001035 Local<v8::FunctionTemplate> fun_templ =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001036 v8::FunctionTemplate::New(isolate, handler);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001037 Local<Function> fun = fun_templ->GetFunction();
1038 env->Global()->Set(v8_str("obj"), fun);
1039 Local<Script> script = v8_compile("obj()");
1040 for (int i = 0; i < 30; i++) {
1041 CHECK_EQ(102, script->Run()->Int32Value());
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001042 }
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001043 }
1044 // Use SetCallHandler to initialize a function template, should work like
1045 // the previous one.
1046 {
1047 LocalContext env;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001048 v8::Isolate* isolate = env->GetIsolate();
1049 v8::HandleScope scope(isolate);
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001050
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001051 Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(isolate);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001052 fun_templ->SetCallHandler(handler_2);
1053 Local<Function> fun = fun_templ->GetFunction();
1054 env->Global()->Set(v8_str("obj"), fun);
1055 Local<Script> script = v8_compile("obj()");
1056 for (int i = 0; i < 30; i++) {
1057 CHECK_EQ(102, script->Run()->Int32Value());
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001058 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001059 }
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001060}
1061
1062
1063template<typename Constructor, typename Accessor>
1064static void TestFunctionTemplateAccessor(Constructor constructor,
1065 Accessor accessor) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001066 LocalContext env;
1067 v8::HandleScope scope(env->GetIsolate());
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001068
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001069 Local<v8::FunctionTemplate> fun_templ =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001070 v8::FunctionTemplate::New(env->GetIsolate(), constructor);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001071 fun_templ->SetClassName(v8_str("funky"));
1072 fun_templ->InstanceTemplate()->SetAccessor(v8_str("m"), accessor);
1073 Local<Function> fun = fun_templ->GetFunction();
1074 env->Global()->Set(v8_str("obj"), fun);
1075 Local<Value> result = v8_compile("(new obj()).toString()")->Run();
1076 CHECK_EQ(v8_str("[object funky]"), result);
1077 CompileRun("var obj_instance = new obj();");
1078 Local<Script> script;
1079 script = v8_compile("obj_instance.x");
1080 for (int i = 0; i < 30; i++) {
1081 CHECK_EQ(1, script->Run()->Int32Value());
1082 }
1083 script = v8_compile("obj_instance.m");
1084 for (int i = 0; i < 30; i++) {
1085 CHECK_EQ(239, script->Run()->Int32Value());
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001086 }
1087}
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001088
ager@chromium.orgb61a0d12010-10-13 08:35:23 +00001089
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001090THREADED_PROFILED_TEST(FunctionTemplate) {
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00001091 TestFunctionTemplateInitializer(handle_callback, handle_callback_2);
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001092 TestFunctionTemplateAccessor(construct_callback, Return239Callback);
1093}
1094
1095
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001096static void SimpleCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
1097 ApiTestFuzzer::Fuzz();
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001098 CheckReturnValue(info, FUNCTION_ADDR(SimpleCallback));
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001099 info.GetReturnValue().Set(v8_num(51423 + info.Length()));
1100}
1101
1102
1103template<typename Callback>
1104static void TestSimpleCallback(Callback callback) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001105 LocalContext env;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00001106 v8::Isolate* isolate = env->GetIsolate();
1107 v8::HandleScope scope(isolate);
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001108
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00001109 v8::Handle<v8::ObjectTemplate> object_template =
1110 v8::ObjectTemplate::New(isolate);
1111 object_template->Set(isolate, "callback",
1112 v8::FunctionTemplate::New(isolate, callback));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001113 v8::Local<v8::Object> object = object_template->NewInstance();
1114 (*env)->Global()->Set(v8_str("callback_object"), object);
1115 v8::Handle<v8::Script> script;
1116 script = v8_compile("callback_object.callback(17)");
1117 for (int i = 0; i < 30; i++) {
1118 CHECK_EQ(51424, script->Run()->Int32Value());
1119 }
1120 script = v8_compile("callback_object.callback(17, 24)");
1121 for (int i = 0; i < 30; i++) {
1122 CHECK_EQ(51425, script->Run()->Int32Value());
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001123 }
1124}
1125
1126
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001127THREADED_PROFILED_TEST(SimpleCallback) {
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001128 TestSimpleCallback(SimpleCallback);
1129}
1130
1131
1132template<typename T>
1133void FastReturnValueCallback(const v8::FunctionCallbackInfo<v8::Value>& info);
1134
1135// constant return values
danno@chromium.org1fd77d52013-06-07 16:01:45 +00001136static int32_t fast_return_value_int32 = 471;
1137static uint32_t fast_return_value_uint32 = 571;
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001138static const double kFastReturnValueDouble = 2.7;
1139// variable return values
1140static bool fast_return_value_bool = false;
ulan@chromium.org837a67e2013-06-11 15:39:48 +00001141enum ReturnValueOddball {
1142 kNullReturnValue,
1143 kUndefinedReturnValue,
1144 kEmptyStringReturnValue
1145};
1146static ReturnValueOddball fast_return_value_void;
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00001147static bool fast_return_value_object_is_empty = false;
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001148
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001149// Helper function to avoid compiler error: insufficient contextual information
1150// to determine type when applying FUNCTION_ADDR to a template function.
1151static i::Address address_of(v8::FunctionCallback callback) {
1152 return FUNCTION_ADDR(callback);
1153}
1154
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001155template<>
1156void FastReturnValueCallback<int32_t>(
1157 const v8::FunctionCallbackInfo<v8::Value>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001158 CheckReturnValue(info, address_of(FastReturnValueCallback<int32_t>));
danno@chromium.org1fd77d52013-06-07 16:01:45 +00001159 info.GetReturnValue().Set(fast_return_value_int32);
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001160}
1161
1162template<>
1163void FastReturnValueCallback<uint32_t>(
1164 const v8::FunctionCallbackInfo<v8::Value>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001165 CheckReturnValue(info, address_of(FastReturnValueCallback<uint32_t>));
danno@chromium.org1fd77d52013-06-07 16:01:45 +00001166 info.GetReturnValue().Set(fast_return_value_uint32);
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001167}
1168
1169template<>
1170void FastReturnValueCallback<double>(
1171 const v8::FunctionCallbackInfo<v8::Value>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001172 CheckReturnValue(info, address_of(FastReturnValueCallback<double>));
svenpanne@chromium.org53ad1752013-05-27 12:20:38 +00001173 info.GetReturnValue().Set(kFastReturnValueDouble);
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001174}
1175
1176template<>
1177void FastReturnValueCallback<bool>(
1178 const v8::FunctionCallbackInfo<v8::Value>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001179 CheckReturnValue(info, address_of(FastReturnValueCallback<bool>));
svenpanne@chromium.org53ad1752013-05-27 12:20:38 +00001180 info.GetReturnValue().Set(fast_return_value_bool);
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001181}
1182
1183template<>
1184void FastReturnValueCallback<void>(
1185 const v8::FunctionCallbackInfo<v8::Value>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001186 CheckReturnValue(info, address_of(FastReturnValueCallback<void>));
ulan@chromium.org837a67e2013-06-11 15:39:48 +00001187 switch (fast_return_value_void) {
1188 case kNullReturnValue:
1189 info.GetReturnValue().SetNull();
1190 break;
1191 case kUndefinedReturnValue:
1192 info.GetReturnValue().SetUndefined();
1193 break;
1194 case kEmptyStringReturnValue:
1195 info.GetReturnValue().SetEmptyString();
1196 break;
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001197 }
1198}
1199
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +00001200template<>
1201void FastReturnValueCallback<Object>(
1202 const v8::FunctionCallbackInfo<v8::Value>& info) {
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00001203 v8::Handle<v8::Object> object;
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001204 if (!fast_return_value_object_is_empty) {
1205 object = Object::New(info.GetIsolate());
1206 }
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00001207 info.GetReturnValue().Set(object);
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +00001208}
1209
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001210template<typename T>
1211Handle<Value> TestFastReturnValues() {
1212 LocalContext env;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00001213 v8::Isolate* isolate = env->GetIsolate();
1214 v8::EscapableHandleScope scope(isolate);
1215 v8::Handle<v8::ObjectTemplate> object_template =
1216 v8::ObjectTemplate::New(isolate);
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001217 v8::FunctionCallback callback = &FastReturnValueCallback<T>;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00001218 object_template->Set(isolate, "callback",
1219 v8::FunctionTemplate::New(isolate, callback));
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001220 v8::Local<v8::Object> object = object_template->NewInstance();
1221 (*env)->Global()->Set(v8_str("callback_object"), object);
machenbach@chromium.orgafbdadc2013-12-09 16:12:18 +00001222 return scope.Escape(CompileRun("callback_object.callback()"));
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001223}
1224
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001225
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001226THREADED_PROFILED_TEST(FastReturnValues) {
danno@chromium.org1fd77d52013-06-07 16:01:45 +00001227 LocalContext env;
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001228 v8::HandleScope scope(CcTest::isolate());
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001229 v8::Handle<v8::Value> value;
danno@chromium.org1fd77d52013-06-07 16:01:45 +00001230 // check int32_t and uint32_t
1231 int32_t int_values[] = {
1232 0, 234, -723,
1233 i::Smi::kMinValue, i::Smi::kMaxValue
1234 };
1235 for (size_t i = 0; i < ARRAY_SIZE(int_values); i++) {
1236 for (int modifier = -1; modifier <= 1; modifier++) {
1237 int int_value = int_values[i] + modifier;
1238 // check int32_t
1239 fast_return_value_int32 = int_value;
1240 value = TestFastReturnValues<int32_t>();
1241 CHECK(value->IsInt32());
1242 CHECK(fast_return_value_int32 == value->Int32Value());
1243 // check uint32_t
1244 fast_return_value_uint32 = static_cast<uint32_t>(int_value);
1245 value = TestFastReturnValues<uint32_t>();
1246 CHECK(value->IsUint32());
1247 CHECK(fast_return_value_uint32 == value->Uint32Value());
1248 }
1249 }
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001250 // check double
1251 value = TestFastReturnValues<double>();
1252 CHECK(value->IsNumber());
1253 CHECK_EQ(kFastReturnValueDouble, value->ToNumber()->Value());
1254 // check bool values
1255 for (int i = 0; i < 2; i++) {
1256 fast_return_value_bool = i == 0;
1257 value = TestFastReturnValues<bool>();
1258 CHECK(value->IsBoolean());
1259 CHECK_EQ(fast_return_value_bool, value->ToBoolean()->Value());
1260 }
1261 // check oddballs
ulan@chromium.org837a67e2013-06-11 15:39:48 +00001262 ReturnValueOddball oddballs[] = {
1263 kNullReturnValue,
1264 kUndefinedReturnValue,
1265 kEmptyStringReturnValue
1266 };
1267 for (size_t i = 0; i < ARRAY_SIZE(oddballs); i++) {
1268 fast_return_value_void = oddballs[i];
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001269 value = TestFastReturnValues<void>();
ulan@chromium.org837a67e2013-06-11 15:39:48 +00001270 switch (fast_return_value_void) {
1271 case kNullReturnValue:
1272 CHECK(value->IsNull());
1273 break;
1274 case kUndefinedReturnValue:
1275 CHECK(value->IsUndefined());
1276 break;
1277 case kEmptyStringReturnValue:
1278 CHECK(value->IsString());
1279 CHECK_EQ(0, v8::String::Cast(*value)->Length());
1280 break;
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001281 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001282 }
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00001283 // check handles
1284 fast_return_value_object_is_empty = false;
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +00001285 value = TestFastReturnValues<Object>();
1286 CHECK(value->IsObject());
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00001287 fast_return_value_object_is_empty = true;
1288 value = TestFastReturnValues<Object>();
1289 CHECK(value->IsUndefined());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001290}
1291
1292
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001293THREADED_TEST(FunctionTemplateSetLength) {
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001294 LocalContext env;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001295 v8::Isolate* isolate = env->GetIsolate();
1296 v8::HandleScope scope(isolate);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001297 {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001298 Local<v8::FunctionTemplate> fun_templ =
1299 v8::FunctionTemplate::New(isolate,
1300 handle_callback,
1301 Handle<v8::Value>(),
1302 Handle<v8::Signature>(),
1303 23);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001304 Local<Function> fun = fun_templ->GetFunction();
1305 env->Global()->Set(v8_str("obj"), fun);
1306 Local<Script> script = v8_compile("obj.length");
1307 CHECK_EQ(23, script->Run()->Int32Value());
1308 }
1309 {
1310 Local<v8::FunctionTemplate> fun_templ =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001311 v8::FunctionTemplate::New(isolate, handle_callback);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001312 fun_templ->SetLength(22);
1313 Local<Function> fun = fun_templ->GetFunction();
1314 env->Global()->Set(v8_str("obj"), fun);
1315 Local<Script> script = v8_compile("obj.length");
1316 CHECK_EQ(22, script->Run()->Int32Value());
1317 }
1318 {
1319 // Without setting length it defaults to 0.
1320 Local<v8::FunctionTemplate> fun_templ =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001321 v8::FunctionTemplate::New(isolate, handle_callback);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001322 Local<Function> fun = fun_templ->GetFunction();
1323 env->Global()->Set(v8_str("obj"), fun);
1324 Local<Script> script = v8_compile("obj.length");
1325 CHECK_EQ(0, script->Run()->Int32Value());
1326 }
1327}
1328
1329
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001330static void* expected_ptr;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001331static void callback(const v8::FunctionCallbackInfo<v8::Value>& args) {
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00001332 void* ptr = v8::External::Cast(*args.Data())->Value();
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001333 CHECK_EQ(expected_ptr, ptr);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001334 args.GetReturnValue().Set(true);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001335}
1336
1337
1338static void TestExternalPointerWrapping() {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001339 LocalContext env;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001340 v8::Isolate* isolate = env->GetIsolate();
1341 v8::HandleScope scope(isolate);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001342
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00001343 v8::Handle<v8::Value> data =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001344 v8::External::New(isolate, expected_ptr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001345
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001346 v8::Handle<v8::Object> obj = v8::Object::New(isolate);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001347 obj->Set(v8_str("func"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001348 v8::FunctionTemplate::New(isolate, callback, data)->GetFunction());
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001349 env->Global()->Set(v8_str("obj"), obj);
1350
1351 CHECK(CompileRun(
1352 "function foo() {\n"
1353 " for (var i = 0; i < 13; i++) obj.func();\n"
1354 "}\n"
1355 "foo(), true")->BooleanValue());
1356}
1357
1358
1359THREADED_TEST(ExternalWrap) {
1360 // Check heap allocated object.
1361 int* ptr = new int;
1362 expected_ptr = ptr;
1363 TestExternalPointerWrapping();
1364 delete ptr;
1365
1366 // Check stack allocated object.
1367 int foo;
1368 expected_ptr = &foo;
1369 TestExternalPointerWrapping();
1370
1371 // Check not aligned addresses.
1372 const int n = 100;
1373 char* s = new char[n];
1374 for (int i = 0; i < n; i++) {
1375 expected_ptr = s + i;
1376 TestExternalPointerWrapping();
1377 }
1378
1379 delete[] s;
1380
1381 // Check several invalid addresses.
1382 expected_ptr = reinterpret_cast<void*>(1);
1383 TestExternalPointerWrapping();
1384
1385 expected_ptr = reinterpret_cast<void*>(0xdeadbeef);
1386 TestExternalPointerWrapping();
1387
1388 expected_ptr = reinterpret_cast<void*>(0xdeadbeef + 1);
1389 TestExternalPointerWrapping();
1390
1391#if defined(V8_HOST_ARCH_X64)
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001392 // Check a value with a leading 1 bit in x64 Smi encoding.
1393 expected_ptr = reinterpret_cast<void*>(0x400000000);
1394 TestExternalPointerWrapping();
1395
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001396 expected_ptr = reinterpret_cast<void*>(0xdeadbeefdeadbeef);
1397 TestExternalPointerWrapping();
1398
1399 expected_ptr = reinterpret_cast<void*>(0xdeadbeefdeadbeef + 1);
1400 TestExternalPointerWrapping();
1401#endif
1402}
1403
1404
sgjesse@chromium.org900d3b72009-08-07 11:24:25 +00001405THREADED_TEST(FindInstanceInPrototypeChain) {
sgjesse@chromium.org900d3b72009-08-07 11:24:25 +00001406 LocalContext env;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001407 v8::Isolate* isolate = env->GetIsolate();
1408 v8::HandleScope scope(isolate);
sgjesse@chromium.org900d3b72009-08-07 11:24:25 +00001409
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001410 Local<v8::FunctionTemplate> base = v8::FunctionTemplate::New(isolate);
1411 Local<v8::FunctionTemplate> derived = v8::FunctionTemplate::New(isolate);
1412 Local<v8::FunctionTemplate> other = v8::FunctionTemplate::New(isolate);
sgjesse@chromium.org900d3b72009-08-07 11:24:25 +00001413 derived->Inherit(base);
1414
1415 Local<v8::Function> base_function = base->GetFunction();
1416 Local<v8::Function> derived_function = derived->GetFunction();
1417 Local<v8::Function> other_function = other->GetFunction();
1418
1419 Local<v8::Object> base_instance = base_function->NewInstance();
1420 Local<v8::Object> derived_instance = derived_function->NewInstance();
1421 Local<v8::Object> derived_instance2 = derived_function->NewInstance();
1422 Local<v8::Object> other_instance = other_function->NewInstance();
1423 derived_instance2->Set(v8_str("__proto__"), derived_instance);
1424 other_instance->Set(v8_str("__proto__"), derived_instance2);
1425
1426 // base_instance is only an instance of base.
1427 CHECK_EQ(base_instance,
1428 base_instance->FindInstanceInPrototypeChain(base));
1429 CHECK(base_instance->FindInstanceInPrototypeChain(derived).IsEmpty());
1430 CHECK(base_instance->FindInstanceInPrototypeChain(other).IsEmpty());
1431
1432 // derived_instance is an instance of base and derived.
1433 CHECK_EQ(derived_instance,
1434 derived_instance->FindInstanceInPrototypeChain(base));
1435 CHECK_EQ(derived_instance,
1436 derived_instance->FindInstanceInPrototypeChain(derived));
1437 CHECK(derived_instance->FindInstanceInPrototypeChain(other).IsEmpty());
1438
1439 // other_instance is an instance of other and its immediate
1440 // prototype derived_instance2 is an instance of base and derived.
1441 // Note, derived_instance is an instance of base and derived too,
1442 // but it comes after derived_instance2 in the prototype chain of
1443 // other_instance.
1444 CHECK_EQ(derived_instance2,
1445 other_instance->FindInstanceInPrototypeChain(base));
1446 CHECK_EQ(derived_instance2,
1447 other_instance->FindInstanceInPrototypeChain(derived));
1448 CHECK_EQ(other_instance,
1449 other_instance->FindInstanceInPrototypeChain(other));
1450}
1451
1452
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001453THREADED_TEST(TinyInteger) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001454 LocalContext env;
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001455 v8::Isolate* isolate = env->GetIsolate();
1456 v8::HandleScope scope(isolate);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001457
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001458 int32_t value = 239;
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001459 Local<v8::Integer> value_obj = v8::Integer::New(isolate, value);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001460 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001461
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001462 value_obj = v8::Integer::New(isolate, value);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001463 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001464}
1465
1466
1467THREADED_TEST(BigSmiInteger) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001468 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001469 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001470 v8::Isolate* isolate = CcTest::isolate();
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001471
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001472 int32_t value = i::Smi::kMaxValue;
1473 // We cannot add one to a Smi::kMaxValue without wrapping.
verwaest@chromium.org662436e2013-08-28 08:41:27 +00001474 if (i::SmiValuesAre31Bits()) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001475 CHECK(i::Smi::IsValid(value));
1476 CHECK(!i::Smi::IsValid(value + 1));
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001477
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001478 Local<v8::Integer> value_obj = v8::Integer::New(isolate, value);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001479 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001480
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001481 value_obj = v8::Integer::New(isolate, value);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001482 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001483 }
1484}
1485
1486
1487THREADED_TEST(BigInteger) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001488 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001489 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001490 v8::Isolate* isolate = CcTest::isolate();
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001491
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001492 // We cannot add one to a Smi::kMaxValue without wrapping.
verwaest@chromium.org662436e2013-08-28 08:41:27 +00001493 if (i::SmiValuesAre31Bits()) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001494 // The casts allow this to compile, even if Smi::kMaxValue is 2^31-1.
1495 // The code will not be run in that case, due to the "if" guard.
1496 int32_t value =
1497 static_cast<int32_t>(static_cast<uint32_t>(i::Smi::kMaxValue) + 1);
1498 CHECK(value > i::Smi::kMaxValue);
1499 CHECK(!i::Smi::IsValid(value));
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001500
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001501 Local<v8::Integer> value_obj = v8::Integer::New(isolate, value);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001502 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001503
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001504 value_obj = v8::Integer::New(isolate, value);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001505 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001506 }
1507}
1508
1509
1510THREADED_TEST(TinyUnsignedInteger) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001511 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001512 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001513 v8::Isolate* isolate = CcTest::isolate();
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001514
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001515 uint32_t value = 239;
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001516
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001517 Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001518 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001519
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001520 value_obj = v8::Integer::NewFromUnsigned(isolate, value);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001521 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001522}
1523
1524
1525THREADED_TEST(BigUnsignedSmiInteger) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001526 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001527 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001528 v8::Isolate* isolate = CcTest::isolate();
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001529
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001530 uint32_t value = static_cast<uint32_t>(i::Smi::kMaxValue);
1531 CHECK(i::Smi::IsValid(value));
1532 CHECK(!i::Smi::IsValid(value + 1));
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001533
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001534 Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001535 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001536
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001537 value_obj = v8::Integer::NewFromUnsigned(isolate, value);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001538 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001539}
1540
1541
1542THREADED_TEST(BigUnsignedInteger) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001543 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001544 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001545 v8::Isolate* isolate = CcTest::isolate();
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001546
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001547 uint32_t value = static_cast<uint32_t>(i::Smi::kMaxValue) + 1;
1548 CHECK(value > static_cast<uint32_t>(i::Smi::kMaxValue));
1549 CHECK(!i::Smi::IsValid(value));
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001550
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001551 Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001552 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001553
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001554 value_obj = v8::Integer::NewFromUnsigned(isolate, value);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001555 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001556}
1557
1558
1559THREADED_TEST(OutOfSignedRangeUnsignedInteger) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001560 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001561 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001562 v8::Isolate* isolate = CcTest::isolate();
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001563
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001564 uint32_t INT32_MAX_AS_UINT = (1U << 31) - 1;
1565 uint32_t value = INT32_MAX_AS_UINT + 1;
1566 CHECK(value > INT32_MAX_AS_UINT); // No overflow.
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001567
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001568 Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001569 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001570
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001571 value_obj = v8::Integer::NewFromUnsigned(isolate, value);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001572 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001573}
1574
1575
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001576THREADED_TEST(IsNativeError) {
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001577 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001578 v8::HandleScope scope(env->GetIsolate());
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001579 v8::Handle<Value> syntax_error = CompileRun(
1580 "var out = 0; try { eval(\"#\"); } catch(x) { out = x; } out; ");
1581 CHECK(syntax_error->IsNativeError());
1582 v8::Handle<Value> not_error = CompileRun("{a:42}");
1583 CHECK(!not_error->IsNativeError());
1584 v8::Handle<Value> not_object = CompileRun("42");
1585 CHECK(!not_object->IsNativeError());
1586}
1587
1588
1589THREADED_TEST(StringObject) {
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001590 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001591 v8::HandleScope scope(env->GetIsolate());
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001592 v8::Handle<Value> boxed_string = CompileRun("new String(\"test\")");
1593 CHECK(boxed_string->IsStringObject());
1594 v8::Handle<Value> unboxed_string = CompileRun("\"test\"");
1595 CHECK(!unboxed_string->IsStringObject());
1596 v8::Handle<Value> boxed_not_string = CompileRun("new Number(42)");
1597 CHECK(!boxed_not_string->IsStringObject());
1598 v8::Handle<Value> not_object = CompileRun("0");
1599 CHECK(!not_object->IsStringObject());
1600 v8::Handle<v8::StringObject> as_boxed = boxed_string.As<v8::StringObject>();
1601 CHECK(!as_boxed.IsEmpty());
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001602 Local<v8::String> the_string = as_boxed->ValueOf();
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001603 CHECK(!the_string.IsEmpty());
1604 ExpectObject("\"test\"", the_string);
1605 v8::Handle<v8::Value> new_boxed_string = v8::StringObject::New(the_string);
1606 CHECK(new_boxed_string->IsStringObject());
1607 as_boxed = new_boxed_string.As<v8::StringObject>();
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001608 the_string = as_boxed->ValueOf();
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001609 CHECK(!the_string.IsEmpty());
1610 ExpectObject("\"test\"", the_string);
1611}
1612
1613
1614THREADED_TEST(NumberObject) {
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001615 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001616 v8::HandleScope scope(env->GetIsolate());
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001617 v8::Handle<Value> boxed_number = CompileRun("new Number(42)");
1618 CHECK(boxed_number->IsNumberObject());
1619 v8::Handle<Value> unboxed_number = CompileRun("42");
1620 CHECK(!unboxed_number->IsNumberObject());
1621 v8::Handle<Value> boxed_not_number = CompileRun("new Boolean(false)");
1622 CHECK(!boxed_not_number->IsNumberObject());
1623 v8::Handle<v8::NumberObject> as_boxed = boxed_number.As<v8::NumberObject>();
1624 CHECK(!as_boxed.IsEmpty());
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001625 double the_number = as_boxed->ValueOf();
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001626 CHECK_EQ(42.0, the_number);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +00001627 v8::Handle<v8::Value> new_boxed_number =
1628 v8::NumberObject::New(env->GetIsolate(), 43);
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001629 CHECK(new_boxed_number->IsNumberObject());
1630 as_boxed = new_boxed_number.As<v8::NumberObject>();
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001631 the_number = as_boxed->ValueOf();
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001632 CHECK_EQ(43.0, the_number);
1633}
1634
1635
1636THREADED_TEST(BooleanObject) {
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001637 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001638 v8::HandleScope scope(env->GetIsolate());
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001639 v8::Handle<Value> boxed_boolean = CompileRun("new Boolean(true)");
1640 CHECK(boxed_boolean->IsBooleanObject());
1641 v8::Handle<Value> unboxed_boolean = CompileRun("true");
1642 CHECK(!unboxed_boolean->IsBooleanObject());
1643 v8::Handle<Value> boxed_not_boolean = CompileRun("new Number(42)");
1644 CHECK(!boxed_not_boolean->IsBooleanObject());
1645 v8::Handle<v8::BooleanObject> as_boxed =
1646 boxed_boolean.As<v8::BooleanObject>();
1647 CHECK(!as_boxed.IsEmpty());
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001648 bool the_boolean = as_boxed->ValueOf();
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001649 CHECK_EQ(true, the_boolean);
1650 v8::Handle<v8::Value> boxed_true = v8::BooleanObject::New(true);
1651 v8::Handle<v8::Value> boxed_false = v8::BooleanObject::New(false);
1652 CHECK(boxed_true->IsBooleanObject());
1653 CHECK(boxed_false->IsBooleanObject());
1654 as_boxed = boxed_true.As<v8::BooleanObject>();
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001655 CHECK_EQ(true, as_boxed->ValueOf());
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001656 as_boxed = boxed_false.As<v8::BooleanObject>();
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001657 CHECK_EQ(false, as_boxed->ValueOf());
1658}
1659
1660
1661THREADED_TEST(PrimitiveAndWrappedBooleans) {
1662 LocalContext env;
1663 v8::HandleScope scope(env->GetIsolate());
1664
machenbach@chromium.org37be4082013-11-26 13:50:38 +00001665 Local<Value> primitive_false = Boolean::New(env->GetIsolate(), false);
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001666 CHECK(primitive_false->IsBoolean());
1667 CHECK(!primitive_false->IsBooleanObject());
1668 CHECK(!primitive_false->BooleanValue());
1669 CHECK(!primitive_false->IsTrue());
1670 CHECK(primitive_false->IsFalse());
1671
1672 Local<Value> false_value = BooleanObject::New(false);
1673 CHECK(!false_value->IsBoolean());
1674 CHECK(false_value->IsBooleanObject());
1675 CHECK(false_value->BooleanValue());
1676 CHECK(!false_value->IsTrue());
1677 CHECK(!false_value->IsFalse());
1678
1679 Local<BooleanObject> false_boolean_object = false_value.As<BooleanObject>();
1680 CHECK(!false_boolean_object->IsBoolean());
1681 CHECK(false_boolean_object->IsBooleanObject());
1682 // TODO(svenpanne) Uncomment when BooleanObject::BooleanValue() is deleted.
1683 // CHECK(false_boolean_object->BooleanValue());
1684 CHECK(!false_boolean_object->ValueOf());
1685 CHECK(!false_boolean_object->IsTrue());
1686 CHECK(!false_boolean_object->IsFalse());
1687
machenbach@chromium.org37be4082013-11-26 13:50:38 +00001688 Local<Value> primitive_true = Boolean::New(env->GetIsolate(), true);
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001689 CHECK(primitive_true->IsBoolean());
1690 CHECK(!primitive_true->IsBooleanObject());
1691 CHECK(primitive_true->BooleanValue());
1692 CHECK(primitive_true->IsTrue());
1693 CHECK(!primitive_true->IsFalse());
1694
1695 Local<Value> true_value = BooleanObject::New(true);
1696 CHECK(!true_value->IsBoolean());
1697 CHECK(true_value->IsBooleanObject());
1698 CHECK(true_value->BooleanValue());
1699 CHECK(!true_value->IsTrue());
1700 CHECK(!true_value->IsFalse());
1701
1702 Local<BooleanObject> true_boolean_object = true_value.As<BooleanObject>();
1703 CHECK(!true_boolean_object->IsBoolean());
1704 CHECK(true_boolean_object->IsBooleanObject());
1705 // TODO(svenpanne) Uncomment when BooleanObject::BooleanValue() is deleted.
1706 // CHECK(true_boolean_object->BooleanValue());
1707 CHECK(true_boolean_object->ValueOf());
1708 CHECK(!true_boolean_object->IsTrue());
1709 CHECK(!true_boolean_object->IsFalse());
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001710}
1711
1712
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001713THREADED_TEST(Number) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001714 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001715 v8::HandleScope scope(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001716 double PI = 3.1415926;
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001717 Local<v8::Number> pi_obj = v8::Number::New(env->GetIsolate(), PI);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001718 CHECK_EQ(PI, pi_obj->NumberValue());
1719}
1720
1721
1722THREADED_TEST(ToNumber) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001723 LocalContext env;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00001724 v8::Isolate* isolate = CcTest::isolate();
1725 v8::HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001726 Local<String> str = v8_str("3.1415926");
1727 CHECK_EQ(3.1415926, str->NumberValue());
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00001728 v8::Handle<v8::Boolean> t = v8::True(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001729 CHECK_EQ(1.0, t->NumberValue());
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00001730 v8::Handle<v8::Boolean> f = v8::False(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001731 CHECK_EQ(0.0, f->NumberValue());
1732}
1733
1734
1735THREADED_TEST(Date) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001736 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001737 v8::HandleScope scope(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001738 double PI = 3.1415926;
machenbach@chromium.org9f18d912013-11-28 13:42:41 +00001739 Local<Value> date = v8::Date::New(env->GetIsolate(), PI);
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +00001740 CHECK_EQ(3.0, date->NumberValue());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001741 date.As<v8::Date>()->Set(v8_str("property"),
1742 v8::Integer::New(env->GetIsolate(), 42));
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +00001743 CHECK_EQ(42, date.As<v8::Date>()->Get(v8_str("property"))->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001744}
1745
1746
1747THREADED_TEST(Boolean) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001748 LocalContext env;
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001749 v8::Isolate* isolate = env->GetIsolate();
1750 v8::HandleScope scope(isolate);
1751 v8::Handle<v8::Boolean> t = v8::True(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001752 CHECK(t->Value());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001753 v8::Handle<v8::Boolean> f = v8::False(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001754 CHECK(!f->Value());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001755 v8::Handle<v8::Primitive> u = v8::Undefined(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001756 CHECK(!u->BooleanValue());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001757 v8::Handle<v8::Primitive> n = v8::Null(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001758 CHECK(!n->BooleanValue());
1759 v8::Handle<String> str1 = v8_str("");
1760 CHECK(!str1->BooleanValue());
1761 v8::Handle<String> str2 = v8_str("x");
1762 CHECK(str2->BooleanValue());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001763 CHECK(!v8::Number::New(isolate, 0)->BooleanValue());
1764 CHECK(v8::Number::New(isolate, -1)->BooleanValue());
1765 CHECK(v8::Number::New(isolate, 1)->BooleanValue());
1766 CHECK(v8::Number::New(isolate, 42)->BooleanValue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001767 CHECK(!v8_compile("NaN")->Run()->BooleanValue());
1768}
1769
1770
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001771static void DummyCallHandler(const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001772 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001773 args.GetReturnValue().Set(v8_num(13.4));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001774}
1775
1776
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001777static void GetM(Local<String> name,
1778 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001779 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001780 info.GetReturnValue().Set(v8_num(876));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001781}
1782
1783
1784THREADED_TEST(GlobalPrototype) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001785 v8::Isolate* isolate = CcTest::isolate();
1786 v8::HandleScope scope(isolate);
1787 v8::Handle<v8::FunctionTemplate> func_templ =
1788 v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001789 func_templ->PrototypeTemplate()->Set(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001790 isolate, "dummy", v8::FunctionTemplate::New(isolate, DummyCallHandler));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001791 v8::Handle<ObjectTemplate> templ = func_templ->InstanceTemplate();
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001792 templ->Set(isolate, "x", v8_num(200));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001793 templ->SetAccessor(v8_str("m"), GetM);
1794 LocalContext env(0, templ);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001795 v8::Handle<Script> script(v8_compile("dummy()"));
1796 v8::Handle<Value> result(script->Run());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001797 CHECK_EQ(13.4, result->NumberValue());
1798 CHECK_EQ(200, v8_compile("x")->Run()->Int32Value());
1799 CHECK_EQ(876, v8_compile("m")->Run()->Int32Value());
1800}
1801
1802
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001803THREADED_TEST(ObjectTemplate) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001804 v8::Isolate* isolate = CcTest::isolate();
1805 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00001806 Local<ObjectTemplate> templ1 = ObjectTemplate::New(isolate);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001807 templ1->Set(isolate, "x", v8_num(10));
1808 templ1->Set(isolate, "y", v8_num(13));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001809 LocalContext env;
1810 Local<v8::Object> instance1 = templ1->NewInstance();
1811 env->Global()->Set(v8_str("p"), instance1);
1812 CHECK(v8_compile("(p.x == 10)")->Run()->BooleanValue());
1813 CHECK(v8_compile("(p.y == 13)")->Run()->BooleanValue());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001814 Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(isolate);
1815 fun->PrototypeTemplate()->Set(isolate, "nirk", v8_num(123));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001816 Local<ObjectTemplate> templ2 = fun->InstanceTemplate();
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001817 templ2->Set(isolate, "a", v8_num(12));
1818 templ2->Set(isolate, "b", templ1);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001819 Local<v8::Object> instance2 = templ2->NewInstance();
1820 env->Global()->Set(v8_str("q"), instance2);
1821 CHECK(v8_compile("(q.nirk == 123)")->Run()->BooleanValue());
1822 CHECK(v8_compile("(q.a == 12)")->Run()->BooleanValue());
1823 CHECK(v8_compile("(q.b.x == 10)")->Run()->BooleanValue());
1824 CHECK(v8_compile("(q.b.y == 13)")->Run()->BooleanValue());
1825}
1826
1827
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001828static void GetFlabby(const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001829 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001830 args.GetReturnValue().Set(v8_num(17.2));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001831}
1832
1833
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001834static void GetKnurd(Local<String> property,
1835 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001836 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001837 info.GetReturnValue().Set(v8_num(15.2));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001838}
1839
1840
1841THREADED_TEST(DescriptorInheritance) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001842 v8::Isolate* isolate = CcTest::isolate();
1843 v8::HandleScope scope(isolate);
1844 v8::Handle<v8::FunctionTemplate> super = v8::FunctionTemplate::New(isolate);
1845 super->PrototypeTemplate()->Set(isolate, "flabby",
1846 v8::FunctionTemplate::New(isolate,
1847 GetFlabby));
1848 super->PrototypeTemplate()->Set(isolate, "PI", v8_num(3.14));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001849
1850 super->InstanceTemplate()->SetAccessor(v8_str("knurd"), GetKnurd);
1851
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001852 v8::Handle<v8::FunctionTemplate> base1 = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001853 base1->Inherit(super);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001854 base1->PrototypeTemplate()->Set(isolate, "v1", v8_num(20.1));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001855
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001856 v8::Handle<v8::FunctionTemplate> base2 = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001857 base2->Inherit(super);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001858 base2->PrototypeTemplate()->Set(isolate, "v2", v8_num(10.1));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001859
1860 LocalContext env;
1861
1862 env->Global()->Set(v8_str("s"), super->GetFunction());
1863 env->Global()->Set(v8_str("base1"), base1->GetFunction());
1864 env->Global()->Set(v8_str("base2"), base2->GetFunction());
1865
1866 // Checks right __proto__ chain.
1867 CHECK(CompileRun("base1.prototype.__proto__ == s.prototype")->BooleanValue());
1868 CHECK(CompileRun("base2.prototype.__proto__ == s.prototype")->BooleanValue());
1869
1870 CHECK(v8_compile("s.prototype.PI == 3.14")->Run()->BooleanValue());
1871
1872 // Instance accessor should not be visible on function object or its prototype
1873 CHECK(CompileRun("s.knurd == undefined")->BooleanValue());
1874 CHECK(CompileRun("s.prototype.knurd == undefined")->BooleanValue());
1875 CHECK(CompileRun("base1.prototype.knurd == undefined")->BooleanValue());
1876
1877 env->Global()->Set(v8_str("obj"),
1878 base1->GetFunction()->NewInstance());
1879 CHECK_EQ(17.2, v8_compile("obj.flabby()")->Run()->NumberValue());
1880 CHECK(v8_compile("'flabby' in obj")->Run()->BooleanValue());
1881 CHECK_EQ(15.2, v8_compile("obj.knurd")->Run()->NumberValue());
1882 CHECK(v8_compile("'knurd' in obj")->Run()->BooleanValue());
1883 CHECK_EQ(20.1, v8_compile("obj.v1")->Run()->NumberValue());
1884
1885 env->Global()->Set(v8_str("obj2"),
1886 base2->GetFunction()->NewInstance());
1887 CHECK_EQ(17.2, v8_compile("obj2.flabby()")->Run()->NumberValue());
1888 CHECK(v8_compile("'flabby' in obj2")->Run()->BooleanValue());
1889 CHECK_EQ(15.2, v8_compile("obj2.knurd")->Run()->NumberValue());
1890 CHECK(v8_compile("'knurd' in obj2")->Run()->BooleanValue());
1891 CHECK_EQ(10.1, v8_compile("obj2.v2")->Run()->NumberValue());
1892
1893 // base1 and base2 cannot cross reference to each's prototype
1894 CHECK(v8_compile("obj.v2")->Run()->IsUndefined());
1895 CHECK(v8_compile("obj2.v1")->Run()->IsUndefined());
1896}
1897
1898
1899int echo_named_call_count;
1900
1901
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001902static void EchoNamedProperty(Local<String> name,
1903 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001904 ApiTestFuzzer::Fuzz();
1905 CHECK_EQ(v8_str("data"), info.Data());
1906 echo_named_call_count++;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001907 info.GetReturnValue().Set(name);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001908}
1909
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001910
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001911// Helper functions for Interceptor/Accessor interaction tests
1912
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001913void SimpleAccessorGetter(Local<String> name,
1914 const v8::PropertyCallbackInfo<v8::Value>& info) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001915 Handle<Object> self = info.This();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001916 info.GetReturnValue().Set(
1917 self->Get(String::Concat(v8_str("accessor_"), name)));
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001918}
1919
1920void SimpleAccessorSetter(Local<String> name, Local<Value> value,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001921 const v8::PropertyCallbackInfo<void>& info) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001922 Handle<Object> self = info.This();
1923 self->Set(String::Concat(v8_str("accessor_"), name), value);
1924}
1925
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001926void EmptyInterceptorGetter(Local<String> name,
1927 const v8::PropertyCallbackInfo<v8::Value>& info) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001928}
1929
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001930void EmptyInterceptorSetter(Local<String> name,
1931 Local<Value> value,
1932 const v8::PropertyCallbackInfo<v8::Value>& info) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001933}
1934
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001935void InterceptorGetter(Local<String> name,
1936 const v8::PropertyCallbackInfo<v8::Value>& info) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001937 // Intercept names that start with 'interceptor_'.
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00001938 String::Utf8Value utf8(name);
1939 char* name_str = *utf8;
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001940 char prefix[] = "interceptor_";
1941 int i;
1942 for (i = 0; name_str[i] && prefix[i]; ++i) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001943 if (name_str[i] != prefix[i]) return;
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001944 }
1945 Handle<Object> self = info.This();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001946 info.GetReturnValue().Set(self->GetHiddenValue(v8_str(name_str + i)));
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001947}
1948
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001949void InterceptorSetter(Local<String> name,
1950 Local<Value> value,
1951 const v8::PropertyCallbackInfo<v8::Value>& info) {
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +00001952 // Intercept accesses that set certain integer values, for which the name does
1953 // not start with 'accessor_'.
1954 String::Utf8Value utf8(name);
1955 char* name_str = *utf8;
1956 char prefix[] = "accessor_";
1957 int i;
1958 for (i = 0; name_str[i] && prefix[i]; ++i) {
1959 if (name_str[i] != prefix[i]) break;
1960 }
1961 if (!prefix[i]) return;
1962
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001963 if (value->IsInt32() && value->Int32Value() < 10000) {
1964 Handle<Object> self = info.This();
1965 self->SetHiddenValue(name, value);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001966 info.GetReturnValue().Set(value);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001967 }
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001968}
1969
1970void AddAccessor(Handle<FunctionTemplate> templ,
1971 Handle<String> name,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001972 v8::AccessorGetterCallback getter,
1973 v8::AccessorSetterCallback setter) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001974 templ->PrototypeTemplate()->SetAccessor(name, getter, setter);
1975}
1976
1977void AddInterceptor(Handle<FunctionTemplate> templ,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001978 v8::NamedPropertyGetterCallback getter,
1979 v8::NamedPropertySetterCallback setter) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001980 templ->InstanceTemplate()->SetNamedPropertyHandler(getter, setter);
1981}
1982
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001983
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001984THREADED_TEST(EmptyInterceptorDoesNotShadowAccessors) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001985 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001986 Handle<FunctionTemplate> parent = FunctionTemplate::New(CcTest::isolate());
1987 Handle<FunctionTemplate> child = FunctionTemplate::New(CcTest::isolate());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001988 child->Inherit(parent);
1989 AddAccessor(parent, v8_str("age"),
1990 SimpleAccessorGetter, SimpleAccessorSetter);
1991 AddInterceptor(child, EmptyInterceptorGetter, EmptyInterceptorSetter);
1992 LocalContext env;
1993 env->Global()->Set(v8_str("Child"), child->GetFunction());
1994 CompileRun("var child = new Child;"
1995 "child.age = 10;");
1996 ExpectBoolean("child.hasOwnProperty('age')", false);
1997 ExpectInt32("child.age", 10);
1998 ExpectInt32("child.accessor_age", 10);
1999}
2000
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002001
machenbach@chromium.orgbbbda922014-01-23 09:38:20 +00002002THREADED_TEST(EmptyInterceptorBreakTransitions) {
2003 v8::HandleScope scope(CcTest::isolate());
2004 Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
2005 AddInterceptor(templ, EmptyInterceptorGetter, EmptyInterceptorSetter);
2006 LocalContext env;
2007 env->Global()->Set(v8_str("Constructor"), templ->GetFunction());
2008 CompileRun("var o1 = new Constructor;"
2009 "o1.a = 1;" // Ensure a and x share the descriptor array.
2010 "Object.defineProperty(o1, 'x', {value: 10});");
2011 CompileRun("var o2 = new Constructor;"
2012 "o2.a = 1;"
2013 "Object.defineProperty(o2, 'x', {value: 10});");
2014}
2015
2016
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002017THREADED_TEST(EmptyInterceptorDoesNotShadowJSAccessors) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002018 v8::Isolate* isolate = CcTest::isolate();
2019 v8::HandleScope scope(isolate);
2020 Handle<FunctionTemplate> parent = FunctionTemplate::New(isolate);
2021 Handle<FunctionTemplate> child = FunctionTemplate::New(isolate);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002022 child->Inherit(parent);
2023 AddInterceptor(child, EmptyInterceptorGetter, EmptyInterceptorSetter);
2024 LocalContext env;
2025 env->Global()->Set(v8_str("Child"), child->GetFunction());
2026 CompileRun("var child = new Child;"
2027 "var parent = child.__proto__;"
2028 "Object.defineProperty(parent, 'age', "
2029 " {get: function(){ return this.accessor_age; }, "
2030 " set: function(v){ this.accessor_age = v; }, "
2031 " enumerable: true, configurable: true});"
2032 "child.age = 10;");
2033 ExpectBoolean("child.hasOwnProperty('age')", false);
2034 ExpectInt32("child.age", 10);
2035 ExpectInt32("child.accessor_age", 10);
2036}
2037
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002038
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002039THREADED_TEST(EmptyInterceptorDoesNotAffectJSProperties) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002040 v8::Isolate* isolate = CcTest::isolate();
2041 v8::HandleScope scope(isolate);
2042 Handle<FunctionTemplate> parent = FunctionTemplate::New(isolate);
2043 Handle<FunctionTemplate> child = FunctionTemplate::New(isolate);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002044 child->Inherit(parent);
2045 AddInterceptor(child, EmptyInterceptorGetter, EmptyInterceptorSetter);
2046 LocalContext env;
2047 env->Global()->Set(v8_str("Child"), child->GetFunction());
2048 CompileRun("var child = new Child;"
2049 "var parent = child.__proto__;"
2050 "parent.name = 'Alice';");
2051 ExpectBoolean("child.hasOwnProperty('name')", false);
2052 ExpectString("child.name", "Alice");
2053 CompileRun("child.name = 'Bob';");
2054 ExpectString("child.name", "Bob");
2055 ExpectBoolean("child.hasOwnProperty('name')", true);
2056 ExpectString("parent.name", "Alice");
2057}
2058
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002059
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002060THREADED_TEST(SwitchFromInterceptorToAccessor) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002061 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002062 Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
danno@chromium.orgbf0c8202011-12-27 10:09:42 +00002063 AddAccessor(templ, v8_str("age"),
2064 SimpleAccessorGetter, SimpleAccessorSetter);
2065 AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
2066 LocalContext env;
2067 env->Global()->Set(v8_str("Obj"), templ->GetFunction());
2068 CompileRun("var obj = new Obj;"
2069 "function setAge(i){ obj.age = i; };"
2070 "for(var i = 0; i <= 10000; i++) setAge(i);");
2071 // All i < 10000 go to the interceptor.
2072 ExpectInt32("obj.interceptor_age", 9999);
2073 // The last i goes to the accessor.
2074 ExpectInt32("obj.accessor_age", 10000);
2075}
2076
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002077
danno@chromium.orgbf0c8202011-12-27 10:09:42 +00002078THREADED_TEST(SwitchFromAccessorToInterceptor) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002079 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002080 Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
danno@chromium.orgbf0c8202011-12-27 10:09:42 +00002081 AddAccessor(templ, v8_str("age"),
2082 SimpleAccessorGetter, SimpleAccessorSetter);
2083 AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
2084 LocalContext env;
2085 env->Global()->Set(v8_str("Obj"), templ->GetFunction());
2086 CompileRun("var obj = new Obj;"
2087 "function setAge(i){ obj.age = i; };"
2088 "for(var i = 20000; i >= 9999; i--) setAge(i);");
2089 // All i >= 10000 go to the accessor.
2090 ExpectInt32("obj.accessor_age", 10000);
2091 // The last i goes to the interceptor.
2092 ExpectInt32("obj.interceptor_age", 9999);
2093}
2094
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002095
danno@chromium.orgbf0c8202011-12-27 10:09:42 +00002096THREADED_TEST(SwitchFromInterceptorToAccessorWithInheritance) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002097 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002098 Handle<FunctionTemplate> parent = FunctionTemplate::New(CcTest::isolate());
2099 Handle<FunctionTemplate> child = FunctionTemplate::New(CcTest::isolate());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002100 child->Inherit(parent);
2101 AddAccessor(parent, v8_str("age"),
2102 SimpleAccessorGetter, SimpleAccessorSetter);
2103 AddInterceptor(child, InterceptorGetter, InterceptorSetter);
2104 LocalContext env;
2105 env->Global()->Set(v8_str("Child"), child->GetFunction());
2106 CompileRun("var child = new Child;"
2107 "function setAge(i){ child.age = i; };"
2108 "for(var i = 0; i <= 10000; i++) setAge(i);");
2109 // All i < 10000 go to the interceptor.
2110 ExpectInt32("child.interceptor_age", 9999);
2111 // The last i goes to the accessor.
2112 ExpectInt32("child.accessor_age", 10000);
2113}
2114
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002115
danno@chromium.orgbf0c8202011-12-27 10:09:42 +00002116THREADED_TEST(SwitchFromAccessorToInterceptorWithInheritance) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002117 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002118 Handle<FunctionTemplate> parent = FunctionTemplate::New(CcTest::isolate());
2119 Handle<FunctionTemplate> child = FunctionTemplate::New(CcTest::isolate());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002120 child->Inherit(parent);
2121 AddAccessor(parent, v8_str("age"),
2122 SimpleAccessorGetter, SimpleAccessorSetter);
2123 AddInterceptor(child, InterceptorGetter, InterceptorSetter);
2124 LocalContext env;
2125 env->Global()->Set(v8_str("Child"), child->GetFunction());
2126 CompileRun("var child = new Child;"
2127 "function setAge(i){ child.age = i; };"
2128 "for(var i = 20000; i >= 9999; i--) setAge(i);");
2129 // All i >= 10000 go to the accessor.
2130 ExpectInt32("child.accessor_age", 10000);
2131 // The last i goes to the interceptor.
2132 ExpectInt32("child.interceptor_age", 9999);
2133}
2134
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002135
danno@chromium.orgbf0c8202011-12-27 10:09:42 +00002136THREADED_TEST(SwitchFromInterceptorToJSAccessor) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002137 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002138 Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
danno@chromium.orgbf0c8202011-12-27 10:09:42 +00002139 AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
2140 LocalContext env;
2141 env->Global()->Set(v8_str("Obj"), templ->GetFunction());
2142 CompileRun("var obj = new Obj;"
2143 "function setter(i) { this.accessor_age = i; };"
2144 "function getter() { return this.accessor_age; };"
2145 "function setAge(i) { obj.age = i; };"
2146 "Object.defineProperty(obj, 'age', { get:getter, set:setter });"
2147 "for(var i = 0; i <= 10000; i++) setAge(i);");
2148 // All i < 10000 go to the interceptor.
2149 ExpectInt32("obj.interceptor_age", 9999);
2150 // The last i goes to the JavaScript accessor.
2151 ExpectInt32("obj.accessor_age", 10000);
2152 // The installed JavaScript getter is still intact.
2153 // This last part is a regression test for issue 1651 and relies on the fact
2154 // that both interceptor and accessor are being installed on the same object.
2155 ExpectInt32("obj.age", 10000);
2156 ExpectBoolean("obj.hasOwnProperty('age')", true);
2157 ExpectUndefined("Object.getOwnPropertyDescriptor(obj, 'age').value");
2158}
2159
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002160
danno@chromium.orgbf0c8202011-12-27 10:09:42 +00002161THREADED_TEST(SwitchFromJSAccessorToInterceptor) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002162 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002163 Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
danno@chromium.orgbf0c8202011-12-27 10:09:42 +00002164 AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
2165 LocalContext env;
2166 env->Global()->Set(v8_str("Obj"), templ->GetFunction());
2167 CompileRun("var obj = new Obj;"
2168 "function setter(i) { this.accessor_age = i; };"
2169 "function getter() { return this.accessor_age; };"
2170 "function setAge(i) { obj.age = i; };"
2171 "Object.defineProperty(obj, 'age', { get:getter, set:setter });"
2172 "for(var i = 20000; i >= 9999; i--) setAge(i);");
2173 // All i >= 10000 go to the accessor.
2174 ExpectInt32("obj.accessor_age", 10000);
2175 // The last i goes to the interceptor.
2176 ExpectInt32("obj.interceptor_age", 9999);
2177 // The installed JavaScript getter is still intact.
2178 // This last part is a regression test for issue 1651 and relies on the fact
2179 // that both interceptor and accessor are being installed on the same object.
2180 ExpectInt32("obj.age", 10000);
2181 ExpectBoolean("obj.hasOwnProperty('age')", true);
2182 ExpectUndefined("Object.getOwnPropertyDescriptor(obj, 'age').value");
2183}
2184
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002185
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002186THREADED_TEST(SwitchFromInterceptorToProperty) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002187 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002188 Handle<FunctionTemplate> parent = FunctionTemplate::New(CcTest::isolate());
2189 Handle<FunctionTemplate> child = FunctionTemplate::New(CcTest::isolate());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002190 child->Inherit(parent);
2191 AddInterceptor(child, InterceptorGetter, InterceptorSetter);
2192 LocalContext env;
2193 env->Global()->Set(v8_str("Child"), child->GetFunction());
2194 CompileRun("var child = new Child;"
2195 "function setAge(i){ child.age = i; };"
2196 "for(var i = 0; i <= 10000; i++) setAge(i);");
2197 // All i < 10000 go to the interceptor.
2198 ExpectInt32("child.interceptor_age", 9999);
2199 // The last i goes to child's own property.
2200 ExpectInt32("child.age", 10000);
2201}
2202
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002203
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002204THREADED_TEST(SwitchFromPropertyToInterceptor) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002205 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002206 Handle<FunctionTemplate> parent = FunctionTemplate::New(CcTest::isolate());
2207 Handle<FunctionTemplate> child = FunctionTemplate::New(CcTest::isolate());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002208 child->Inherit(parent);
2209 AddInterceptor(child, InterceptorGetter, InterceptorSetter);
2210 LocalContext env;
2211 env->Global()->Set(v8_str("Child"), child->GetFunction());
2212 CompileRun("var child = new Child;"
2213 "function setAge(i){ child.age = i; };"
2214 "for(var i = 20000; i >= 9999; i--) setAge(i);");
2215 // All i >= 10000 go to child's own property.
2216 ExpectInt32("child.age", 10000);
2217 // The last i goes to the interceptor.
2218 ExpectInt32("child.interceptor_age", 9999);
2219}
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002220
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002221
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002222THREADED_TEST(NamedPropertyHandlerGetter) {
2223 echo_named_call_count = 0;
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002224 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002225 v8::Handle<v8::FunctionTemplate> templ =
2226 v8::FunctionTemplate::New(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002227 templ->InstanceTemplate()->SetNamedPropertyHandler(EchoNamedProperty,
2228 0, 0, 0, 0,
2229 v8_str("data"));
2230 LocalContext env;
2231 env->Global()->Set(v8_str("obj"),
2232 templ->GetFunction()->NewInstance());
2233 CHECK_EQ(echo_named_call_count, 0);
2234 v8_compile("obj.x")->Run();
2235 CHECK_EQ(echo_named_call_count, 1);
2236 const char* code = "var str = 'oddle'; obj[str] + obj.poddle;";
2237 v8::Handle<Value> str = CompileRun(code);
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00002238 String::Utf8Value value(str);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002239 CHECK_EQ(*value, "oddlepoddle");
2240 // Check default behavior
2241 CHECK_EQ(v8_compile("obj.flob = 10;")->Run()->Int32Value(), 10);
2242 CHECK(v8_compile("'myProperty' in obj")->Run()->BooleanValue());
2243 CHECK(v8_compile("delete obj.myProperty")->Run()->BooleanValue());
2244}
2245
2246
2247int echo_indexed_call_count = 0;
2248
2249
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002250static void EchoIndexedProperty(
2251 uint32_t index,
2252 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002253 ApiTestFuzzer::Fuzz();
2254 CHECK_EQ(v8_num(637), info.Data());
2255 echo_indexed_call_count++;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002256 info.GetReturnValue().Set(v8_num(index));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002257}
2258
2259
2260THREADED_TEST(IndexedPropertyHandlerGetter) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002261 v8::Isolate* isolate = CcTest::isolate();
2262 v8::HandleScope scope(isolate);
2263 v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002264 templ->InstanceTemplate()->SetIndexedPropertyHandler(EchoIndexedProperty,
2265 0, 0, 0, 0,
2266 v8_num(637));
2267 LocalContext env;
2268 env->Global()->Set(v8_str("obj"),
2269 templ->GetFunction()->NewInstance());
2270 Local<Script> script = v8_compile("obj[900]");
2271 CHECK_EQ(script->Run()->Int32Value(), 900);
2272}
2273
2274
2275v8::Handle<v8::Object> bottom;
2276
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002277static void CheckThisIndexedPropertyHandler(
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002278 uint32_t index,
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002279 const v8::PropertyCallbackInfo<v8::Value>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00002280 CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertyHandler));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002281 ApiTestFuzzer::Fuzz();
2282 CHECK(info.This()->Equals(bottom));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002283}
2284
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002285static void CheckThisNamedPropertyHandler(
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002286 Local<String> name,
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002287 const v8::PropertyCallbackInfo<v8::Value>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00002288 CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertyHandler));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002289 ApiTestFuzzer::Fuzz();
2290 CHECK(info.This()->Equals(bottom));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002291}
2292
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002293void CheckThisIndexedPropertySetter(
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002294 uint32_t index,
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002295 Local<Value> value,
2296 const v8::PropertyCallbackInfo<v8::Value>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00002297 CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertySetter));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002298 ApiTestFuzzer::Fuzz();
2299 CHECK(info.This()->Equals(bottom));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002300}
2301
2302
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002303void CheckThisNamedPropertySetter(
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002304 Local<String> property,
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002305 Local<Value> value,
2306 const v8::PropertyCallbackInfo<v8::Value>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00002307 CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertySetter));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002308 ApiTestFuzzer::Fuzz();
2309 CHECK(info.This()->Equals(bottom));
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002310}
2311
2312void CheckThisIndexedPropertyQuery(
2313 uint32_t index,
2314 const v8::PropertyCallbackInfo<v8::Integer>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00002315 CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertyQuery));
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002316 ApiTestFuzzer::Fuzz();
2317 CHECK(info.This()->Equals(bottom));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002318}
2319
2320
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002321void CheckThisNamedPropertyQuery(
2322 Local<String> property,
2323 const v8::PropertyCallbackInfo<v8::Integer>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00002324 CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertyQuery));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002325 ApiTestFuzzer::Fuzz();
2326 CHECK(info.This()->Equals(bottom));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002327}
2328
2329
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002330void CheckThisIndexedPropertyDeleter(
2331 uint32_t index,
2332 const v8::PropertyCallbackInfo<v8::Boolean>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00002333 CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertyDeleter));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002334 ApiTestFuzzer::Fuzz();
2335 CHECK(info.This()->Equals(bottom));
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002336}
2337
2338
2339void CheckThisNamedPropertyDeleter(
2340 Local<String> property,
2341 const v8::PropertyCallbackInfo<v8::Boolean>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00002342 CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertyDeleter));
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002343 ApiTestFuzzer::Fuzz();
2344 CHECK(info.This()->Equals(bottom));
2345}
2346
2347
2348void CheckThisIndexedPropertyEnumerator(
2349 const v8::PropertyCallbackInfo<v8::Array>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00002350 CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertyEnumerator));
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002351 ApiTestFuzzer::Fuzz();
2352 CHECK(info.This()->Equals(bottom));
2353}
2354
2355
2356void CheckThisNamedPropertyEnumerator(
2357 const v8::PropertyCallbackInfo<v8::Array>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00002358 CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertyEnumerator));
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002359 ApiTestFuzzer::Fuzz();
2360 CHECK(info.This()->Equals(bottom));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002361}
2362
2363
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002364THREADED_PROFILED_TEST(PropertyHandlerInPrototype) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002365 LocalContext env;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002366 v8::Isolate* isolate = env->GetIsolate();
2367 v8::HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002368
2369 // Set up a prototype chain with three interceptors.
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002370 v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002371 templ->InstanceTemplate()->SetIndexedPropertyHandler(
2372 CheckThisIndexedPropertyHandler,
2373 CheckThisIndexedPropertySetter,
2374 CheckThisIndexedPropertyQuery,
2375 CheckThisIndexedPropertyDeleter,
2376 CheckThisIndexedPropertyEnumerator);
2377
2378 templ->InstanceTemplate()->SetNamedPropertyHandler(
2379 CheckThisNamedPropertyHandler,
2380 CheckThisNamedPropertySetter,
2381 CheckThisNamedPropertyQuery,
2382 CheckThisNamedPropertyDeleter,
2383 CheckThisNamedPropertyEnumerator);
2384
2385 bottom = templ->GetFunction()->NewInstance();
2386 Local<v8::Object> top = templ->GetFunction()->NewInstance();
2387 Local<v8::Object> middle = templ->GetFunction()->NewInstance();
2388
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +00002389 bottom->SetPrototype(middle);
2390 middle->SetPrototype(top);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002391 env->Global()->Set(v8_str("obj"), bottom);
2392
2393 // Indexed and named get.
2394 Script::Compile(v8_str("obj[0]"))->Run();
2395 Script::Compile(v8_str("obj.x"))->Run();
2396
2397 // Indexed and named set.
2398 Script::Compile(v8_str("obj[1] = 42"))->Run();
2399 Script::Compile(v8_str("obj.y = 42"))->Run();
2400
2401 // Indexed and named query.
2402 Script::Compile(v8_str("0 in obj"))->Run();
2403 Script::Compile(v8_str("'x' in obj"))->Run();
2404
2405 // Indexed and named deleter.
2406 Script::Compile(v8_str("delete obj[0]"))->Run();
2407 Script::Compile(v8_str("delete obj.x"))->Run();
2408
2409 // Enumerators.
2410 Script::Compile(v8_str("for (var p in obj) ;"))->Run();
2411}
2412
2413
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002414static void PrePropertyHandlerGet(
2415 Local<String> key,
2416 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002417 ApiTestFuzzer::Fuzz();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002418 if (v8_str("pre")->Equals(key)) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002419 info.GetReturnValue().Set(v8_str("PrePropertyHandler: pre"));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002420 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002421}
2422
2423
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002424static void PrePropertyHandlerQuery(
2425 Local<String> key,
2426 const v8::PropertyCallbackInfo<v8::Integer>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002427 if (v8_str("pre")->Equals(key)) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002428 info.GetReturnValue().Set(static_cast<int32_t>(v8::None));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002429 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002430}
2431
2432
2433THREADED_TEST(PrePropertyHandler) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002434 v8::Isolate* isolate = CcTest::isolate();
2435 v8::HandleScope scope(isolate);
2436 v8::Handle<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002437 desc->InstanceTemplate()->SetNamedPropertyHandler(PrePropertyHandlerGet,
2438 0,
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00002439 PrePropertyHandlerQuery);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002440 LocalContext env(NULL, desc->InstanceTemplate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002441 Script::Compile(v8_str(
2442 "var pre = 'Object: pre'; var on = 'Object: on';"))->Run();
2443 v8::Handle<Value> result_pre = Script::Compile(v8_str("pre"))->Run();
2444 CHECK_EQ(v8_str("PrePropertyHandler: pre"), result_pre);
2445 v8::Handle<Value> result_on = Script::Compile(v8_str("on"))->Run();
2446 CHECK_EQ(v8_str("Object: on"), result_on);
2447 v8::Handle<Value> result_post = Script::Compile(v8_str("post"))->Run();
2448 CHECK(result_post.IsEmpty());
2449}
2450
2451
ager@chromium.org870a0b62008-11-04 11:43:05 +00002452THREADED_TEST(UndefinedIsNotEnumerable) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00002453 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00002454 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org870a0b62008-11-04 11:43:05 +00002455 v8::Handle<Value> result = Script::Compile(v8_str(
2456 "this.propertyIsEnumerable(undefined)"))->Run();
2457 CHECK(result->IsFalse());
2458}
2459
2460
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002461v8::Handle<Script> call_recursively_script;
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00002462static const int kTargetRecursionDepth = 200; // near maximum
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002463
2464
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002465static void CallScriptRecursivelyCall(
2466 const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002467 ApiTestFuzzer::Fuzz();
2468 int depth = args.This()->Get(v8_str("depth"))->Int32Value();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002469 if (depth == kTargetRecursionDepth) return;
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002470 args.This()->Set(v8_str("depth"),
2471 v8::Integer::New(args.GetIsolate(), depth + 1));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002472 args.GetReturnValue().Set(call_recursively_script->Run());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002473}
2474
2475
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002476static void CallFunctionRecursivelyCall(
2477 const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002478 ApiTestFuzzer::Fuzz();
2479 int depth = args.This()->Get(v8_str("depth"))->Int32Value();
2480 if (depth == kTargetRecursionDepth) {
2481 printf("[depth = %d]\n", depth);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002482 return;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002483 }
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002484 args.This()->Set(v8_str("depth"),
2485 v8::Integer::New(args.GetIsolate(), depth + 1));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002486 v8::Handle<Value> function =
2487 args.This()->Get(v8_str("callFunctionRecursively"));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002488 args.GetReturnValue().Set(
2489 function.As<Function>()->Call(args.This(), 0, NULL));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002490}
2491
2492
2493THREADED_TEST(DeepCrossLanguageRecursion) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002494 v8::Isolate* isolate = CcTest::isolate();
2495 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00002496 v8::Handle<v8::ObjectTemplate> global = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002497 global->Set(v8_str("callScriptRecursively"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002498 v8::FunctionTemplate::New(isolate, CallScriptRecursivelyCall));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002499 global->Set(v8_str("callFunctionRecursively"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002500 v8::FunctionTemplate::New(isolate, CallFunctionRecursivelyCall));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002501 LocalContext env(NULL, global);
2502
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002503 env->Global()->Set(v8_str("depth"), v8::Integer::New(isolate, 0));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002504 call_recursively_script = v8_compile("callScriptRecursively()");
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00002505 call_recursively_script->Run();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002506 call_recursively_script = v8::Handle<Script>();
2507
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002508 env->Global()->Set(v8_str("depth"), v8::Integer::New(isolate, 0));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002509 Script::Compile(v8_str("callFunctionRecursively()"))->Run();
2510}
2511
2512
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002513static void ThrowingPropertyHandlerGet(
2514 Local<String> key,
2515 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002516 ApiTestFuzzer::Fuzz();
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00002517 info.GetReturnValue().Set(info.GetIsolate()->ThrowException(key));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002518}
2519
2520
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002521static void ThrowingPropertyHandlerSet(
2522 Local<String> key,
2523 Local<Value>,
2524 const v8::PropertyCallbackInfo<v8::Value>& info) {
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00002525 info.GetIsolate()->ThrowException(key);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002526 info.GetReturnValue().SetUndefined(); // not the same as empty handle
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002527}
2528
2529
2530THREADED_TEST(CallbackExceptionRegression) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00002531 v8::Isolate* isolate = CcTest::isolate();
2532 v8::HandleScope scope(isolate);
2533 v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002534 obj->SetNamedPropertyHandler(ThrowingPropertyHandlerGet,
2535 ThrowingPropertyHandlerSet);
2536 LocalContext env;
2537 env->Global()->Set(v8_str("obj"), obj->NewInstance());
2538 v8::Handle<Value> otto = Script::Compile(v8_str(
2539 "try { with (obj) { otto; } } catch (e) { e; }"))->Run();
2540 CHECK_EQ(v8_str("otto"), otto);
2541 v8::Handle<Value> netto = Script::Compile(v8_str(
2542 "try { with (obj) { netto = 4; } } catch (e) { e; }"))->Run();
2543 CHECK_EQ(v8_str("netto"), netto);
2544}
2545
2546
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002547THREADED_TEST(FunctionPrototype) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002548 v8::Isolate* isolate = CcTest::isolate();
2549 v8::HandleScope scope(isolate);
2550 Local<v8::FunctionTemplate> Foo = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002551 Foo->PrototypeTemplate()->Set(v8_str("plak"), v8_num(321));
2552 LocalContext env;
2553 env->Global()->Set(v8_str("Foo"), Foo->GetFunction());
2554 Local<Script> script = Script::Compile(v8_str("Foo.prototype.plak"));
2555 CHECK_EQ(script->Run()->Int32Value(), 321);
2556}
2557
2558
2559THREADED_TEST(InternalFields) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002560 LocalContext env;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002561 v8::Isolate* isolate = env->GetIsolate();
2562 v8::HandleScope scope(isolate);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002563
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002564 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002565 Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
2566 instance_templ->SetInternalFieldCount(1);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002567 Local<v8::Object> obj = templ->GetFunction()->NewInstance();
2568 CHECK_EQ(1, obj->InternalFieldCount());
2569 CHECK(obj->GetInternalField(0)->IsUndefined());
2570 obj->SetInternalField(0, v8_num(17));
2571 CHECK_EQ(17, obj->GetInternalField(0)->Int32Value());
2572}
2573
2574
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002575THREADED_TEST(GlobalObjectInternalFields) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00002576 v8::Isolate* isolate = CcTest::isolate();
2577 v8::HandleScope scope(isolate);
2578 Local<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New(isolate);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002579 global_template->SetInternalFieldCount(1);
2580 LocalContext env(NULL, global_template);
2581 v8::Handle<v8::Object> global_proxy = env->Global();
2582 v8::Handle<v8::Object> global = global_proxy->GetPrototype().As<v8::Object>();
2583 CHECK_EQ(1, global->InternalFieldCount());
2584 CHECK(global->GetInternalField(0)->IsUndefined());
2585 global->SetInternalField(0, v8_num(17));
2586 CHECK_EQ(17, global->GetInternalField(0)->Int32Value());
2587}
2588
2589
danno@chromium.org169691d2013-07-15 08:01:13 +00002590THREADED_TEST(GlobalObjectHasRealIndexedProperty) {
2591 LocalContext env;
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002592 v8::HandleScope scope(CcTest::isolate());
danno@chromium.org169691d2013-07-15 08:01:13 +00002593
2594 v8::Local<v8::Object> global = env->Global();
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00002595 global->Set(0, v8::String::NewFromUtf8(CcTest::isolate(), "value"));
danno@chromium.org169691d2013-07-15 08:01:13 +00002596 CHECK(global->HasRealIndexedProperty(0));
2597}
2598
2599
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002600static void CheckAlignedPointerInInternalField(Handle<v8::Object> obj,
2601 void* value) {
2602 CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(value) & 0x1));
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00002603 obj->SetAlignedPointerInInternalField(0, value);
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002604 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00002605 CHECK_EQ(value, obj->GetAlignedPointerFromInternalField(0));
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002606}
2607
2608
2609THREADED_TEST(InternalFieldsAlignedPointers) {
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002610 LocalContext env;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002611 v8::Isolate* isolate = env->GetIsolate();
2612 v8::HandleScope scope(isolate);
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002613
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002614 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002615 Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
2616 instance_templ->SetInternalFieldCount(1);
2617 Local<v8::Object> obj = templ->GetFunction()->NewInstance();
2618 CHECK_EQ(1, obj->InternalFieldCount());
2619
2620 CheckAlignedPointerInInternalField(obj, NULL);
2621
2622 int* heap_allocated = new int[100];
2623 CheckAlignedPointerInInternalField(obj, heap_allocated);
2624 delete[] heap_allocated;
2625
2626 int stack_allocated[100];
2627 CheckAlignedPointerInInternalField(obj, stack_allocated);
2628
2629 void* huge = reinterpret_cast<void*>(~static_cast<uintptr_t>(1));
2630 CheckAlignedPointerInInternalField(obj, huge);
2631}
2632
2633
2634static void CheckAlignedPointerInEmbedderData(LocalContext* env,
2635 int index,
2636 void* value) {
2637 CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(value) & 0x1));
2638 (*env)->SetAlignedPointerInEmbedderData(index, value);
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002639 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002640 CHECK_EQ(value, (*env)->GetAlignedPointerFromEmbedderData(index));
2641}
2642
2643
2644static void* AlignedTestPointer(int i) {
2645 return reinterpret_cast<void*>(i * 1234);
2646}
2647
2648
2649THREADED_TEST(EmbedderDataAlignedPointers) {
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002650 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00002651 v8::HandleScope scope(env->GetIsolate());
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002652
2653 CheckAlignedPointerInEmbedderData(&env, 0, NULL);
2654
2655 int* heap_allocated = new int[100];
2656 CheckAlignedPointerInEmbedderData(&env, 1, heap_allocated);
2657 delete[] heap_allocated;
2658
2659 int stack_allocated[100];
2660 CheckAlignedPointerInEmbedderData(&env, 2, stack_allocated);
2661
2662 void* huge = reinterpret_cast<void*>(~static_cast<uintptr_t>(1));
2663 CheckAlignedPointerInEmbedderData(&env, 3, huge);
2664
2665 // Test growing of the embedder data's backing store.
2666 for (int i = 0; i < 100; i++) {
2667 env->SetAlignedPointerInEmbedderData(i, AlignedTestPointer(i));
2668 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002669 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002670 for (int i = 0; i < 100; i++) {
2671 CHECK_EQ(AlignedTestPointer(i), env->GetAlignedPointerFromEmbedderData(i));
2672 }
2673}
2674
2675
2676static void CheckEmbedderData(LocalContext* env,
2677 int index,
2678 v8::Handle<Value> data) {
2679 (*env)->SetEmbedderData(index, data);
2680 CHECK((*env)->GetEmbedderData(index)->StrictEquals(data));
2681}
2682
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002683
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002684THREADED_TEST(EmbedderData) {
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002685 LocalContext env;
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002686 v8::Isolate* isolate = env->GetIsolate();
2687 v8::HandleScope scope(isolate);
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002688
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00002689 CheckEmbedderData(
2690 &env, 3,
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002691 v8::String::NewFromUtf8(isolate, "The quick brown fox jumps"));
2692 CheckEmbedderData(&env, 2, v8::String::NewFromUtf8(isolate,
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00002693 "over the lazy dog."));
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002694 CheckEmbedderData(&env, 1, v8::Number::New(isolate, 1.2345));
2695 CheckEmbedderData(&env, 0, v8::Boolean::New(isolate, true));
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002696}
2697
2698
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002699THREADED_TEST(IdentityHash) {
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002700 LocalContext env;
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002701 v8::Isolate* isolate = env->GetIsolate();
2702 v8::HandleScope scope(isolate);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002703
2704 // Ensure that the test starts with an fresh heap to test whether the hash
2705 // code is based on the address.
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002706 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002707 Local<v8::Object> obj = v8::Object::New(isolate);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002708 int hash = obj->GetIdentityHash();
2709 int hash1 = obj->GetIdentityHash();
2710 CHECK_EQ(hash, hash1);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002711 int hash2 = v8::Object::New(isolate)->GetIdentityHash();
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002712 // Since the identity hash is essentially a random number two consecutive
2713 // objects should not be assigned the same hash code. If the test below fails
2714 // the random number generator should be evaluated.
2715 CHECK_NE(hash, hash2);
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002716 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002717 int hash3 = v8::Object::New(isolate)->GetIdentityHash();
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002718 // Make sure that the identity hash is not based on the initial address of
2719 // the object alone. If the test below fails the random number generator
2720 // should be evaluated.
2721 CHECK_NE(hash, hash3);
2722 int hash4 = obj->GetIdentityHash();
2723 CHECK_EQ(hash, hash4);
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002724
2725 // Check identity hashes behaviour in the presence of JS accessors.
2726 // Put a getter for 'v8::IdentityHash' on the Object's prototype:
2727 {
2728 CompileRun("Object.prototype['v8::IdentityHash'] = 42;\n");
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002729 Local<v8::Object> o1 = v8::Object::New(isolate);
2730 Local<v8::Object> o2 = v8::Object::New(isolate);
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002731 CHECK_NE(o1->GetIdentityHash(), o2->GetIdentityHash());
2732 }
2733 {
2734 CompileRun(
2735 "function cnst() { return 42; };\n"
2736 "Object.prototype.__defineGetter__('v8::IdentityHash', cnst);\n");
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002737 Local<v8::Object> o1 = v8::Object::New(isolate);
2738 Local<v8::Object> o2 = v8::Object::New(isolate);
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002739 CHECK_NE(o1->GetIdentityHash(), o2->GetIdentityHash());
2740 }
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002741}
2742
2743
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002744THREADED_TEST(SymbolProperties) {
2745 i::FLAG_harmony_symbols = true;
2746
2747 LocalContext env;
2748 v8::Isolate* isolate = env->GetIsolate();
2749 v8::HandleScope scope(isolate);
2750
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002751 v8::Local<v8::Object> obj = v8::Object::New(isolate);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002752 v8::Local<v8::Symbol> sym1 = v8::Symbol::New(isolate);
2753 v8::Local<v8::Symbol> sym2 = v8::Symbol::New(isolate, "my-symbol");
2754
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002755 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002756
2757 // Check basic symbol functionality.
2758 CHECK(sym1->IsSymbol());
2759 CHECK(sym2->IsSymbol());
2760 CHECK(!obj->IsSymbol());
2761
2762 CHECK(sym1->Equals(sym1));
2763 CHECK(sym2->Equals(sym2));
2764 CHECK(!sym1->Equals(sym2));
2765 CHECK(!sym2->Equals(sym1));
2766 CHECK(sym1->StrictEquals(sym1));
2767 CHECK(sym2->StrictEquals(sym2));
2768 CHECK(!sym1->StrictEquals(sym2));
2769 CHECK(!sym2->StrictEquals(sym1));
2770
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00002771 CHECK(sym2->Name()->Equals(v8::String::NewFromUtf8(isolate, "my-symbol")));
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002772
2773 v8::Local<v8::Value> sym_val = sym2;
2774 CHECK(sym_val->IsSymbol());
2775 CHECK(sym_val->Equals(sym2));
2776 CHECK(sym_val->StrictEquals(sym2));
2777 CHECK(v8::Symbol::Cast(*sym_val)->Equals(sym2));
2778
2779 v8::Local<v8::Value> sym_obj = v8::SymbolObject::New(isolate, sym2);
2780 CHECK(sym_obj->IsSymbolObject());
2781 CHECK(!sym2->IsSymbolObject());
2782 CHECK(!obj->IsSymbolObject());
2783 CHECK(sym_obj->Equals(sym2));
2784 CHECK(!sym_obj->StrictEquals(sym2));
2785 CHECK(v8::SymbolObject::Cast(*sym_obj)->Equals(sym_obj));
danno@chromium.orgd3c42102013-08-01 16:58:23 +00002786 CHECK(v8::SymbolObject::Cast(*sym_obj)->ValueOf()->Equals(sym2));
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002787
2788 // Make sure delete of a non-existent symbol property works.
2789 CHECK(obj->Delete(sym1));
2790 CHECK(!obj->Has(sym1));
2791
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002792 CHECK(obj->Set(sym1, v8::Integer::New(isolate, 1503)));
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002793 CHECK(obj->Has(sym1));
2794 CHECK_EQ(1503, obj->Get(sym1)->Int32Value());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002795 CHECK(obj->Set(sym1, v8::Integer::New(isolate, 2002)));
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002796 CHECK(obj->Has(sym1));
2797 CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
2798 CHECK_EQ(v8::None, obj->GetPropertyAttributes(sym1));
2799
2800 CHECK_EQ(0, obj->GetOwnPropertyNames()->Length());
2801 int num_props = obj->GetPropertyNames()->Length();
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002802 CHECK(obj->Set(v8::String::NewFromUtf8(isolate, "bla"),
2803 v8::Integer::New(isolate, 20)));
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002804 CHECK_EQ(1, obj->GetOwnPropertyNames()->Length());
2805 CHECK_EQ(num_props + 1, obj->GetPropertyNames()->Length());
2806
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002807 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002808
2809 // Add another property and delete it afterwards to force the object in
2810 // slow case.
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002811 CHECK(obj->Set(sym2, v8::Integer::New(isolate, 2008)));
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002812 CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
2813 CHECK_EQ(2008, obj->Get(sym2)->Int32Value());
2814 CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
2815 CHECK_EQ(1, obj->GetOwnPropertyNames()->Length());
2816
2817 CHECK(obj->Has(sym1));
2818 CHECK(obj->Has(sym2));
2819 CHECK(obj->Delete(sym2));
2820 CHECK(obj->Has(sym1));
2821 CHECK(!obj->Has(sym2));
2822 CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
2823 CHECK_EQ(1, obj->GetOwnPropertyNames()->Length());
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00002824
2825 // Symbol properties are inherited.
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002826 v8::Local<v8::Object> child = v8::Object::New(isolate);
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00002827 child->SetPrototype(obj);
2828 CHECK(child->Has(sym1));
2829 CHECK_EQ(2002, child->Get(sym1)->Int32Value());
2830 CHECK_EQ(0, child->GetOwnPropertyNames()->Length());
2831}
2832
2833
2834THREADED_TEST(PrivateProperties) {
2835 LocalContext env;
2836 v8::Isolate* isolate = env->GetIsolate();
2837 v8::HandleScope scope(isolate);
2838
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002839 v8::Local<v8::Object> obj = v8::Object::New(isolate);
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00002840 v8::Local<v8::Private> priv1 = v8::Private::New(isolate);
2841 v8::Local<v8::Private> priv2 = v8::Private::New(isolate, "my-private");
2842
2843 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
2844
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00002845 CHECK(priv2->Name()->Equals(v8::String::NewFromUtf8(isolate, "my-private")));
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00002846
2847 // Make sure delete of a non-existent private symbol property works.
2848 CHECK(obj->DeletePrivate(priv1));
2849 CHECK(!obj->HasPrivate(priv1));
2850
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002851 CHECK(obj->SetPrivate(priv1, v8::Integer::New(isolate, 1503)));
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00002852 CHECK(obj->HasPrivate(priv1));
2853 CHECK_EQ(1503, obj->GetPrivate(priv1)->Int32Value());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002854 CHECK(obj->SetPrivate(priv1, v8::Integer::New(isolate, 2002)));
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00002855 CHECK(obj->HasPrivate(priv1));
2856 CHECK_EQ(2002, obj->GetPrivate(priv1)->Int32Value());
2857
2858 CHECK_EQ(0, obj->GetOwnPropertyNames()->Length());
2859 int num_props = obj->GetPropertyNames()->Length();
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002860 CHECK(obj->Set(v8::String::NewFromUtf8(isolate, "bla"),
2861 v8::Integer::New(isolate, 20)));
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00002862 CHECK_EQ(1, obj->GetOwnPropertyNames()->Length());
2863 CHECK_EQ(num_props + 1, obj->GetPropertyNames()->Length());
2864
2865 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
2866
2867 // Add another property and delete it afterwards to force the object in
2868 // slow case.
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002869 CHECK(obj->SetPrivate(priv2, v8::Integer::New(isolate, 2008)));
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00002870 CHECK_EQ(2002, obj->GetPrivate(priv1)->Int32Value());
2871 CHECK_EQ(2008, obj->GetPrivate(priv2)->Int32Value());
2872 CHECK_EQ(2002, obj->GetPrivate(priv1)->Int32Value());
2873 CHECK_EQ(1, obj->GetOwnPropertyNames()->Length());
2874
2875 CHECK(obj->HasPrivate(priv1));
2876 CHECK(obj->HasPrivate(priv2));
2877 CHECK(obj->DeletePrivate(priv2));
2878 CHECK(obj->HasPrivate(priv1));
2879 CHECK(!obj->HasPrivate(priv2));
2880 CHECK_EQ(2002, obj->GetPrivate(priv1)->Int32Value());
2881 CHECK_EQ(1, obj->GetOwnPropertyNames()->Length());
2882
2883 // Private properties are inherited (for the time being).
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002884 v8::Local<v8::Object> child = v8::Object::New(isolate);
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00002885 child->SetPrototype(obj);
2886 CHECK(child->HasPrivate(priv1));
2887 CHECK_EQ(2002, child->GetPrivate(priv1)->Int32Value());
2888 CHECK_EQ(0, child->GetOwnPropertyNames()->Length());
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002889}
2890
2891
ulan@chromium.org837a67e2013-06-11 15:39:48 +00002892class ScopedArrayBufferContents {
2893 public:
2894 explicit ScopedArrayBufferContents(
2895 const v8::ArrayBuffer::Contents& contents)
2896 : contents_(contents) {}
2897 ~ScopedArrayBufferContents() { free(contents_.Data()); }
2898 void* Data() const { return contents_.Data(); }
2899 size_t ByteLength() const { return contents_.ByteLength(); }
2900 private:
2901 const v8::ArrayBuffer::Contents contents_;
2902};
2903
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002904template <typename T>
2905static void CheckInternalFieldsAreZero(v8::Handle<T> value) {
2906 CHECK_EQ(T::kInternalFieldCount, value->InternalFieldCount());
2907 for (int i = 0; i < value->InternalFieldCount(); i++) {
2908 CHECK_EQ(0, value->GetInternalField(i)->Int32Value());
2909 }
2910}
2911
ulan@chromium.org837a67e2013-06-11 15:39:48 +00002912
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002913THREADED_TEST(ArrayBuffer_ApiInternalToExternal) {
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002914 LocalContext env;
2915 v8::Isolate* isolate = env->GetIsolate();
2916 v8::HandleScope handle_scope(isolate);
2917
machenbach@chromium.org9f18d912013-11-28 13:42:41 +00002918 Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, 1024);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002919 CheckInternalFieldsAreZero(ab);
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002920 CHECK_EQ(1024, static_cast<int>(ab->ByteLength()));
2921 CHECK(!ab->IsExternal());
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002922 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002923
ulan@chromium.org837a67e2013-06-11 15:39:48 +00002924 ScopedArrayBufferContents ab_contents(ab->Externalize());
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002925 CHECK(ab->IsExternal());
2926
2927 CHECK_EQ(1024, static_cast<int>(ab_contents.ByteLength()));
2928 uint8_t* data = static_cast<uint8_t*>(ab_contents.Data());
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002929 ASSERT(data != NULL);
2930 env->Global()->Set(v8_str("ab"), ab);
2931
2932 v8::Handle<v8::Value> result = CompileRun("ab.byteLength");
2933 CHECK_EQ(1024, result->Int32Value());
2934
danno@chromium.orgf005df62013-04-30 16:36:45 +00002935 result = CompileRun("var u8 = new Uint8Array(ab);"
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002936 "u8[0] = 0xFF;"
2937 "u8[1] = 0xAA;"
2938 "u8.length");
2939 CHECK_EQ(1024, result->Int32Value());
2940 CHECK_EQ(0xFF, data[0]);
2941 CHECK_EQ(0xAA, data[1]);
2942 data[0] = 0xCC;
2943 data[1] = 0x11;
2944 result = CompileRun("u8[0] + u8[1]");
2945 CHECK_EQ(0xDD, result->Int32Value());
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002946}
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002947
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002948
2949THREADED_TEST(ArrayBuffer_JSInternalToExternal) {
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002950 LocalContext env;
2951 v8::Isolate* isolate = env->GetIsolate();
2952 v8::HandleScope handle_scope(isolate);
2953
2954
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00002955 v8::Local<v8::Value> result =
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002956 CompileRun("var ab1 = new ArrayBuffer(2);"
2957 "var u8_a = new Uint8Array(ab1);"
2958 "u8_a[0] = 0xAA;"
2959 "u8_a[1] = 0xFF; u8_a.buffer");
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00002960 Local<v8::ArrayBuffer> ab1 = Local<v8::ArrayBuffer>::Cast(result);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002961 CheckInternalFieldsAreZero(ab1);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002962 CHECK_EQ(2, static_cast<int>(ab1->ByteLength()));
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002963 CHECK(!ab1->IsExternal());
ulan@chromium.org837a67e2013-06-11 15:39:48 +00002964 ScopedArrayBufferContents ab1_contents(ab1->Externalize());
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002965 CHECK(ab1->IsExternal());
2966
2967 result = CompileRun("ab1.byteLength");
2968 CHECK_EQ(2, result->Int32Value());
2969 result = CompileRun("u8_a[0]");
2970 CHECK_EQ(0xAA, result->Int32Value());
2971 result = CompileRun("u8_a[1]");
2972 CHECK_EQ(0xFF, result->Int32Value());
2973 result = CompileRun("var u8_b = new Uint8Array(ab1);"
2974 "u8_b[0] = 0xBB;"
2975 "u8_a[0]");
2976 CHECK_EQ(0xBB, result->Int32Value());
2977 result = CompileRun("u8_b[1]");
2978 CHECK_EQ(0xFF, result->Int32Value());
2979
2980 CHECK_EQ(2, static_cast<int>(ab1_contents.ByteLength()));
2981 uint8_t* ab1_data = static_cast<uint8_t*>(ab1_contents.Data());
2982 CHECK_EQ(0xBB, ab1_data[0]);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002983 CHECK_EQ(0xFF, ab1_data[1]);
2984 ab1_data[0] = 0xCC;
2985 ab1_data[1] = 0x11;
2986 result = CompileRun("u8_a[0] + u8_a[1]");
2987 CHECK_EQ(0xDD, result->Int32Value());
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002988}
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002989
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002990
2991THREADED_TEST(ArrayBuffer_External) {
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002992 LocalContext env;
2993 v8::Isolate* isolate = env->GetIsolate();
2994 v8::HandleScope handle_scope(isolate);
2995
2996 i::ScopedVector<uint8_t> my_data(100);
2997 memset(my_data.start(), 0, 100);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +00002998 Local<v8::ArrayBuffer> ab3 =
2999 v8::ArrayBuffer::New(isolate, my_data.start(), 100);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00003000 CheckInternalFieldsAreZero(ab3);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003001 CHECK_EQ(100, static_cast<int>(ab3->ByteLength()));
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00003002 CHECK(ab3->IsExternal());
3003
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003004 env->Global()->Set(v8_str("ab3"), ab3);
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00003005
3006 v8::Handle<v8::Value> result = CompileRun("ab3.byteLength");
3007 CHECK_EQ(100, result->Int32Value());
3008
danno@chromium.orgf005df62013-04-30 16:36:45 +00003009 result = CompileRun("var u8_b = new Uint8Array(ab3);"
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003010 "u8_b[0] = 0xBB;"
3011 "u8_b[1] = 0xCC;"
3012 "u8_b.length");
3013 CHECK_EQ(100, result->Int32Value());
3014 CHECK_EQ(0xBB, my_data[0]);
3015 CHECK_EQ(0xCC, my_data[1]);
3016 my_data[0] = 0xCC;
3017 my_data[1] = 0x11;
3018 result = CompileRun("u8_b[0] + u8_b[1]");
3019 CHECK_EQ(0xDD, result->Int32Value());
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003020}
3021
3022
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003023static void CheckDataViewIsNeutered(v8::Handle<v8::DataView> dv) {
3024 CHECK_EQ(0, static_cast<int>(dv->ByteLength()));
3025 CHECK_EQ(0, static_cast<int>(dv->ByteOffset()));
3026}
3027
3028
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003029static void CheckIsNeutered(v8::Handle<v8::TypedArray> ta) {
3030 CHECK_EQ(0, static_cast<int>(ta->ByteLength()));
3031 CHECK_EQ(0, static_cast<int>(ta->Length()));
3032 CHECK_EQ(0, static_cast<int>(ta->ByteOffset()));
3033}
3034
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003035
3036static void CheckIsTypedArrayVarNeutered(const char* name) {
3037 i::ScopedVector<char> source(1024);
3038 i::OS::SNPrintF(source,
3039 "%s.byteLength == 0 && %s.byteOffset == 0 && %s.length == 0",
3040 name, name, name);
3041 CHECK(CompileRun(source.start())->IsTrue());
3042 v8::Handle<v8::TypedArray> ta =
3043 v8::Handle<v8::TypedArray>::Cast(CompileRun(name));
3044 CheckIsNeutered(ta);
3045}
3046
3047
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003048template <typename TypedArray, int kElementSize>
3049static Handle<TypedArray> CreateAndCheck(Handle<v8::ArrayBuffer> ab,
3050 int byteOffset,
3051 int length) {
3052 v8::Handle<TypedArray> ta = TypedArray::New(ab, byteOffset, length);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00003053 CheckInternalFieldsAreZero<v8::ArrayBufferView>(ta);
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003054 CHECK_EQ(byteOffset, static_cast<int>(ta->ByteOffset()));
3055 CHECK_EQ(length, static_cast<int>(ta->Length()));
3056 CHECK_EQ(length * kElementSize, static_cast<int>(ta->ByteLength()));
3057 return ta;
3058}
3059
3060
3061THREADED_TEST(ArrayBuffer_NeuteringApi) {
3062 LocalContext env;
3063 v8::Isolate* isolate = env->GetIsolate();
3064 v8::HandleScope handle_scope(isolate);
3065
machenbach@chromium.org9f18d912013-11-28 13:42:41 +00003066 v8::Handle<v8::ArrayBuffer> buffer = v8::ArrayBuffer::New(isolate, 1024);
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003067
3068 v8::Handle<v8::Uint8Array> u8a =
3069 CreateAndCheck<v8::Uint8Array, 1>(buffer, 1, 1023);
3070 v8::Handle<v8::Uint8ClampedArray> u8c =
3071 CreateAndCheck<v8::Uint8ClampedArray, 1>(buffer, 1, 1023);
3072 v8::Handle<v8::Int8Array> i8a =
3073 CreateAndCheck<v8::Int8Array, 1>(buffer, 1, 1023);
3074
3075 v8::Handle<v8::Uint16Array> u16a =
3076 CreateAndCheck<v8::Uint16Array, 2>(buffer, 2, 511);
3077 v8::Handle<v8::Int16Array> i16a =
3078 CreateAndCheck<v8::Int16Array, 2>(buffer, 2, 511);
3079
3080 v8::Handle<v8::Uint32Array> u32a =
3081 CreateAndCheck<v8::Uint32Array, 4>(buffer, 4, 255);
3082 v8::Handle<v8::Int32Array> i32a =
3083 CreateAndCheck<v8::Int32Array, 4>(buffer, 4, 255);
3084
3085 v8::Handle<v8::Float32Array> f32a =
3086 CreateAndCheck<v8::Float32Array, 4>(buffer, 4, 255);
3087 v8::Handle<v8::Float64Array> f64a =
3088 CreateAndCheck<v8::Float64Array, 8>(buffer, 8, 127);
3089
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003090 v8::Handle<v8::DataView> dv = v8::DataView::New(buffer, 1, 1023);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00003091 CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003092 CHECK_EQ(1, static_cast<int>(dv->ByteOffset()));
3093 CHECK_EQ(1023, static_cast<int>(dv->ByteLength()));
3094
ulan@chromium.org837a67e2013-06-11 15:39:48 +00003095 ScopedArrayBufferContents contents(buffer->Externalize());
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003096 buffer->Neuter();
3097 CHECK_EQ(0, static_cast<int>(buffer->ByteLength()));
3098 CheckIsNeutered(u8a);
3099 CheckIsNeutered(u8c);
3100 CheckIsNeutered(i8a);
3101 CheckIsNeutered(u16a);
3102 CheckIsNeutered(i16a);
3103 CheckIsNeutered(u32a);
3104 CheckIsNeutered(i32a);
3105 CheckIsNeutered(f32a);
3106 CheckIsNeutered(f64a);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003107 CheckDataViewIsNeutered(dv);
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003108}
3109
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00003110
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003111THREADED_TEST(ArrayBuffer_NeuteringScript) {
3112 LocalContext env;
3113 v8::Isolate* isolate = env->GetIsolate();
3114 v8::HandleScope handle_scope(isolate);
3115
3116 CompileRun(
3117 "var ab = new ArrayBuffer(1024);"
3118 "var u8a = new Uint8Array(ab, 1, 1023);"
3119 "var u8c = new Uint8ClampedArray(ab, 1, 1023);"
3120 "var i8a = new Int8Array(ab, 1, 1023);"
3121 "var u16a = new Uint16Array(ab, 2, 511);"
3122 "var i16a = new Int16Array(ab, 2, 511);"
3123 "var u32a = new Uint32Array(ab, 4, 255);"
3124 "var i32a = new Int32Array(ab, 4, 255);"
3125 "var f32a = new Float32Array(ab, 4, 255);"
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003126 "var f64a = new Float64Array(ab, 8, 127);"
3127 "var dv = new DataView(ab, 1, 1023);");
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003128
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00003129 v8::Handle<v8::ArrayBuffer> ab =
3130 Local<v8::ArrayBuffer>::Cast(CompileRun("ab"));
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003131
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003132 v8::Handle<v8::DataView> dv =
3133 v8::Handle<v8::DataView>::Cast(CompileRun("dv"));
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003134
ulan@chromium.org837a67e2013-06-11 15:39:48 +00003135 ScopedArrayBufferContents contents(ab->Externalize());
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003136 ab->Neuter();
3137 CHECK_EQ(0, static_cast<int>(ab->ByteLength()));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003138 CHECK_EQ(0, CompileRun("ab.byteLength")->Int32Value());
3139
3140 CheckIsTypedArrayVarNeutered("u8a");
3141 CheckIsTypedArrayVarNeutered("u8c");
3142 CheckIsTypedArrayVarNeutered("i8a");
3143 CheckIsTypedArrayVarNeutered("u16a");
3144 CheckIsTypedArrayVarNeutered("i16a");
3145 CheckIsTypedArrayVarNeutered("u32a");
3146 CheckIsTypedArrayVarNeutered("i32a");
3147 CheckIsTypedArrayVarNeutered("f32a");
3148 CheckIsTypedArrayVarNeutered("f64a");
3149
3150 CHECK(CompileRun("dv.byteLength == 0 && dv.byteOffset == 0")->IsTrue());
3151 CheckDataViewIsNeutered(dv);
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003152}
3153
3154
3155
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003156THREADED_TEST(HiddenProperties) {
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003157 LocalContext env;
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003158 v8::Isolate* isolate = env->GetIsolate();
3159 v8::HandleScope scope(isolate);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003160
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003161 v8::Local<v8::Object> obj = v8::Object::New(env->GetIsolate());
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003162 v8::Local<v8::String> key = v8_str("api-test::hidden-key");
3163 v8::Local<v8::String> empty = v8_str("");
3164 v8::Local<v8::String> prop_name = v8_str("prop_name");
3165
machenbach@chromium.org528ce022013-09-23 14:09:36 +00003166 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003167
kasperl@chromium.orgacae3782009-04-11 09:17:08 +00003168 // Make sure delete of a non-existent hidden value works
3169 CHECK(obj->DeleteHiddenValue(key));
3170
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003171 CHECK(obj->SetHiddenValue(key, v8::Integer::New(isolate, 1503)));
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003172 CHECK_EQ(1503, obj->GetHiddenValue(key)->Int32Value());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003173 CHECK(obj->SetHiddenValue(key, v8::Integer::New(isolate, 2002)));
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003174 CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
3175
machenbach@chromium.org528ce022013-09-23 14:09:36 +00003176 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003177
3178 // Make sure we do not find the hidden property.
3179 CHECK(!obj->Has(empty));
3180 CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
3181 CHECK(obj->Get(empty)->IsUndefined());
3182 CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003183 CHECK(obj->Set(empty, v8::Integer::New(isolate, 2003)));
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003184 CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
3185 CHECK_EQ(2003, obj->Get(empty)->Int32Value());
3186
machenbach@chromium.org528ce022013-09-23 14:09:36 +00003187 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003188
3189 // Add another property and delete it afterwards to force the object in
3190 // slow case.
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003191 CHECK(obj->Set(prop_name, v8::Integer::New(isolate, 2008)));
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003192 CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
3193 CHECK_EQ(2008, obj->Get(prop_name)->Int32Value());
3194 CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
3195 CHECK(obj->Delete(prop_name));
3196 CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
3197
machenbach@chromium.org528ce022013-09-23 14:09:36 +00003198 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003199
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00003200 CHECK(obj->SetHiddenValue(key, Handle<Value>()));
3201 CHECK(obj->GetHiddenValue(key).IsEmpty());
3202
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003203 CHECK(obj->SetHiddenValue(key, v8::Integer::New(isolate, 2002)));
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003204 CHECK(obj->DeleteHiddenValue(key));
3205 CHECK(obj->GetHiddenValue(key).IsEmpty());
3206}
3207
3208
ricow@chromium.org9fe9cdf2011-09-27 08:04:16 +00003209THREADED_TEST(Regress97784) {
3210 // Regression test for crbug.com/97784
3211 // Messing with the Object.prototype should not have effect on
3212 // hidden properties.
ricow@chromium.org9fe9cdf2011-09-27 08:04:16 +00003213 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003214 v8::HandleScope scope(env->GetIsolate());
ricow@chromium.org9fe9cdf2011-09-27 08:04:16 +00003215
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003216 v8::Local<v8::Object> obj = v8::Object::New(env->GetIsolate());
ricow@chromium.org9fe9cdf2011-09-27 08:04:16 +00003217 v8::Local<v8::String> key = v8_str("hidden");
3218
3219 CompileRun(
3220 "set_called = false;"
3221 "Object.defineProperty("
3222 " Object.prototype,"
3223 " 'hidden',"
3224 " {get: function() { return 45; },"
3225 " set: function() { set_called = true; }})");
3226
3227 CHECK(obj->GetHiddenValue(key).IsEmpty());
3228 // Make sure that the getter and setter from Object.prototype is not invoked.
3229 // If it did we would have full access to the hidden properties in
3230 // the accessor.
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003231 CHECK(obj->SetHiddenValue(key, v8::Integer::New(env->GetIsolate(), 42)));
ricow@chromium.org9fe9cdf2011-09-27 08:04:16 +00003232 ExpectFalse("set_called");
3233 CHECK_EQ(42, obj->GetHiddenValue(key)->Int32Value());
3234}
3235
3236
ager@chromium.orgc4c92722009-11-18 14:12:51 +00003237static bool interceptor_for_hidden_properties_called;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003238static void InterceptorForHiddenProperties(
3239 Local<String> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.orgc4c92722009-11-18 14:12:51 +00003240 interceptor_for_hidden_properties_called = true;
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00003241}
3242
3243
3244THREADED_TEST(HiddenPropertiesWithInterceptors) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00003245 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00003246 v8::Isolate* isolate = context->GetIsolate();
3247 v8::HandleScope scope(isolate);
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00003248
ager@chromium.orgc4c92722009-11-18 14:12:51 +00003249 interceptor_for_hidden_properties_called = false;
3250
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00003251 v8::Local<v8::String> key = v8_str("api-test::hidden-key");
3252
3253 // Associate an interceptor with an object and start setting hidden values.
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00003254 Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(isolate);
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00003255 Local<v8::ObjectTemplate> instance_templ = fun_templ->InstanceTemplate();
3256 instance_templ->SetNamedPropertyHandler(InterceptorForHiddenProperties);
3257 Local<v8::Function> function = fun_templ->GetFunction();
3258 Local<v8::Object> obj = function->NewInstance();
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003259 CHECK(obj->SetHiddenValue(key, v8::Integer::New(isolate, 2302)));
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00003260 CHECK_EQ(2302, obj->GetHiddenValue(key)->Int32Value());
ager@chromium.orgc4c92722009-11-18 14:12:51 +00003261 CHECK(!interceptor_for_hidden_properties_called);
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00003262}
3263
3264
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003265THREADED_TEST(External) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00003266 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003267 int x = 3;
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00003268 Local<v8::External> ext = v8::External::New(CcTest::isolate(), &x);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003269 LocalContext env;
3270 env->Global()->Set(v8_str("ext"), ext);
3271 Local<Value> reext_obj = Script::Compile(v8_str("this.ext"))->Run();
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00003272 v8::Handle<v8::External> reext = reext_obj.As<v8::External>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003273 int* ptr = static_cast<int*>(reext->Value());
3274 CHECK_EQ(x, 3);
3275 *ptr = 10;
3276 CHECK_EQ(x, 10);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00003277
3278 // Make sure unaligned pointers are wrapped properly.
3279 char* data = i::StrDup("0123456789");
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00003280 Local<v8::Value> zero = v8::External::New(CcTest::isolate(), &data[0]);
3281 Local<v8::Value> one = v8::External::New(CcTest::isolate(), &data[1]);
3282 Local<v8::Value> two = v8::External::New(CcTest::isolate(), &data[2]);
3283 Local<v8::Value> three = v8::External::New(CcTest::isolate(), &data[3]);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00003284
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00003285 char* char_ptr = reinterpret_cast<char*>(v8::External::Cast(*zero)->Value());
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00003286 CHECK_EQ('0', *char_ptr);
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00003287 char_ptr = reinterpret_cast<char*>(v8::External::Cast(*one)->Value());
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00003288 CHECK_EQ('1', *char_ptr);
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00003289 char_ptr = reinterpret_cast<char*>(v8::External::Cast(*two)->Value());
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00003290 CHECK_EQ('2', *char_ptr);
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00003291 char_ptr = reinterpret_cast<char*>(v8::External::Cast(*three)->Value());
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00003292 CHECK_EQ('3', *char_ptr);
3293 i::DeleteArray(data);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003294}
3295
3296
3297THREADED_TEST(GlobalHandle) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00003298 v8::Isolate* isolate = CcTest::isolate();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003299 v8::Persistent<String> global;
3300 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003301 v8::HandleScope scope(isolate);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003302 global.Reset(isolate, v8_str("str"));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003303 }
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00003304 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003305 v8::HandleScope scope(isolate);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003306 CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00003307 }
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00003308 global.Reset();
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003309 {
3310 v8::HandleScope scope(isolate);
3311 global.Reset(isolate, v8_str("str"));
3312 }
3313 {
3314 v8::HandleScope scope(isolate);
3315 CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
3316 }
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00003317 global.Reset();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003318}
3319
3320
ulan@chromium.org57ff8812013-05-10 08:16:55 +00003321THREADED_TEST(ResettingGlobalHandle) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00003322 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00003323 v8::Persistent<String> global;
3324 {
3325 v8::HandleScope scope(isolate);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003326 global.Reset(isolate, v8_str("str"));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00003327 }
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003328 v8::internal::GlobalHandles* global_handles =
3329 reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003330 int initial_handle_count = global_handles->global_handles_count();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00003331 {
3332 v8::HandleScope scope(isolate);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003333 CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00003334 }
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003335 {
3336 v8::HandleScope scope(isolate);
3337 global.Reset(isolate, v8_str("longer"));
3338 }
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003339 CHECK_EQ(global_handles->global_handles_count(), initial_handle_count);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003340 {
3341 v8::HandleScope scope(isolate);
3342 CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 6);
3343 }
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00003344 global.Reset();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003345 CHECK_EQ(global_handles->global_handles_count(), initial_handle_count - 1);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00003346}
3347
3348
3349THREADED_TEST(ResettingGlobalHandleToEmpty) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00003350 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00003351 v8::Persistent<String> global;
3352 {
3353 v8::HandleScope scope(isolate);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003354 global.Reset(isolate, v8_str("str"));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00003355 }
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003356 v8::internal::GlobalHandles* global_handles =
3357 reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003358 int initial_handle_count = global_handles->global_handles_count();
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003359 {
3360 v8::HandleScope scope(isolate);
3361 CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
3362 }
ulan@chromium.org57ff8812013-05-10 08:16:55 +00003363 {
3364 v8::HandleScope scope(isolate);
3365 Local<String> empty;
3366 global.Reset(isolate, empty);
3367 }
3368 CHECK(global.IsEmpty());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003369 CHECK_EQ(global_handles->global_handles_count(), initial_handle_count - 1);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00003370}
3371
3372
machenbach@chromium.orgc86e8c22013-11-27 15:11:04 +00003373template<class T>
3374static v8::UniquePersistent<T> PassUnique(v8::UniquePersistent<T> unique) {
3375 return unique.Pass();
3376}
3377
3378
3379template<class T>
3380static v8::UniquePersistent<T> ReturnUnique(v8::Isolate* isolate,
3381 const v8::Persistent<T> & global) {
3382 v8::UniquePersistent<String> unique(isolate, global);
3383 return unique.Pass();
3384}
3385
3386
3387THREADED_TEST(UniquePersistent) {
3388 v8::Isolate* isolate = CcTest::isolate();
3389 v8::Persistent<String> global;
3390 {
3391 v8::HandleScope scope(isolate);
3392 global.Reset(isolate, v8_str("str"));
3393 }
3394 v8::internal::GlobalHandles* global_handles =
3395 reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
3396 int initial_handle_count = global_handles->global_handles_count();
3397 {
3398 v8::UniquePersistent<String> unique(isolate, global);
3399 CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
3400 // Test assignment via Pass
3401 {
3402 v8::UniquePersistent<String> copy = unique.Pass();
3403 CHECK(unique.IsEmpty());
3404 CHECK(copy == global);
3405 CHECK_EQ(initial_handle_count + 1,
3406 global_handles->global_handles_count());
3407 unique = copy.Pass();
3408 }
3409 // Test ctor via Pass
3410 {
3411 v8::UniquePersistent<String> copy(unique.Pass());
3412 CHECK(unique.IsEmpty());
3413 CHECK(copy == global);
3414 CHECK_EQ(initial_handle_count + 1,
3415 global_handles->global_handles_count());
3416 unique = copy.Pass();
3417 }
3418 // Test pass through function call
3419 {
3420 v8::UniquePersistent<String> copy = PassUnique(unique.Pass());
3421 CHECK(unique.IsEmpty());
3422 CHECK(copy == global);
3423 CHECK_EQ(initial_handle_count + 1,
3424 global_handles->global_handles_count());
3425 unique = copy.Pass();
3426 }
3427 CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
3428 }
3429 // Test pass from function call
3430 {
3431 v8::UniquePersistent<String> unique = ReturnUnique(isolate, global);
3432 CHECK(unique == global);
3433 CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
3434 }
3435 CHECK_EQ(initial_handle_count, global_handles->global_handles_count());
3436 global.Reset();
3437}
3438
3439
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003440THREADED_TEST(GlobalHandleUpcast) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00003441 v8::Isolate* isolate = CcTest::isolate();
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003442 v8::HandleScope scope(isolate);
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00003443 v8::Local<String> local = v8::Local<String>::New(isolate, v8_str("str"));
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003444 v8::Persistent<String> global_string(isolate, local);
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003445 v8::Persistent<Value>& global_value =
3446 v8::Persistent<Value>::Cast(global_string);
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003447 CHECK(v8::Local<v8::Value>::New(isolate, global_value)->IsString());
3448 CHECK(global_string == v8::Persistent<String>::Cast(global_value));
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00003449 global_string.Reset();
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003450}
3451
3452
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +00003453THREADED_TEST(HandleEquality) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00003454 v8::Isolate* isolate = CcTest::isolate();
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +00003455 v8::Persistent<String> global1;
3456 v8::Persistent<String> global2;
3457 {
3458 v8::HandleScope scope(isolate);
3459 global1.Reset(isolate, v8_str("str"));
3460 global2.Reset(isolate, v8_str("str2"));
3461 }
3462 CHECK_EQ(global1 == global1, true);
3463 CHECK_EQ(global1 != global1, false);
3464 {
3465 v8::HandleScope scope(isolate);
3466 Local<String> local1 = Local<String>::New(isolate, global1);
3467 Local<String> local2 = Local<String>::New(isolate, global2);
3468
3469 CHECK_EQ(global1 == local1, true);
3470 CHECK_EQ(global1 != local1, false);
3471 CHECK_EQ(local1 == global1, true);
3472 CHECK_EQ(local1 != global1, false);
3473
3474 CHECK_EQ(global1 == local2, false);
3475 CHECK_EQ(global1 != local2, true);
3476 CHECK_EQ(local2 == global1, false);
3477 CHECK_EQ(local2 != global1, true);
3478
3479 CHECK_EQ(local1 == local2, false);
3480 CHECK_EQ(local1 != local2, true);
3481
3482 Local<String> anotherLocal1 = Local<String>::New(isolate, global1);
3483 CHECK_EQ(local1 == anotherLocal1, true);
3484 CHECK_EQ(local1 != anotherLocal1, false);
3485 }
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00003486 global1.Reset();
3487 global2.Reset();
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +00003488}
3489
3490
mstarzinger@chromium.org32280cf2012-12-06 17:32:37 +00003491THREADED_TEST(LocalHandle) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00003492 v8::HandleScope scope(CcTest::isolate());
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00003493 v8::Local<String> local =
3494 v8::Local<String>::New(CcTest::isolate(), v8_str("str"));
mstarzinger@chromium.org32280cf2012-12-06 17:32:37 +00003495 CHECK_EQ(local->Length(), 3);
3496}
3497
3498
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00003499class WeakCallCounter {
3500 public:
3501 explicit WeakCallCounter(int id) : id_(id), number_of_weak_calls_(0) { }
3502 int id() { return id_; }
3503 void increment() { number_of_weak_calls_++; }
3504 int NumberOfWeakCalls() { return number_of_weak_calls_; }
3505 private:
3506 int id_;
3507 int number_of_weak_calls_;
3508};
3509
3510
mstarzinger@chromium.org69008382013-10-18 10:34:25 +00003511template<typename T>
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003512struct WeakCallCounterAndPersistent {
3513 explicit WeakCallCounterAndPersistent(WeakCallCounter* counter)
3514 : counter(counter) {}
3515 WeakCallCounter* counter;
3516 v8::Persistent<T> handle;
3517};
3518
3519
3520template <typename T>
3521static void WeakPointerCallback(
3522 const v8::WeakCallbackData<T, WeakCallCounterAndPersistent<T> >& data) {
3523 CHECK_EQ(1234, data.GetParameter()->counter->id());
3524 data.GetParameter()->counter->increment();
3525 data.GetParameter()->handle.Reset();
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00003526}
3527
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00003528
mstarzinger@chromium.org69008382013-10-18 10:34:25 +00003529template<typename T>
3530static UniqueId MakeUniqueId(const Persistent<T>& p) {
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00003531 return UniqueId(reinterpret_cast<uintptr_t>(*v8::Utils::OpenPersistent(p)));
3532}
3533
3534
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003535THREADED_TEST(ApiObjectGroups) {
3536 LocalContext env;
3537 v8::Isolate* iso = env->GetIsolate();
3538 HandleScope scope(iso);
3539
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003540 WeakCallCounter counter(1234);
3541
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003542 WeakCallCounterAndPersistent<Value> g1s1(&counter);
3543 WeakCallCounterAndPersistent<Value> g1s2(&counter);
3544 WeakCallCounterAndPersistent<Value> g1c1(&counter);
3545 WeakCallCounterAndPersistent<Value> g2s1(&counter);
3546 WeakCallCounterAndPersistent<Value> g2s2(&counter);
3547 WeakCallCounterAndPersistent<Value> g2c1(&counter);
3548
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003549 {
3550 HandleScope scope(iso);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003551 g1s1.handle.Reset(iso, Object::New(iso));
3552 g1s2.handle.Reset(iso, Object::New(iso));
3553 g1c1.handle.Reset(iso, Object::New(iso));
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003554 g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback);
3555 g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback);
3556 g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003557
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003558 g2s1.handle.Reset(iso, Object::New(iso));
3559 g2s2.handle.Reset(iso, Object::New(iso));
3560 g2c1.handle.Reset(iso, Object::New(iso));
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003561 g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback);
3562 g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback);
3563 g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003564 }
3565
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003566 WeakCallCounterAndPersistent<Value> root(&counter);
3567 root.handle.Reset(iso, g1s1.handle); // make a root.
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003568
3569 // Connect group 1 and 2, make a cycle.
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003570 {
3571 HandleScope scope(iso);
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003572 CHECK(Local<Object>::New(iso, g1s2.handle.As<Object>())->
3573 Set(0, Local<Value>::New(iso, g2s2.handle)));
3574 CHECK(Local<Object>::New(iso, g2s1.handle.As<Object>())->
3575 Set(0, Local<Value>::New(iso, g1s1.handle)));
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003576 }
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003577
3578 {
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003579 UniqueId id1 = MakeUniqueId(g1s1.handle);
3580 UniqueId id2 = MakeUniqueId(g2s2.handle);
3581 iso->SetObjectGroupId(g1s1.handle, id1);
3582 iso->SetObjectGroupId(g1s2.handle, id1);
3583 iso->SetReferenceFromGroup(id1, g1c1.handle);
3584 iso->SetObjectGroupId(g2s1.handle, id2);
3585 iso->SetObjectGroupId(g2s2.handle, id2);
3586 iso->SetReferenceFromGroup(id2, g2c1.handle);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003587 }
3588 // Do a single full GC, ensure incremental marking is stopped.
3589 v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>(
3590 iso)->heap();
3591 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
3592
3593 // All object should be alive.
3594 CHECK_EQ(0, counter.NumberOfWeakCalls());
3595
3596 // Weaken the root.
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003597 root.handle.SetWeak(&root, &WeakPointerCallback);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003598 // But make children strong roots---all the objects (except for children)
3599 // should be collectable now.
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003600 g1c1.handle.ClearWeak();
3601 g2c1.handle.ClearWeak();
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003602
3603 // Groups are deleted, rebuild groups.
3604 {
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003605 UniqueId id1 = MakeUniqueId(g1s1.handle);
3606 UniqueId id2 = MakeUniqueId(g2s2.handle);
3607 iso->SetObjectGroupId(g1s1.handle, id1);
3608 iso->SetObjectGroupId(g1s2.handle, id1);
3609 iso->SetReferenceFromGroup(id1, g1c1.handle);
3610 iso->SetObjectGroupId(g2s1.handle, id2);
3611 iso->SetObjectGroupId(g2s2.handle, id2);
3612 iso->SetReferenceFromGroup(id2, g2c1.handle);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003613 }
3614
3615 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
3616
3617 // All objects should be gone. 5 global handles in total.
3618 CHECK_EQ(5, counter.NumberOfWeakCalls());
3619
3620 // And now make children weak again and collect them.
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003621 g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback);
3622 g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003623
3624 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
3625 CHECK_EQ(7, counter.NumberOfWeakCalls());
3626}
3627
3628
mstarzinger@chromium.org69008382013-10-18 10:34:25 +00003629THREADED_TEST(ApiObjectGroupsForSubtypes) {
3630 LocalContext env;
3631 v8::Isolate* iso = env->GetIsolate();
3632 HandleScope scope(iso);
3633
mstarzinger@chromium.org69008382013-10-18 10:34:25 +00003634 WeakCallCounter counter(1234);
3635
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003636 WeakCallCounterAndPersistent<Object> g1s1(&counter);
3637 WeakCallCounterAndPersistent<String> g1s2(&counter);
3638 WeakCallCounterAndPersistent<String> g1c1(&counter);
3639 WeakCallCounterAndPersistent<Object> g2s1(&counter);
3640 WeakCallCounterAndPersistent<String> g2s2(&counter);
3641 WeakCallCounterAndPersistent<String> g2c1(&counter);
3642
mstarzinger@chromium.org69008382013-10-18 10:34:25 +00003643 {
3644 HandleScope scope(iso);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003645 g1s1.handle.Reset(iso, Object::New(iso));
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003646 g1s2.handle.Reset(iso, String::NewFromUtf8(iso, "foo1"));
3647 g1c1.handle.Reset(iso, String::NewFromUtf8(iso, "foo2"));
3648 g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback);
3649 g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback);
3650 g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback);
mstarzinger@chromium.org69008382013-10-18 10:34:25 +00003651
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003652 g2s1.handle.Reset(iso, Object::New(iso));
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003653 g2s2.handle.Reset(iso, String::NewFromUtf8(iso, "foo3"));
3654 g2c1.handle.Reset(iso, String::NewFromUtf8(iso, "foo4"));
3655 g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback);
3656 g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback);
3657 g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback);
mstarzinger@chromium.org69008382013-10-18 10:34:25 +00003658 }
3659
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003660 WeakCallCounterAndPersistent<Value> root(&counter);
3661 root.handle.Reset(iso, g1s1.handle); // make a root.
mstarzinger@chromium.org69008382013-10-18 10:34:25 +00003662
3663 // Connect group 1 and 2, make a cycle.
3664 {
3665 HandleScope scope(iso);
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003666 CHECK(Local<Object>::New(iso, g1s1.handle)
3667 ->Set(0, Local<Object>::New(iso, g2s1.handle)));
3668 CHECK(Local<Object>::New(iso, g2s1.handle)
3669 ->Set(0, Local<Object>::New(iso, g1s1.handle)));
mstarzinger@chromium.org69008382013-10-18 10:34:25 +00003670 }
3671
3672 {
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003673 UniqueId id1 = MakeUniqueId(g1s1.handle);
3674 UniqueId id2 = MakeUniqueId(g2s2.handle);
3675 iso->SetObjectGroupId(g1s1.handle, id1);
3676 iso->SetObjectGroupId(g1s2.handle, id1);
3677 iso->SetReference(g1s1.handle, g1c1.handle);
3678 iso->SetObjectGroupId(g2s1.handle, id2);
3679 iso->SetObjectGroupId(g2s2.handle, id2);
3680 iso->SetReferenceFromGroup(id2, g2c1.handle);
mstarzinger@chromium.org69008382013-10-18 10:34:25 +00003681 }
3682 // Do a single full GC, ensure incremental marking is stopped.
3683 v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>(
3684 iso)->heap();
3685 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
3686
3687 // All object should be alive.
3688 CHECK_EQ(0, counter.NumberOfWeakCalls());
3689
3690 // Weaken the root.
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003691 root.handle.SetWeak(&root, &WeakPointerCallback);
mstarzinger@chromium.org69008382013-10-18 10:34:25 +00003692 // But make children strong roots---all the objects (except for children)
3693 // should be collectable now.
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003694 g1c1.handle.ClearWeak();
3695 g2c1.handle.ClearWeak();
mstarzinger@chromium.org69008382013-10-18 10:34:25 +00003696
3697 // Groups are deleted, rebuild groups.
3698 {
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003699 UniqueId id1 = MakeUniqueId(g1s1.handle);
3700 UniqueId id2 = MakeUniqueId(g2s2.handle);
3701 iso->SetObjectGroupId(g1s1.handle, id1);
3702 iso->SetObjectGroupId(g1s2.handle, id1);
3703 iso->SetReference(g1s1.handle, g1c1.handle);
3704 iso->SetObjectGroupId(g2s1.handle, id2);
3705 iso->SetObjectGroupId(g2s2.handle, id2);
3706 iso->SetReferenceFromGroup(id2, g2c1.handle);
mstarzinger@chromium.org69008382013-10-18 10:34:25 +00003707 }
3708
3709 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
3710
3711 // All objects should be gone. 5 global handles in total.
3712 CHECK_EQ(5, counter.NumberOfWeakCalls());
3713
3714 // And now make children weak again and collect them.
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003715 g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback);
3716 g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback);
mstarzinger@chromium.org69008382013-10-18 10:34:25 +00003717
3718 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
3719 CHECK_EQ(7, counter.NumberOfWeakCalls());
3720}
3721
3722
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003723THREADED_TEST(ApiObjectGroupsCycle) {
3724 LocalContext env;
3725 v8::Isolate* iso = env->GetIsolate();
3726 HandleScope scope(iso);
3727
3728 WeakCallCounter counter(1234);
3729
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003730 WeakCallCounterAndPersistent<Value> g1s1(&counter);
3731 WeakCallCounterAndPersistent<Value> g1s2(&counter);
3732 WeakCallCounterAndPersistent<Value> g2s1(&counter);
3733 WeakCallCounterAndPersistent<Value> g2s2(&counter);
3734 WeakCallCounterAndPersistent<Value> g3s1(&counter);
3735 WeakCallCounterAndPersistent<Value> g3s2(&counter);
3736 WeakCallCounterAndPersistent<Value> g4s1(&counter);
3737 WeakCallCounterAndPersistent<Value> g4s2(&counter);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003738
3739 {
3740 HandleScope scope(iso);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003741 g1s1.handle.Reset(iso, Object::New(iso));
3742 g1s2.handle.Reset(iso, Object::New(iso));
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003743 g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback);
3744 g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback);
3745 CHECK(g1s1.handle.IsWeak());
3746 CHECK(g1s2.handle.IsWeak());
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003747
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003748 g2s1.handle.Reset(iso, Object::New(iso));
3749 g2s2.handle.Reset(iso, Object::New(iso));
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003750 g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback);
3751 g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback);
3752 CHECK(g2s1.handle.IsWeak());
3753 CHECK(g2s2.handle.IsWeak());
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003754
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003755 g3s1.handle.Reset(iso, Object::New(iso));
3756 g3s2.handle.Reset(iso, Object::New(iso));
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003757 g3s1.handle.SetWeak(&g3s1, &WeakPointerCallback);
3758 g3s2.handle.SetWeak(&g3s2, &WeakPointerCallback);
3759 CHECK(g3s1.handle.IsWeak());
3760 CHECK(g3s2.handle.IsWeak());
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003761
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003762 g4s1.handle.Reset(iso, Object::New(iso));
3763 g4s2.handle.Reset(iso, Object::New(iso));
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003764 g4s1.handle.SetWeak(&g4s1, &WeakPointerCallback);
3765 g4s2.handle.SetWeak(&g4s2, &WeakPointerCallback);
3766 CHECK(g4s1.handle.IsWeak());
3767 CHECK(g4s2.handle.IsWeak());
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003768 }
3769
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003770 WeakCallCounterAndPersistent<Value> root(&counter);
3771 root.handle.Reset(iso, g1s1.handle); // make a root.
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003772
3773 // Connect groups. We're building the following cycle:
3774 // G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other
3775 // groups.
3776 {
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003777 UniqueId id1 = MakeUniqueId(g1s1.handle);
3778 UniqueId id2 = MakeUniqueId(g2s1.handle);
3779 UniqueId id3 = MakeUniqueId(g3s1.handle);
3780 UniqueId id4 = MakeUniqueId(g4s1.handle);
3781 iso->SetObjectGroupId(g1s1.handle, id1);
3782 iso->SetObjectGroupId(g1s2.handle, id1);
3783 iso->SetReferenceFromGroup(id1, g2s1.handle);
3784 iso->SetObjectGroupId(g2s1.handle, id2);
3785 iso->SetObjectGroupId(g2s2.handle, id2);
3786 iso->SetReferenceFromGroup(id2, g3s1.handle);
3787 iso->SetObjectGroupId(g3s1.handle, id3);
3788 iso->SetObjectGroupId(g3s2.handle, id3);
3789 iso->SetReferenceFromGroup(id3, g4s1.handle);
3790 iso->SetObjectGroupId(g4s1.handle, id4);
3791 iso->SetObjectGroupId(g4s2.handle, id4);
3792 iso->SetReferenceFromGroup(id4, g1s1.handle);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003793 }
3794 // Do a single full GC
3795 v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>(
3796 iso)->heap();
3797 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
3798
3799 // All object should be alive.
3800 CHECK_EQ(0, counter.NumberOfWeakCalls());
3801
3802 // Weaken the root.
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003803 root.handle.SetWeak(&root, &WeakPointerCallback);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003804
3805 // Groups are deleted, rebuild groups.
3806 {
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003807 UniqueId id1 = MakeUniqueId(g1s1.handle);
3808 UniqueId id2 = MakeUniqueId(g2s1.handle);
3809 UniqueId id3 = MakeUniqueId(g3s1.handle);
3810 UniqueId id4 = MakeUniqueId(g4s1.handle);
3811 iso->SetObjectGroupId(g1s1.handle, id1);
3812 iso->SetObjectGroupId(g1s2.handle, id1);
3813 iso->SetReferenceFromGroup(id1, g2s1.handle);
3814 iso->SetObjectGroupId(g2s1.handle, id2);
3815 iso->SetObjectGroupId(g2s2.handle, id2);
3816 iso->SetReferenceFromGroup(id2, g3s1.handle);
3817 iso->SetObjectGroupId(g3s1.handle, id3);
3818 iso->SetObjectGroupId(g3s2.handle, id3);
3819 iso->SetReferenceFromGroup(id3, g4s1.handle);
3820 iso->SetObjectGroupId(g4s1.handle, id4);
3821 iso->SetObjectGroupId(g4s2.handle, id4);
3822 iso->SetReferenceFromGroup(id4, g1s1.handle);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003823 }
3824
3825 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
3826
3827 // All objects should be gone. 9 global handles in total.
3828 CHECK_EQ(9, counter.NumberOfWeakCalls());
3829}
3830
3831
mvstanton@chromium.orge4ac3ef2012-11-12 14:53:34 +00003832// TODO(mstarzinger): This should be a THREADED_TEST but causes failures
3833// on the buildbots, so was made non-threaded for the time being.
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003834TEST(ApiObjectGroupsCycleForScavenger) {
3835 i::FLAG_stress_compaction = false;
3836 i::FLAG_gc_global = false;
3837 LocalContext env;
3838 v8::Isolate* iso = env->GetIsolate();
3839 HandleScope scope(iso);
3840
3841 WeakCallCounter counter(1234);
3842
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003843 WeakCallCounterAndPersistent<Value> g1s1(&counter);
3844 WeakCallCounterAndPersistent<Value> g1s2(&counter);
3845 WeakCallCounterAndPersistent<Value> g2s1(&counter);
3846 WeakCallCounterAndPersistent<Value> g2s2(&counter);
3847 WeakCallCounterAndPersistent<Value> g3s1(&counter);
3848 WeakCallCounterAndPersistent<Value> g3s2(&counter);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003849
3850 {
3851 HandleScope scope(iso);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003852 g1s1.handle.Reset(iso, Object::New(iso));
3853 g1s2.handle.Reset(iso, Object::New(iso));
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003854 g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback);
3855 g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003856
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003857 g2s1.handle.Reset(iso, Object::New(iso));
3858 g2s2.handle.Reset(iso, Object::New(iso));
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003859 g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback);
3860 g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003861
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003862 g3s1.handle.Reset(iso, Object::New(iso));
3863 g3s2.handle.Reset(iso, Object::New(iso));
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003864 g3s1.handle.SetWeak(&g3s1, &WeakPointerCallback);
3865 g3s2.handle.SetWeak(&g3s2, &WeakPointerCallback);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003866 }
3867
3868 // Make a root.
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003869 WeakCallCounterAndPersistent<Value> root(&counter);
3870 root.handle.Reset(iso, g1s1.handle);
3871 root.handle.MarkPartiallyDependent();
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003872
3873 // Connect groups. We're building the following cycle:
3874 // G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other
3875 // groups.
3876 {
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003877 HandleScope handle_scope(iso);
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003878 g1s1.handle.MarkPartiallyDependent();
3879 g1s2.handle.MarkPartiallyDependent();
3880 g2s1.handle.MarkPartiallyDependent();
3881 g2s2.handle.MarkPartiallyDependent();
3882 g3s1.handle.MarkPartiallyDependent();
3883 g3s2.handle.MarkPartiallyDependent();
3884 iso->SetObjectGroupId(g1s1.handle, UniqueId(1));
3885 iso->SetObjectGroupId(g1s2.handle, UniqueId(1));
3886 Local<Object>::New(iso, g1s1.handle.As<Object>())->Set(
3887 v8_str("x"), Local<Value>::New(iso, g2s1.handle));
3888 iso->SetObjectGroupId(g2s1.handle, UniqueId(2));
3889 iso->SetObjectGroupId(g2s2.handle, UniqueId(2));
3890 Local<Object>::New(iso, g2s1.handle.As<Object>())->Set(
3891 v8_str("x"), Local<Value>::New(iso, g3s1.handle));
3892 iso->SetObjectGroupId(g3s1.handle, UniqueId(3));
3893 iso->SetObjectGroupId(g3s2.handle, UniqueId(3));
3894 Local<Object>::New(iso, g3s1.handle.As<Object>())->Set(
3895 v8_str("x"), Local<Value>::New(iso, g1s1.handle));
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003896 }
3897
3898 v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>(
3899 iso)->heap();
3900 heap->CollectGarbage(i::NEW_SPACE);
3901
3902 // All objects should be alive.
3903 CHECK_EQ(0, counter.NumberOfWeakCalls());
3904
3905 // Weaken the root.
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003906 root.handle.SetWeak(&root, &WeakPointerCallback);
3907 root.handle.MarkPartiallyDependent();
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003908
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003909 // Groups are deleted, rebuild groups.
3910 {
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003911 HandleScope handle_scope(iso);
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003912 g1s1.handle.MarkPartiallyDependent();
3913 g1s2.handle.MarkPartiallyDependent();
3914 g2s1.handle.MarkPartiallyDependent();
3915 g2s2.handle.MarkPartiallyDependent();
3916 g3s1.handle.MarkPartiallyDependent();
3917 g3s2.handle.MarkPartiallyDependent();
3918 iso->SetObjectGroupId(g1s1.handle, UniqueId(1));
3919 iso->SetObjectGroupId(g1s2.handle, UniqueId(1));
3920 Local<Object>::New(iso, g1s1.handle.As<Object>())->Set(
3921 v8_str("x"), Local<Value>::New(iso, g2s1.handle));
3922 iso->SetObjectGroupId(g2s1.handle, UniqueId(2));
3923 iso->SetObjectGroupId(g2s2.handle, UniqueId(2));
3924 Local<Object>::New(iso, g2s1.handle.As<Object>())->Set(
3925 v8_str("x"), Local<Value>::New(iso, g3s1.handle));
3926 iso->SetObjectGroupId(g3s1.handle, UniqueId(3));
3927 iso->SetObjectGroupId(g3s2.handle, UniqueId(3));
3928 Local<Object>::New(iso, g3s1.handle.As<Object>())->Set(
3929 v8_str("x"), Local<Value>::New(iso, g1s1.handle));
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003930 }
3931
3932 heap->CollectGarbage(i::NEW_SPACE);
3933
3934 // All objects should be gone. 7 global handles in total.
3935 CHECK_EQ(7, counter.NumberOfWeakCalls());
3936}
3937
3938
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003939THREADED_TEST(ScriptException) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003940 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003941 v8::HandleScope scope(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003942 Local<Script> script = Script::Compile(v8_str("throw 'panama!';"));
3943 v8::TryCatch try_catch;
3944 Local<Value> result = script->Run();
3945 CHECK(result.IsEmpty());
3946 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00003947 String::Utf8Value exception_value(try_catch.Exception());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003948 CHECK_EQ(*exception_value, "panama!");
3949}
3950
3951
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00003952TEST(TryCatchCustomException) {
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00003953 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003954 v8::HandleScope scope(env->GetIsolate());
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00003955 v8::TryCatch try_catch;
3956 CompileRun("function CustomError() { this.a = 'b'; }"
3957 "(function f() { throw new CustomError(); })();");
3958 CHECK(try_catch.HasCaught());
3959 CHECK(try_catch.Exception()->ToObject()->
3960 Get(v8_str("a"))->Equals(v8_str("b")));
3961}
3962
3963
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003964bool message_received;
3965
3966
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00003967static void check_message_0(v8::Handle<v8::Message> message,
3968 v8::Handle<Value> data) {
hpayer@chromium.org8432c912013-02-28 15:55:26 +00003969 CHECK_EQ(5.76, data->NumberValue());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003970 CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
ager@chromium.org65dad4b2009-04-23 08:48:43 +00003971 CHECK_EQ(7.56, message->GetScriptData()->NumberValue());
danno@chromium.orgd3c42102013-08-01 16:58:23 +00003972 CHECK(!message->IsSharedCrossOrigin());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003973 message_received = true;
3974}
3975
3976
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00003977THREADED_TEST(MessageHandler0) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003978 message_received = false;
machenbach@chromium.org528ce022013-09-23 14:09:36 +00003979 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003980 CHECK(!message_received);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003981 LocalContext context;
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003982 v8::V8::AddMessageListener(check_message_0, v8_num(5.76));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003983 v8::ScriptOrigin origin =
3984 v8::ScriptOrigin(v8_str("6.75"));
ager@chromium.org65dad4b2009-04-23 08:48:43 +00003985 v8::Handle<v8::Script> script = Script::Compile(v8_str("throw 'error'"),
3986 &origin);
3987 script->SetData(v8_str("7.56"));
3988 script->Run();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003989 CHECK(message_received);
3990 // clear out the message listener
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00003991 v8::V8::RemoveMessageListeners(check_message_0);
3992}
3993
3994
3995static void check_message_1(v8::Handle<v8::Message> message,
3996 v8::Handle<Value> data) {
3997 CHECK(data->IsNumber());
3998 CHECK_EQ(1337, data->Int32Value());
danno@chromium.orgd3c42102013-08-01 16:58:23 +00003999 CHECK(!message->IsSharedCrossOrigin());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00004000 message_received = true;
4001}
4002
4003
4004TEST(MessageHandler1) {
4005 message_received = false;
machenbach@chromium.org528ce022013-09-23 14:09:36 +00004006 v8::HandleScope scope(CcTest::isolate());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00004007 CHECK(!message_received);
4008 v8::V8::AddMessageListener(check_message_1);
4009 LocalContext context;
4010 CompileRun("throw 1337;");
4011 CHECK(message_received);
4012 // clear out the message listener
4013 v8::V8::RemoveMessageListeners(check_message_1);
4014}
4015
4016
4017static void check_message_2(v8::Handle<v8::Message> message,
4018 v8::Handle<Value> data) {
4019 LocalContext context;
4020 CHECK(data->IsObject());
4021 v8::Local<v8::Value> hidden_property =
4022 v8::Object::Cast(*data)->GetHiddenValue(v8_str("hidden key"));
4023 CHECK(v8_str("hidden value")->Equals(hidden_property));
danno@chromium.orgd3c42102013-08-01 16:58:23 +00004024 CHECK(!message->IsSharedCrossOrigin());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00004025 message_received = true;
4026}
4027
4028
4029TEST(MessageHandler2) {
4030 message_received = false;
machenbach@chromium.org528ce022013-09-23 14:09:36 +00004031 v8::HandleScope scope(CcTest::isolate());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00004032 CHECK(!message_received);
4033 v8::V8::AddMessageListener(check_message_2);
4034 LocalContext context;
4035 v8::Local<v8::Value> error = v8::Exception::Error(v8_str("custom error"));
4036 v8::Object::Cast(*error)->SetHiddenValue(v8_str("hidden key"),
4037 v8_str("hidden value"));
4038 context->Global()->Set(v8_str("error"), error);
4039 CompileRun("throw error;");
4040 CHECK(message_received);
4041 // clear out the message listener
4042 v8::V8::RemoveMessageListeners(check_message_2);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004043}
4044
4045
danno@chromium.orgd3c42102013-08-01 16:58:23 +00004046static void check_message_3(v8::Handle<v8::Message> message,
4047 v8::Handle<Value> data) {
4048 CHECK(message->IsSharedCrossOrigin());
4049 CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
4050 message_received = true;
4051}
4052
4053
4054TEST(MessageHandler3) {
4055 message_received = false;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00004056 v8::Isolate* isolate = CcTest::isolate();
4057 v8::HandleScope scope(isolate);
danno@chromium.orgd3c42102013-08-01 16:58:23 +00004058 CHECK(!message_received);
4059 v8::V8::AddMessageListener(check_message_3);
4060 LocalContext context;
4061 v8::ScriptOrigin origin =
4062 v8::ScriptOrigin(v8_str("6.75"),
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004063 v8::Integer::New(isolate, 1),
4064 v8::Integer::New(isolate, 2),
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00004065 v8::True(isolate));
danno@chromium.orgd3c42102013-08-01 16:58:23 +00004066 v8::Handle<v8::Script> script = Script::Compile(v8_str("throw 'error'"),
4067 &origin);
4068 script->Run();
4069 CHECK(message_received);
4070 // clear out the message listener
4071 v8::V8::RemoveMessageListeners(check_message_3);
4072}
4073
4074
4075static void check_message_4(v8::Handle<v8::Message> message,
4076 v8::Handle<Value> data) {
4077 CHECK(!message->IsSharedCrossOrigin());
4078 CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
4079 message_received = true;
4080}
4081
4082
4083TEST(MessageHandler4) {
4084 message_received = false;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00004085 v8::Isolate* isolate = CcTest::isolate();
4086 v8::HandleScope scope(isolate);
danno@chromium.orgd3c42102013-08-01 16:58:23 +00004087 CHECK(!message_received);
4088 v8::V8::AddMessageListener(check_message_4);
4089 LocalContext context;
4090 v8::ScriptOrigin origin =
4091 v8::ScriptOrigin(v8_str("6.75"),
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004092 v8::Integer::New(isolate, 1),
4093 v8::Integer::New(isolate, 2),
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00004094 v8::False(isolate));
danno@chromium.orgd3c42102013-08-01 16:58:23 +00004095 v8::Handle<v8::Script> script = Script::Compile(v8_str("throw 'error'"),
4096 &origin);
4097 script->Run();
4098 CHECK(message_received);
4099 // clear out the message listener
4100 v8::V8::RemoveMessageListeners(check_message_4);
4101}
4102
4103
4104static void check_message_5a(v8::Handle<v8::Message> message,
4105 v8::Handle<Value> data) {
4106 CHECK(message->IsSharedCrossOrigin());
4107 CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
4108 message_received = true;
4109}
4110
4111
4112static void check_message_5b(v8::Handle<v8::Message> message,
4113 v8::Handle<Value> data) {
4114 CHECK(!message->IsSharedCrossOrigin());
4115 CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
4116 message_received = true;
4117}
4118
4119
4120TEST(MessageHandler5) {
4121 message_received = false;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00004122 v8::Isolate* isolate = CcTest::isolate();
4123 v8::HandleScope scope(isolate);
danno@chromium.orgd3c42102013-08-01 16:58:23 +00004124 CHECK(!message_received);
4125 v8::V8::AddMessageListener(check_message_5a);
4126 LocalContext context;
4127 v8::ScriptOrigin origin =
4128 v8::ScriptOrigin(v8_str("6.75"),
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004129 v8::Integer::New(isolate, 1),
4130 v8::Integer::New(isolate, 2),
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00004131 v8::True(isolate));
danno@chromium.orgd3c42102013-08-01 16:58:23 +00004132 v8::Handle<v8::Script> script = Script::Compile(v8_str("throw 'error'"),
4133 &origin);
4134 script->Run();
4135 CHECK(message_received);
4136 // clear out the message listener
4137 v8::V8::RemoveMessageListeners(check_message_5a);
4138
4139 message_received = false;
4140 v8::V8::AddMessageListener(check_message_5b);
4141 origin =
4142 v8::ScriptOrigin(v8_str("6.75"),
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004143 v8::Integer::New(isolate, 1),
4144 v8::Integer::New(isolate, 2),
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00004145 v8::False(isolate));
danno@chromium.orgd3c42102013-08-01 16:58:23 +00004146 script = Script::Compile(v8_str("throw 'error'"),
4147 &origin);
4148 script->Run();
4149 CHECK(message_received);
4150 // clear out the message listener
4151 v8::V8::RemoveMessageListeners(check_message_5b);
4152}
4153
4154
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004155THREADED_TEST(GetSetProperty) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004156 LocalContext context;
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004157 v8::Isolate* isolate = context->GetIsolate();
4158 v8::HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004159 context->Global()->Set(v8_str("foo"), v8_num(14));
4160 context->Global()->Set(v8_str("12"), v8_num(92));
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004161 context->Global()->Set(v8::Integer::New(isolate, 16), v8_num(32));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004162 context->Global()->Set(v8_num(13), v8_num(56));
4163 Local<Value> foo = Script::Compile(v8_str("this.foo"))->Run();
4164 CHECK_EQ(14, foo->Int32Value());
4165 Local<Value> twelve = Script::Compile(v8_str("this[12]"))->Run();
4166 CHECK_EQ(92, twelve->Int32Value());
4167 Local<Value> sixteen = Script::Compile(v8_str("this[16]"))->Run();
4168 CHECK_EQ(32, sixteen->Int32Value());
4169 Local<Value> thirteen = Script::Compile(v8_str("this[13]"))->Run();
4170 CHECK_EQ(56, thirteen->Int32Value());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004171 CHECK_EQ(92,
4172 context->Global()->Get(v8::Integer::New(isolate, 12))->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004173 CHECK_EQ(92, context->Global()->Get(v8_str("12"))->Int32Value());
4174 CHECK_EQ(92, context->Global()->Get(v8_num(12))->Int32Value());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004175 CHECK_EQ(32,
4176 context->Global()->Get(v8::Integer::New(isolate, 16))->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004177 CHECK_EQ(32, context->Global()->Get(v8_str("16"))->Int32Value());
4178 CHECK_EQ(32, context->Global()->Get(v8_num(16))->Int32Value());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004179 CHECK_EQ(56,
4180 context->Global()->Get(v8::Integer::New(isolate, 13))->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004181 CHECK_EQ(56, context->Global()->Get(v8_str("13"))->Int32Value());
4182 CHECK_EQ(56, context->Global()->Get(v8_num(13))->Int32Value());
4183}
4184
4185
4186THREADED_TEST(PropertyAttributes) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004187 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004188 v8::HandleScope scope(context->GetIsolate());
rossberg@chromium.org717967f2011-07-20 13:44:42 +00004189 // none
4190 Local<String> prop = v8_str("none");
4191 context->Global()->Set(prop, v8_num(7));
4192 CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(prop));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004193 // read-only
rossberg@chromium.org717967f2011-07-20 13:44:42 +00004194 prop = v8_str("read_only");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004195 context->Global()->Set(prop, v8_num(7), v8::ReadOnly);
4196 CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
rossberg@chromium.org717967f2011-07-20 13:44:42 +00004197 CHECK_EQ(v8::ReadOnly, context->Global()->GetPropertyAttributes(prop));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004198 Script::Compile(v8_str("read_only = 9"))->Run();
4199 CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
4200 context->Global()->Set(prop, v8_num(10));
4201 CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
4202 // dont-delete
4203 prop = v8_str("dont_delete");
4204 context->Global()->Set(prop, v8_num(13), v8::DontDelete);
4205 CHECK_EQ(13, context->Global()->Get(prop)->Int32Value());
4206 Script::Compile(v8_str("delete dont_delete"))->Run();
4207 CHECK_EQ(13, context->Global()->Get(prop)->Int32Value());
rossberg@chromium.org717967f2011-07-20 13:44:42 +00004208 CHECK_EQ(v8::DontDelete, context->Global()->GetPropertyAttributes(prop));
4209 // dont-enum
4210 prop = v8_str("dont_enum");
4211 context->Global()->Set(prop, v8_num(28), v8::DontEnum);
4212 CHECK_EQ(v8::DontEnum, context->Global()->GetPropertyAttributes(prop));
4213 // absent
4214 prop = v8_str("absent");
4215 CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(prop));
4216 Local<Value> fake_prop = v8_num(1);
4217 CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(fake_prop));
4218 // exception
4219 TryCatch try_catch;
4220 Local<Value> exception =
4221 CompileRun("({ toString: function() { throw 'exception';} })");
4222 CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(exception));
4223 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00004224 String::Utf8Value exception_value(try_catch.Exception());
rossberg@chromium.org717967f2011-07-20 13:44:42 +00004225 CHECK_EQ("exception", *exception_value);
4226 try_catch.Reset();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004227}
4228
4229
4230THREADED_TEST(Array) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004231 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004232 v8::HandleScope scope(context->GetIsolate());
machenbach@chromium.org9f18d912013-11-28 13:42:41 +00004233 Local<v8::Array> array = v8::Array::New(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004234 CHECK_EQ(0, array->Length());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004235 CHECK(array->Get(0)->IsUndefined());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004236 CHECK(!array->Has(0));
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004237 CHECK(array->Get(100)->IsUndefined());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004238 CHECK(!array->Has(100));
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004239 array->Set(2, v8_num(7));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004240 CHECK_EQ(3, array->Length());
4241 CHECK(!array->Has(0));
4242 CHECK(!array->Has(1));
4243 CHECK(array->Has(2));
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004244 CHECK_EQ(7, array->Get(2)->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004245 Local<Value> obj = Script::Compile(v8_str("[1, 2, 3]"))->Run();
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004246 Local<v8::Array> arr = obj.As<v8::Array>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004247 CHECK_EQ(3, arr->Length());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004248 CHECK_EQ(1, arr->Get(0)->Int32Value());
4249 CHECK_EQ(2, arr->Get(1)->Int32Value());
4250 CHECK_EQ(3, arr->Get(2)->Int32Value());
machenbach@chromium.org9f18d912013-11-28 13:42:41 +00004251 array = v8::Array::New(context->GetIsolate(), 27);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00004252 CHECK_EQ(27, array->Length());
machenbach@chromium.org9f18d912013-11-28 13:42:41 +00004253 array = v8::Array::New(context->GetIsolate(), -27);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00004254 CHECK_EQ(0, array->Length());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004255}
4256
4257
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00004258void HandleF(const v8::FunctionCallbackInfo<v8::Value>& args) {
machenbach@chromium.orgafbdadc2013-12-09 16:12:18 +00004259 v8::EscapableHandleScope scope(args.GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004260 ApiTestFuzzer::Fuzz();
machenbach@chromium.org9f18d912013-11-28 13:42:41 +00004261 Local<v8::Array> result = v8::Array::New(args.GetIsolate(), args.Length());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004262 for (int i = 0; i < args.Length(); i++)
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004263 result->Set(i, args[i]);
machenbach@chromium.orgafbdadc2013-12-09 16:12:18 +00004264 args.GetReturnValue().Set(scope.Escape(result));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004265}
4266
4267
4268THREADED_TEST(Vector) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00004269 v8::Isolate* isolate = CcTest::isolate();
4270 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004271 Local<ObjectTemplate> global = ObjectTemplate::New(isolate);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00004272 global->Set(v8_str("f"), v8::FunctionTemplate::New(isolate, HandleF));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004273 LocalContext context(0, global);
4274
4275 const char* fun = "f()";
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004276 Local<v8::Array> a0 = CompileRun(fun).As<v8::Array>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004277 CHECK_EQ(0, a0->Length());
4278
4279 const char* fun2 = "f(11)";
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004280 Local<v8::Array> a1 = CompileRun(fun2).As<v8::Array>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004281 CHECK_EQ(1, a1->Length());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004282 CHECK_EQ(11, a1->Get(0)->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004283
4284 const char* fun3 = "f(12, 13)";
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004285 Local<v8::Array> a2 = CompileRun(fun3).As<v8::Array>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004286 CHECK_EQ(2, a2->Length());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004287 CHECK_EQ(12, a2->Get(0)->Int32Value());
4288 CHECK_EQ(13, a2->Get(1)->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004289
4290 const char* fun4 = "f(14, 15, 16)";
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004291 Local<v8::Array> a3 = CompileRun(fun4).As<v8::Array>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004292 CHECK_EQ(3, a3->Length());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004293 CHECK_EQ(14, a3->Get(0)->Int32Value());
4294 CHECK_EQ(15, a3->Get(1)->Int32Value());
4295 CHECK_EQ(16, a3->Get(2)->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004296
4297 const char* fun5 = "f(17, 18, 19, 20)";
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004298 Local<v8::Array> a4 = CompileRun(fun5).As<v8::Array>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004299 CHECK_EQ(4, a4->Length());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004300 CHECK_EQ(17, a4->Get(0)->Int32Value());
4301 CHECK_EQ(18, a4->Get(1)->Int32Value());
4302 CHECK_EQ(19, a4->Get(2)->Int32Value());
4303 CHECK_EQ(20, a4->Get(3)->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004304}
4305
4306
4307THREADED_TEST(FunctionCall) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004308 LocalContext context;
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +00004309 v8::Isolate* isolate = context->GetIsolate();
4310 v8::HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004311 CompileRun(
4312 "function Foo() {"
4313 " var result = [];"
4314 " for (var i = 0; i < arguments.length; i++) {"
4315 " result.push(arguments[i]);"
4316 " }"
4317 " return result;"
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +00004318 "}"
4319 "function ReturnThisSloppy() {"
4320 " return this;"
4321 "}"
4322 "function ReturnThisStrict() {"
4323 " 'use strict';"
4324 " return this;"
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004325 "}");
4326 Local<Function> Foo =
4327 Local<Function>::Cast(context->Global()->Get(v8_str("Foo")));
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +00004328 Local<Function> ReturnThisSloppy =
4329 Local<Function>::Cast(context->Global()->Get(v8_str("ReturnThisSloppy")));
4330 Local<Function> ReturnThisStrict =
4331 Local<Function>::Cast(context->Global()->Get(v8_str("ReturnThisStrict")));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004332
4333 v8::Handle<Value>* args0 = NULL;
4334 Local<v8::Array> a0 = Local<v8::Array>::Cast(Foo->Call(Foo, 0, args0));
4335 CHECK_EQ(0, a0->Length());
4336
4337 v8::Handle<Value> args1[] = { v8_num(1.1) };
4338 Local<v8::Array> a1 = Local<v8::Array>::Cast(Foo->Call(Foo, 1, args1));
4339 CHECK_EQ(1, a1->Length());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004340 CHECK_EQ(1.1, a1->Get(v8::Integer::New(isolate, 0))->NumberValue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004341
4342 v8::Handle<Value> args2[] = { v8_num(2.2),
4343 v8_num(3.3) };
4344 Local<v8::Array> a2 = Local<v8::Array>::Cast(Foo->Call(Foo, 2, args2));
4345 CHECK_EQ(2, a2->Length());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004346 CHECK_EQ(2.2, a2->Get(v8::Integer::New(isolate, 0))->NumberValue());
4347 CHECK_EQ(3.3, a2->Get(v8::Integer::New(isolate, 1))->NumberValue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004348
4349 v8::Handle<Value> args3[] = { v8_num(4.4),
4350 v8_num(5.5),
4351 v8_num(6.6) };
4352 Local<v8::Array> a3 = Local<v8::Array>::Cast(Foo->Call(Foo, 3, args3));
4353 CHECK_EQ(3, a3->Length());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004354 CHECK_EQ(4.4, a3->Get(v8::Integer::New(isolate, 0))->NumberValue());
4355 CHECK_EQ(5.5, a3->Get(v8::Integer::New(isolate, 1))->NumberValue());
4356 CHECK_EQ(6.6, a3->Get(v8::Integer::New(isolate, 2))->NumberValue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004357
4358 v8::Handle<Value> args4[] = { v8_num(7.7),
4359 v8_num(8.8),
4360 v8_num(9.9),
4361 v8_num(10.11) };
4362 Local<v8::Array> a4 = Local<v8::Array>::Cast(Foo->Call(Foo, 4, args4));
4363 CHECK_EQ(4, a4->Length());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004364 CHECK_EQ(7.7, a4->Get(v8::Integer::New(isolate, 0))->NumberValue());
4365 CHECK_EQ(8.8, a4->Get(v8::Integer::New(isolate, 1))->NumberValue());
4366 CHECK_EQ(9.9, a4->Get(v8::Integer::New(isolate, 2))->NumberValue());
4367 CHECK_EQ(10.11, a4->Get(v8::Integer::New(isolate, 3))->NumberValue());
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +00004368
4369 Local<v8::Value> r1 = ReturnThisSloppy->Call(v8::Undefined(isolate), 0, NULL);
4370 CHECK(r1->StrictEquals(context->Global()));
4371 Local<v8::Value> r2 = ReturnThisSloppy->Call(v8::Null(isolate), 0, NULL);
4372 CHECK(r2->StrictEquals(context->Global()));
4373 Local<v8::Value> r3 = ReturnThisSloppy->Call(v8_num(42), 0, NULL);
4374 CHECK(r3->IsNumberObject());
4375 CHECK_EQ(42.0, r3.As<v8::NumberObject>()->ValueOf());
4376 Local<v8::Value> r4 = ReturnThisSloppy->Call(v8_str("hello"), 0, NULL);
4377 CHECK(r4->IsStringObject());
4378 CHECK(r4.As<v8::StringObject>()->ValueOf()->StrictEquals(v8_str("hello")));
4379 Local<v8::Value> r5 = ReturnThisSloppy->Call(v8::True(isolate), 0, NULL);
4380 CHECK(r5->IsBooleanObject());
4381 CHECK(r5.As<v8::BooleanObject>()->ValueOf());
4382
4383 Local<v8::Value> r6 = ReturnThisStrict->Call(v8::Undefined(isolate), 0, NULL);
4384 CHECK(r6->IsUndefined());
4385 Local<v8::Value> r7 = ReturnThisStrict->Call(v8::Null(isolate), 0, NULL);
4386 CHECK(r7->IsNull());
4387 Local<v8::Value> r8 = ReturnThisStrict->Call(v8_num(42), 0, NULL);
4388 CHECK(r8->StrictEquals(v8_num(42)));
4389 Local<v8::Value> r9 = ReturnThisStrict->Call(v8_str("hello"), 0, NULL);
4390 CHECK(r9->StrictEquals(v8_str("hello")));
4391 Local<v8::Value> r10 = ReturnThisStrict->Call(v8::True(isolate), 0, NULL);
4392 CHECK(r10->StrictEquals(v8::True(isolate)));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004393}
4394
4395
4396static const char* js_code_causing_out_of_memory =
4397 "var a = new Array(); while(true) a.push(a);";
4398
4399
4400// These tests run for a long time and prevent us from running tests
4401// that come after them so they cannot run in parallel.
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00004402TEST(OutOfMemory) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004403 // It's not possible to read a snapshot into a heap with different dimensions.
lrn@chromium.org32d961d2010-06-30 09:09:34 +00004404 if (i::Snapshot::IsEnabled()) return;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004405 // Set heap limits.
4406 static const int K = 1024;
4407 v8::ResourceConstraints constraints;
4408 constraints.set_max_young_space_size(256 * K);
machenbach@chromium.orgc1789ee2013-07-05 07:09:57 +00004409 constraints.set_max_old_space_size(5 * K * K);
machenbach@chromium.org7ff76072013-11-21 09:47:43 +00004410 v8::SetResourceConstraints(CcTest::isolate(), &constraints);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004411
4412 // Execute a script that causes out of memory.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004413 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004414 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004415 v8::V8::IgnoreOutOfMemoryException();
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00004416 Local<Script> script = Script::Compile(String::NewFromUtf8(
4417 context->GetIsolate(), js_code_causing_out_of_memory));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004418 Local<Value> result = script->Run();
4419
4420 // Check for out of memory state.
4421 CHECK(result.IsEmpty());
4422 CHECK(context->HasOutOfMemoryException());
4423}
4424
4425
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00004426void ProvokeOutOfMemory(const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004427 ApiTestFuzzer::Fuzz();
4428
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004429 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004430 v8::HandleScope scope(context->GetIsolate());
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00004431 Local<Script> script = Script::Compile(String::NewFromUtf8(
4432 context->GetIsolate(), js_code_causing_out_of_memory));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004433 Local<Value> result = script->Run();
4434
4435 // Check for out of memory state.
4436 CHECK(result.IsEmpty());
4437 CHECK(context->HasOutOfMemoryException());
4438
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00004439 args.GetReturnValue().Set(result);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004440}
4441
4442
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00004443TEST(OutOfMemoryNested) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004444 // It's not possible to read a snapshot into a heap with different dimensions.
lrn@chromium.org32d961d2010-06-30 09:09:34 +00004445 if (i::Snapshot::IsEnabled()) return;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004446 // Set heap limits.
4447 static const int K = 1024;
4448 v8::ResourceConstraints constraints;
4449 constraints.set_max_young_space_size(256 * K);
machenbach@chromium.orgc1789ee2013-07-05 07:09:57 +00004450 constraints.set_max_old_space_size(5 * K * K);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004451 v8::Isolate* isolate = CcTest::isolate();
4452 v8::SetResourceConstraints(isolate, &constraints);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004453
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004454 v8::HandleScope scope(isolate);
4455 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004456 templ->Set(v8_str("ProvokeOutOfMemory"),
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004457 v8::FunctionTemplate::New(isolate, ProvokeOutOfMemory));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004458 LocalContext context(0, templ);
4459 v8::V8::IgnoreOutOfMemoryException();
4460 Local<Value> result = CompileRun(
4461 "var thrown = false;"
4462 "try {"
4463 " ProvokeOutOfMemory();"
4464 "} catch (e) {"
4465 " thrown = true;"
4466 "}");
4467 // Check for out of memory state.
4468 CHECK(result.IsEmpty());
4469 CHECK(context->HasOutOfMemoryException());
4470}
4471
4472
yangguo@chromium.org49546742013-12-23 16:17:49 +00004473void OOMCallback(const char* location, const char* message) {
4474 exit(0);
4475}
4476
4477
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004478TEST(HugeConsStringOutOfMemory) {
4479 // It's not possible to read a snapshot into a heap with different dimensions.
lrn@chromium.org32d961d2010-06-30 09:09:34 +00004480 if (i::Snapshot::IsEnabled()) return;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004481 // Set heap limits.
4482 static const int K = 1024;
4483 v8::ResourceConstraints constraints;
4484 constraints.set_max_young_space_size(256 * K);
machenbach@chromium.orgc1789ee2013-07-05 07:09:57 +00004485 constraints.set_max_old_space_size(4 * K * K);
machenbach@chromium.org7ff76072013-11-21 09:47:43 +00004486 v8::SetResourceConstraints(CcTest::isolate(), &constraints);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004487
4488 // Execute a script that causes out of memory.
yangguo@chromium.org49546742013-12-23 16:17:49 +00004489 v8::V8::SetFatalErrorHandler(OOMCallback);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004490
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00004491 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004492 v8::HandleScope scope(context->GetIsolate());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00004493
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004494 // Build huge string. This should fail with out of memory exception.
yangguo@chromium.org49546742013-12-23 16:17:49 +00004495 CompileRun(
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004496 "var str = Array.prototype.join.call({length: 513}, \"A\").toUpperCase();"
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00004497 "for (var i = 0; i < 22; i++) { str = str + str; }");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004498
yangguo@chromium.org49546742013-12-23 16:17:49 +00004499 CHECK(false); // Should not return.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004500}
4501
4502
4503THREADED_TEST(ConstructCall) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004504 LocalContext context;
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004505 v8::Isolate* isolate = context->GetIsolate();
4506 v8::HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004507 CompileRun(
4508 "function Foo() {"
4509 " var result = [];"
4510 " for (var i = 0; i < arguments.length; i++) {"
4511 " result.push(arguments[i]);"
4512 " }"
4513 " return result;"
4514 "}");
4515 Local<Function> Foo =
4516 Local<Function>::Cast(context->Global()->Get(v8_str("Foo")));
4517
4518 v8::Handle<Value>* args0 = NULL;
4519 Local<v8::Array> a0 = Local<v8::Array>::Cast(Foo->NewInstance(0, args0));
4520 CHECK_EQ(0, a0->Length());
4521
4522 v8::Handle<Value> args1[] = { v8_num(1.1) };
4523 Local<v8::Array> a1 = Local<v8::Array>::Cast(Foo->NewInstance(1, args1));
4524 CHECK_EQ(1, a1->Length());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004525 CHECK_EQ(1.1, a1->Get(v8::Integer::New(isolate, 0))->NumberValue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004526
4527 v8::Handle<Value> args2[] = { v8_num(2.2),
4528 v8_num(3.3) };
4529 Local<v8::Array> a2 = Local<v8::Array>::Cast(Foo->NewInstance(2, args2));
4530 CHECK_EQ(2, a2->Length());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004531 CHECK_EQ(2.2, a2->Get(v8::Integer::New(isolate, 0))->NumberValue());
4532 CHECK_EQ(3.3, a2->Get(v8::Integer::New(isolate, 1))->NumberValue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004533
4534 v8::Handle<Value> args3[] = { v8_num(4.4),
4535 v8_num(5.5),
4536 v8_num(6.6) };
4537 Local<v8::Array> a3 = Local<v8::Array>::Cast(Foo->NewInstance(3, args3));
4538 CHECK_EQ(3, a3->Length());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004539 CHECK_EQ(4.4, a3->Get(v8::Integer::New(isolate, 0))->NumberValue());
4540 CHECK_EQ(5.5, a3->Get(v8::Integer::New(isolate, 1))->NumberValue());
4541 CHECK_EQ(6.6, a3->Get(v8::Integer::New(isolate, 2))->NumberValue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004542
4543 v8::Handle<Value> args4[] = { v8_num(7.7),
4544 v8_num(8.8),
4545 v8_num(9.9),
4546 v8_num(10.11) };
4547 Local<v8::Array> a4 = Local<v8::Array>::Cast(Foo->NewInstance(4, args4));
4548 CHECK_EQ(4, a4->Length());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004549 CHECK_EQ(7.7, a4->Get(v8::Integer::New(isolate, 0))->NumberValue());
4550 CHECK_EQ(8.8, a4->Get(v8::Integer::New(isolate, 1))->NumberValue());
4551 CHECK_EQ(9.9, a4->Get(v8::Integer::New(isolate, 2))->NumberValue());
4552 CHECK_EQ(10.11, a4->Get(v8::Integer::New(isolate, 3))->NumberValue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004553}
4554
4555
4556static void CheckUncle(v8::TryCatch* try_catch) {
4557 CHECK(try_catch->HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00004558 String::Utf8Value str_value(try_catch->Exception());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004559 CHECK_EQ(*str_value, "uncle?");
4560 try_catch->Reset();
4561}
4562
4563
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004564THREADED_TEST(ConversionNumber) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004565 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004566 v8::HandleScope scope(env->GetIsolate());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004567 // Very large number.
4568 CompileRun("var obj = Math.pow(2,32) * 1237;");
4569 Local<Value> obj = env->Global()->Get(v8_str("obj"));
4570 CHECK_EQ(5312874545152.0, obj->ToNumber()->Value());
4571 CHECK_EQ(0, obj->ToInt32()->Value());
4572 CHECK(0u == obj->ToUint32()->Value()); // NOLINT - no CHECK_EQ for unsigned.
4573 // Large number.
4574 CompileRun("var obj = -1234567890123;");
4575 obj = env->Global()->Get(v8_str("obj"));
4576 CHECK_EQ(-1234567890123.0, obj->ToNumber()->Value());
4577 CHECK_EQ(-1912276171, obj->ToInt32()->Value());
4578 CHECK(2382691125u == obj->ToUint32()->Value()); // NOLINT
4579 // Small positive integer.
4580 CompileRun("var obj = 42;");
4581 obj = env->Global()->Get(v8_str("obj"));
4582 CHECK_EQ(42.0, obj->ToNumber()->Value());
4583 CHECK_EQ(42, obj->ToInt32()->Value());
4584 CHECK(42u == obj->ToUint32()->Value()); // NOLINT
4585 // Negative integer.
4586 CompileRun("var obj = -37;");
4587 obj = env->Global()->Get(v8_str("obj"));
4588 CHECK_EQ(-37.0, obj->ToNumber()->Value());
4589 CHECK_EQ(-37, obj->ToInt32()->Value());
4590 CHECK(4294967259u == obj->ToUint32()->Value()); // NOLINT
4591 // Positive non-int32 integer.
4592 CompileRun("var obj = 0x81234567;");
4593 obj = env->Global()->Get(v8_str("obj"));
4594 CHECK_EQ(2166572391.0, obj->ToNumber()->Value());
4595 CHECK_EQ(-2128394905, obj->ToInt32()->Value());
4596 CHECK(2166572391u == obj->ToUint32()->Value()); // NOLINT
4597 // Fraction.
4598 CompileRun("var obj = 42.3;");
4599 obj = env->Global()->Get(v8_str("obj"));
4600 CHECK_EQ(42.3, obj->ToNumber()->Value());
4601 CHECK_EQ(42, obj->ToInt32()->Value());
4602 CHECK(42u == obj->ToUint32()->Value()); // NOLINT
4603 // Large negative fraction.
4604 CompileRun("var obj = -5726623061.75;");
4605 obj = env->Global()->Get(v8_str("obj"));
4606 CHECK_EQ(-5726623061.75, obj->ToNumber()->Value());
4607 CHECK_EQ(-1431655765, obj->ToInt32()->Value());
4608 CHECK(2863311531u == obj->ToUint32()->Value()); // NOLINT
4609}
4610
4611
4612THREADED_TEST(isNumberType) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004613 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004614 v8::HandleScope scope(env->GetIsolate());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004615 // Very large number.
4616 CompileRun("var obj = Math.pow(2,32) * 1237;");
4617 Local<Value> obj = env->Global()->Get(v8_str("obj"));
4618 CHECK(!obj->IsInt32());
4619 CHECK(!obj->IsUint32());
4620 // Large negative number.
4621 CompileRun("var obj = -1234567890123;");
4622 obj = env->Global()->Get(v8_str("obj"));
4623 CHECK(!obj->IsInt32());
4624 CHECK(!obj->IsUint32());
4625 // Small positive integer.
4626 CompileRun("var obj = 42;");
4627 obj = env->Global()->Get(v8_str("obj"));
4628 CHECK(obj->IsInt32());
4629 CHECK(obj->IsUint32());
4630 // Negative integer.
4631 CompileRun("var obj = -37;");
4632 obj = env->Global()->Get(v8_str("obj"));
4633 CHECK(obj->IsInt32());
4634 CHECK(!obj->IsUint32());
4635 // Positive non-int32 integer.
4636 CompileRun("var obj = 0x81234567;");
4637 obj = env->Global()->Get(v8_str("obj"));
4638 CHECK(!obj->IsInt32());
4639 CHECK(obj->IsUint32());
4640 // Fraction.
4641 CompileRun("var obj = 42.3;");
4642 obj = env->Global()->Get(v8_str("obj"));
4643 CHECK(!obj->IsInt32());
4644 CHECK(!obj->IsUint32());
4645 // Large negative fraction.
4646 CompileRun("var obj = -5726623061.75;");
4647 obj = env->Global()->Get(v8_str("obj"));
4648 CHECK(!obj->IsInt32());
4649 CHECK(!obj->IsUint32());
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00004650 // Positive zero
4651 CompileRun("var obj = 0.0;");
4652 obj = env->Global()->Get(v8_str("obj"));
4653 CHECK(obj->IsInt32());
4654 CHECK(obj->IsUint32());
4655 // Positive zero
4656 CompileRun("var obj = -0.0;");
4657 obj = env->Global()->Get(v8_str("obj"));
4658 CHECK(!obj->IsInt32());
4659 CHECK(!obj->IsUint32());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004660}
4661
4662
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004663THREADED_TEST(ConversionException) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004664 LocalContext env;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00004665 v8::Isolate* isolate = env->GetIsolate();
4666 v8::HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004667 CompileRun(
4668 "function TestClass() { };"
4669 "TestClass.prototype.toString = function () { throw 'uncle?'; };"
4670 "var obj = new TestClass();");
4671 Local<Value> obj = env->Global()->Get(v8_str("obj"));
4672
4673 v8::TryCatch try_catch;
4674
4675 Local<Value> to_string_result = obj->ToString();
4676 CHECK(to_string_result.IsEmpty());
4677 CheckUncle(&try_catch);
4678
4679 Local<Value> to_number_result = obj->ToNumber();
4680 CHECK(to_number_result.IsEmpty());
4681 CheckUncle(&try_catch);
4682
4683 Local<Value> to_integer_result = obj->ToInteger();
4684 CHECK(to_integer_result.IsEmpty());
4685 CheckUncle(&try_catch);
4686
4687 Local<Value> to_uint32_result = obj->ToUint32();
4688 CHECK(to_uint32_result.IsEmpty());
4689 CheckUncle(&try_catch);
4690
4691 Local<Value> to_int32_result = obj->ToInt32();
4692 CHECK(to_int32_result.IsEmpty());
4693 CheckUncle(&try_catch);
4694
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00004695 Local<Value> to_object_result = v8::Undefined(isolate)->ToObject();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004696 CHECK(to_object_result.IsEmpty());
4697 CHECK(try_catch.HasCaught());
4698 try_catch.Reset();
4699
4700 int32_t int32_value = obj->Int32Value();
4701 CHECK_EQ(0, int32_value);
4702 CheckUncle(&try_catch);
4703
4704 uint32_t uint32_value = obj->Uint32Value();
4705 CHECK_EQ(0, uint32_value);
4706 CheckUncle(&try_catch);
4707
4708 double number_value = obj->NumberValue();
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00004709 CHECK_NE(0, std::isnan(number_value));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004710 CheckUncle(&try_catch);
4711
4712 int64_t integer_value = obj->IntegerValue();
4713 CHECK_EQ(0.0, static_cast<double>(integer_value));
4714 CheckUncle(&try_catch);
4715}
4716
4717
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00004718void ThrowFromC(const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004719 ApiTestFuzzer::Fuzz();
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00004720 args.GetIsolate()->ThrowException(v8_str("konto"));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004721}
4722
4723
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00004724void CCatcher(const v8::FunctionCallbackInfo<v8::Value>& args) {
4725 if (args.Length() < 1) {
4726 args.GetReturnValue().Set(false);
4727 return;
4728 }
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004729 v8::HandleScope scope(args.GetIsolate());
ager@chromium.org8bb60582008-12-11 12:02:20 +00004730 v8::TryCatch try_catch;
ager@chromium.org71daaf62009-04-01 07:22:49 +00004731 Local<Value> result = v8::Script::Compile(args[0]->ToString())->Run();
4732 CHECK(!try_catch.HasCaught() || result.IsEmpty());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00004733 args.GetReturnValue().Set(try_catch.HasCaught());
ager@chromium.org8bb60582008-12-11 12:02:20 +00004734}
4735
4736
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004737THREADED_TEST(APICatch) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004738 v8::Isolate* isolate = CcTest::isolate();
4739 v8::HandleScope scope(isolate);
4740 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004741 templ->Set(v8_str("ThrowFromC"),
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004742 v8::FunctionTemplate::New(isolate, ThrowFromC));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004743 LocalContext context(0, templ);
4744 CompileRun(
4745 "var thrown = false;"
4746 "try {"
4747 " ThrowFromC();"
4748 "} catch (e) {"
4749 " thrown = true;"
4750 "}");
4751 Local<Value> thrown = context->Global()->Get(v8_str("thrown"));
4752 CHECK(thrown->BooleanValue());
4753}
4754
4755
ager@chromium.org8bb60582008-12-11 12:02:20 +00004756THREADED_TEST(APIThrowTryCatch) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004757 v8::Isolate* isolate = CcTest::isolate();
4758 v8::HandleScope scope(isolate);
4759 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org8bb60582008-12-11 12:02:20 +00004760 templ->Set(v8_str("ThrowFromC"),
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004761 v8::FunctionTemplate::New(isolate, ThrowFromC));
ager@chromium.org8bb60582008-12-11 12:02:20 +00004762 LocalContext context(0, templ);
4763 v8::TryCatch try_catch;
4764 CompileRun("ThrowFromC();");
4765 CHECK(try_catch.HasCaught());
4766}
4767
4768
4769// Test that a try-finally block doesn't shadow a try-catch block
4770// when setting up an external handler.
ager@chromium.org71daaf62009-04-01 07:22:49 +00004771//
4772// BUG(271): Some of the exception propagation does not work on the
4773// ARM simulator because the simulator separates the C++ stack and the
4774// JS stack. This test therefore fails on the simulator. The test is
4775// not threaded to allow the threading tests to run on the simulator.
4776TEST(TryCatchInTryFinally) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004777 v8::Isolate* isolate = CcTest::isolate();
4778 v8::HandleScope scope(isolate);
4779 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org8bb60582008-12-11 12:02:20 +00004780 templ->Set(v8_str("CCatcher"),
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004781 v8::FunctionTemplate::New(isolate, CCatcher));
ager@chromium.org8bb60582008-12-11 12:02:20 +00004782 LocalContext context(0, templ);
4783 Local<Value> result = CompileRun("try {"
4784 " try {"
4785 " CCatcher('throw 7;');"
4786 " } finally {"
4787 " }"
4788 "} catch (e) {"
4789 "}");
4790 CHECK(result->IsTrue());
4791}
4792
4793
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00004794static void check_reference_error_message(
4795 v8::Handle<v8::Message> message,
4796 v8::Handle<v8::Value> data) {
4797 const char* reference_error = "Uncaught ReferenceError: asdf is not defined";
4798 CHECK(message->Get()->Equals(v8_str(reference_error)));
4799}
4800
4801
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00004802static void Fail(const v8::FunctionCallbackInfo<v8::Value>& args) {
kmillikin@chromium.org31b12772011-02-02 16:08:26 +00004803 ApiTestFuzzer::Fuzz();
4804 CHECK(false);
kmillikin@chromium.org31b12772011-02-02 16:08:26 +00004805}
4806
4807
4808// Test that overwritten methods are not invoked on uncaught exception
4809// formatting. However, they are invoked when performing normal error
4810// string conversions.
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00004811TEST(APIThrowMessageOverwrittenToString) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00004812 v8::Isolate* isolate = CcTest::isolate();
4813 v8::HandleScope scope(isolate);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00004814 v8::V8::AddMessageListener(check_reference_error_message);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004815 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00004816 templ->Set(v8_str("fail"), v8::FunctionTemplate::New(isolate, Fail));
kmillikin@chromium.org31b12772011-02-02 16:08:26 +00004817 LocalContext context(NULL, templ);
4818 CompileRun("asdf;");
4819 CompileRun("var limit = {};"
4820 "limit.valueOf = fail;"
4821 "Error.stackTraceLimit = limit;");
4822 CompileRun("asdf");
4823 CompileRun("Array.prototype.pop = fail;");
4824 CompileRun("Object.prototype.hasOwnProperty = fail;");
4825 CompileRun("Object.prototype.toString = function f() { return 'Yikes'; }");
whesse@chromium.org7a392b32011-01-31 11:30:36 +00004826 CompileRun("Number.prototype.toString = function f() { return 'Yikes'; }");
4827 CompileRun("String.prototype.toString = function f() { return 'Yikes'; }");
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00004828 CompileRun("ReferenceError.prototype.toString ="
4829 " function() { return 'Whoops' }");
4830 CompileRun("asdf;");
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00004831 CompileRun("ReferenceError.prototype.constructor.name = void 0;");
4832 CompileRun("asdf;");
4833 CompileRun("ReferenceError.prototype.constructor = void 0;");
4834 CompileRun("asdf;");
ager@chromium.org0ee099b2011-01-25 14:06:47 +00004835 CompileRun("ReferenceError.prototype.__proto__ = new Object();");
4836 CompileRun("asdf;");
4837 CompileRun("ReferenceError.prototype = new Object();");
4838 CompileRun("asdf;");
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00004839 v8::Handle<Value> string = CompileRun("try { asdf; } catch(e) { e + ''; }");
4840 CHECK(string->Equals(v8_str("Whoops")));
ager@chromium.org378b34e2011-01-28 08:04:38 +00004841 CompileRun("ReferenceError.prototype.constructor = new Object();"
4842 "ReferenceError.prototype.constructor.name = 1;"
4843 "Number.prototype.toString = function() { return 'Whoops'; };"
4844 "ReferenceError.prototype.toString = Object.prototype.toString;");
4845 CompileRun("asdf;");
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00004846 v8::V8::RemoveMessageListeners(check_reference_error_message);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00004847}
4848
4849
danno@chromium.org59400602013-08-13 17:09:37 +00004850static void check_custom_error_tostring(
yangguo@chromium.org304cc332012-07-24 07:59:48 +00004851 v8::Handle<v8::Message> message,
4852 v8::Handle<v8::Value> data) {
4853 const char* uncaught_error = "Uncaught MyError toString";
4854 CHECK(message->Get()->Equals(v8_str(uncaught_error)));
4855}
4856
4857
4858TEST(CustomErrorToString) {
yangguo@chromium.org304cc332012-07-24 07:59:48 +00004859 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004860 v8::HandleScope scope(context->GetIsolate());
danno@chromium.org59400602013-08-13 17:09:37 +00004861 v8::V8::AddMessageListener(check_custom_error_tostring);
yangguo@chromium.org304cc332012-07-24 07:59:48 +00004862 CompileRun(
4863 "function MyError(name, message) { "
4864 " this.name = name; "
4865 " this.message = message; "
4866 "} "
4867 "MyError.prototype = Object.create(Error.prototype); "
4868 "MyError.prototype.toString = function() { "
4869 " return 'MyError toString'; "
4870 "}; "
4871 "throw new MyError('my name', 'my message'); ");
danno@chromium.org59400602013-08-13 17:09:37 +00004872 v8::V8::RemoveMessageListeners(check_custom_error_tostring);
4873}
4874
4875
4876static void check_custom_error_message(
4877 v8::Handle<v8::Message> message,
4878 v8::Handle<v8::Value> data) {
4879 const char* uncaught_error = "Uncaught MyError: my message";
4880 printf("%s\n", *v8::String::Utf8Value(message->Get()));
4881 CHECK(message->Get()->Equals(v8_str(uncaught_error)));
4882}
4883
4884
4885TEST(CustomErrorMessage) {
4886 LocalContext context;
4887 v8::HandleScope scope(context->GetIsolate());
4888 v8::V8::AddMessageListener(check_custom_error_message);
4889
4890 // Handlebars.
4891 CompileRun(
4892 "function MyError(msg) { "
4893 " this.name = 'MyError'; "
4894 " this.message = msg; "
4895 "} "
4896 "MyError.prototype = new Error(); "
4897 "throw new MyError('my message'); ");
4898
4899 // Closure.
4900 CompileRun(
4901 "function MyError(msg) { "
4902 " this.name = 'MyError'; "
4903 " this.message = msg; "
4904 "} "
4905 "inherits = function(childCtor, parentCtor) { "
4906 " function tempCtor() {}; "
4907 " tempCtor.prototype = parentCtor.prototype; "
4908 " childCtor.superClass_ = parentCtor.prototype; "
4909 " childCtor.prototype = new tempCtor(); "
4910 " childCtor.prototype.constructor = childCtor; "
4911 "}; "
4912 "inherits(MyError, Error); "
4913 "throw new MyError('my message'); ");
4914
4915 // Object.create.
4916 CompileRun(
4917 "function MyError(msg) { "
4918 " this.name = 'MyError'; "
4919 " this.message = msg; "
4920 "} "
4921 "MyError.prototype = Object.create(Error.prototype); "
4922 "throw new MyError('my message'); ");
4923
yangguo@chromium.org304cc332012-07-24 07:59:48 +00004924 v8::V8::RemoveMessageListeners(check_custom_error_message);
4925}
4926
4927
ager@chromium.org8bb60582008-12-11 12:02:20 +00004928static void receive_message(v8::Handle<v8::Message> message,
4929 v8::Handle<v8::Value> data) {
ager@chromium.org71daaf62009-04-01 07:22:49 +00004930 message->Get();
ager@chromium.org8bb60582008-12-11 12:02:20 +00004931 message_received = true;
4932}
4933
4934
4935TEST(APIThrowMessage) {
4936 message_received = false;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004937 v8::Isolate* isolate = CcTest::isolate();
4938 v8::HandleScope scope(isolate);
ager@chromium.org8bb60582008-12-11 12:02:20 +00004939 v8::V8::AddMessageListener(receive_message);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004940 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org8bb60582008-12-11 12:02:20 +00004941 templ->Set(v8_str("ThrowFromC"),
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004942 v8::FunctionTemplate::New(isolate, ThrowFromC));
ager@chromium.org8bb60582008-12-11 12:02:20 +00004943 LocalContext context(0, templ);
4944 CompileRun("ThrowFromC();");
4945 CHECK(message_received);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00004946 v8::V8::RemoveMessageListeners(receive_message);
ager@chromium.org8bb60582008-12-11 12:02:20 +00004947}
4948
4949
4950TEST(APIThrowMessageAndVerboseTryCatch) {
4951 message_received = false;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004952 v8::Isolate* isolate = CcTest::isolate();
4953 v8::HandleScope scope(isolate);
ager@chromium.org8bb60582008-12-11 12:02:20 +00004954 v8::V8::AddMessageListener(receive_message);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004955 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org8bb60582008-12-11 12:02:20 +00004956 templ->Set(v8_str("ThrowFromC"),
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004957 v8::FunctionTemplate::New(isolate, ThrowFromC));
ager@chromium.org8bb60582008-12-11 12:02:20 +00004958 LocalContext context(0, templ);
4959 v8::TryCatch try_catch;
4960 try_catch.SetVerbose(true);
ager@chromium.org71daaf62009-04-01 07:22:49 +00004961 Local<Value> result = CompileRun("ThrowFromC();");
ager@chromium.org8bb60582008-12-11 12:02:20 +00004962 CHECK(try_catch.HasCaught());
ager@chromium.org71daaf62009-04-01 07:22:49 +00004963 CHECK(result.IsEmpty());
ager@chromium.org8bb60582008-12-11 12:02:20 +00004964 CHECK(message_received);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00004965 v8::V8::RemoveMessageListeners(receive_message);
ager@chromium.org8bb60582008-12-11 12:02:20 +00004966}
4967
4968
karlklose@chromium.org44bc7082011-04-11 12:33:05 +00004969TEST(APIStackOverflowAndVerboseTryCatch) {
4970 message_received = false;
karlklose@chromium.org44bc7082011-04-11 12:33:05 +00004971 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004972 v8::HandleScope scope(context->GetIsolate());
4973 v8::V8::AddMessageListener(receive_message);
karlklose@chromium.org44bc7082011-04-11 12:33:05 +00004974 v8::TryCatch try_catch;
4975 try_catch.SetVerbose(true);
4976 Local<Value> result = CompileRun("function foo() { foo(); } foo();");
4977 CHECK(try_catch.HasCaught());
4978 CHECK(result.IsEmpty());
4979 CHECK(message_received);
4980 v8::V8::RemoveMessageListeners(receive_message);
4981}
4982
4983
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004984THREADED_TEST(ExternalScriptException) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004985 v8::Isolate* isolate = CcTest::isolate();
4986 v8::HandleScope scope(isolate);
4987 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004988 templ->Set(v8_str("ThrowFromC"),
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004989 v8::FunctionTemplate::New(isolate, ThrowFromC));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004990 LocalContext context(0, templ);
4991
4992 v8::TryCatch try_catch;
4993 Local<Script> script
4994 = Script::Compile(v8_str("ThrowFromC(); throw 'panama';"));
4995 Local<Value> result = script->Run();
4996 CHECK(result.IsEmpty());
4997 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00004998 String::Utf8Value exception_value(try_catch.Exception());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004999 CHECK_EQ("konto", *exception_value);
5000}
5001
5002
5003
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005004void CThrowCountDown(const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005005 ApiTestFuzzer::Fuzz();
5006 CHECK_EQ(4, args.Length());
5007 int count = args[0]->Int32Value();
5008 int cInterval = args[2]->Int32Value();
5009 if (count == 0) {
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00005010 args.GetIsolate()->ThrowException(v8_str("FromC"));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005011 return;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005012 } else {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00005013 Local<v8::Object> global =
5014 args.GetIsolate()->GetCurrentContext()->Global();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005015 Local<Value> fun = global->Get(v8_str("JSThrowCountDown"));
5016 v8::Handle<Value> argv[] = { v8_num(count - 1),
5017 args[1],
5018 args[2],
5019 args[3] };
5020 if (count % cInterval == 0) {
5021 v8::TryCatch try_catch;
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00005022 Local<Value> result = fun.As<Function>()->Call(global, 4, argv);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005023 int expected = args[3]->Int32Value();
5024 if (try_catch.HasCaught()) {
5025 CHECK_EQ(expected, count);
ager@chromium.org71daaf62009-04-01 07:22:49 +00005026 CHECK(result.IsEmpty());
machenbach@chromium.org528ce022013-09-23 14:09:36 +00005027 CHECK(!CcTest::i_isolate()->has_scheduled_exception());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005028 } else {
5029 CHECK_NE(expected, count);
5030 }
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005031 args.GetReturnValue().Set(result);
5032 return;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005033 } else {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005034 args.GetReturnValue().Set(fun.As<Function>()->Call(global, 4, argv));
5035 return;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005036 }
5037 }
5038}
5039
5040
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005041void JSCheck(const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005042 ApiTestFuzzer::Fuzz();
5043 CHECK_EQ(3, args.Length());
5044 bool equality = args[0]->BooleanValue();
5045 int count = args[1]->Int32Value();
5046 int expected = args[2]->Int32Value();
5047 if (equality) {
5048 CHECK_EQ(count, expected);
5049 } else {
5050 CHECK_NE(count, expected);
5051 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005052}
5053
5054
ager@chromium.org8bb60582008-12-11 12:02:20 +00005055THREADED_TEST(EvalInTryFinally) {
ager@chromium.org8bb60582008-12-11 12:02:20 +00005056 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005057 v8::HandleScope scope(context->GetIsolate());
ager@chromium.org8bb60582008-12-11 12:02:20 +00005058 v8::TryCatch try_catch;
5059 CompileRun("(function() {"
5060 " try {"
5061 " eval('asldkf (*&^&*^');"
5062 " } finally {"
5063 " return;"
5064 " }"
5065 "})()");
5066 CHECK(!try_catch.HasCaught());
5067}
5068
5069
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005070// This test works by making a stack of alternating JavaScript and C
5071// activations. These activations set up exception handlers with regular
5072// intervals, one interval for C activations and another for JavaScript
5073// activations. When enough activations have been created an exception is
5074// thrown and we check that the right activation catches the exception and that
5075// no other activations do. The right activation is always the topmost one with
5076// a handler, regardless of whether it is in JavaScript or C.
5077//
5078// The notation used to describe a test case looks like this:
5079//
5080// *JS[4] *C[3] @JS[2] C[1] JS[0]
5081//
5082// Each entry is an activation, either JS or C. The index is the count at that
5083// level. Stars identify activations with exception handlers, the @ identifies
5084// the exception handler that should catch the exception.
ager@chromium.org71daaf62009-04-01 07:22:49 +00005085//
5086// BUG(271): Some of the exception propagation does not work on the
5087// ARM simulator because the simulator separates the C++ stack and the
5088// JS stack. This test therefore fails on the simulator. The test is
5089// not threaded to allow the threading tests to run on the simulator.
5090TEST(ExceptionOrder) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00005091 v8::Isolate* isolate = CcTest::isolate();
5092 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005093 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00005094 templ->Set(v8_str("check"), v8::FunctionTemplate::New(isolate, JSCheck));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005095 templ->Set(v8_str("CThrowCountDown"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00005096 v8::FunctionTemplate::New(isolate, CThrowCountDown));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005097 LocalContext context(0, templ);
5098 CompileRun(
5099 "function JSThrowCountDown(count, jsInterval, cInterval, expected) {"
5100 " if (count == 0) throw 'FromJS';"
5101 " if (count % jsInterval == 0) {"
5102 " try {"
5103 " var value = CThrowCountDown(count - 1,"
5104 " jsInterval,"
5105 " cInterval,"
5106 " expected);"
5107 " check(false, count, expected);"
5108 " return value;"
5109 " } catch (e) {"
5110 " check(true, count, expected);"
5111 " }"
5112 " } else {"
5113 " return CThrowCountDown(count - 1, jsInterval, cInterval, expected);"
5114 " }"
5115 "}");
5116 Local<Function> fun =
5117 Local<Function>::Cast(context->Global()->Get(v8_str("JSThrowCountDown")));
5118
5119 const int argc = 4;
5120 // count jsInterval cInterval expected
5121
5122 // *JS[4] *C[3] @JS[2] C[1] JS[0]
5123 v8::Handle<Value> a0[argc] = { v8_num(4), v8_num(2), v8_num(3), v8_num(2) };
5124 fun->Call(fun, argc, a0);
5125
5126 // JS[5] *C[4] JS[3] @C[2] JS[1] C[0]
5127 v8::Handle<Value> a1[argc] = { v8_num(5), v8_num(6), v8_num(1), v8_num(2) };
5128 fun->Call(fun, argc, a1);
5129
5130 // JS[6] @C[5] JS[4] C[3] JS[2] C[1] JS[0]
5131 v8::Handle<Value> a2[argc] = { v8_num(6), v8_num(7), v8_num(5), v8_num(5) };
5132 fun->Call(fun, argc, a2);
5133
5134 // @JS[6] C[5] JS[4] C[3] JS[2] C[1] JS[0]
5135 v8::Handle<Value> a3[argc] = { v8_num(6), v8_num(6), v8_num(7), v8_num(6) };
5136 fun->Call(fun, argc, a3);
5137
5138 // JS[6] *C[5] @JS[4] C[3] JS[2] C[1] JS[0]
5139 v8::Handle<Value> a4[argc] = { v8_num(6), v8_num(4), v8_num(5), v8_num(4) };
5140 fun->Call(fun, argc, a4);
5141
5142 // JS[6] C[5] *JS[4] @C[3] JS[2] C[1] JS[0]
5143 v8::Handle<Value> a5[argc] = { v8_num(6), v8_num(4), v8_num(3), v8_num(3) };
5144 fun->Call(fun, argc, a5);
5145}
5146
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00005147
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005148void ThrowValue(const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005149 ApiTestFuzzer::Fuzz();
5150 CHECK_EQ(1, args.Length());
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00005151 args.GetIsolate()->ThrowException(args[0]);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005152}
5153
5154
5155THREADED_TEST(ThrowValues) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00005156 v8::Isolate* isolate = CcTest::isolate();
5157 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005158 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00005159 templ->Set(v8_str("Throw"), v8::FunctionTemplate::New(isolate, ThrowValue));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005160 LocalContext context(0, templ);
5161 v8::Handle<v8::Array> result = v8::Handle<v8::Array>::Cast(CompileRun(
5162 "function Run(obj) {"
5163 " try {"
5164 " Throw(obj);"
5165 " } catch (e) {"
5166 " return e;"
5167 " }"
5168 " return 'no exception';"
5169 "}"
5170 "[Run('str'), Run(1), Run(0), Run(null), Run(void 0)];"));
5171 CHECK_EQ(5, result->Length());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00005172 CHECK(result->Get(v8::Integer::New(isolate, 0))->IsString());
5173 CHECK(result->Get(v8::Integer::New(isolate, 1))->IsNumber());
5174 CHECK_EQ(1, result->Get(v8::Integer::New(isolate, 1))->Int32Value());
5175 CHECK(result->Get(v8::Integer::New(isolate, 2))->IsNumber());
5176 CHECK_EQ(0, result->Get(v8::Integer::New(isolate, 2))->Int32Value());
5177 CHECK(result->Get(v8::Integer::New(isolate, 3))->IsNull());
5178 CHECK(result->Get(v8::Integer::New(isolate, 4))->IsUndefined());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005179}
5180
5181
5182THREADED_TEST(CatchZero) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005183 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005184 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005185 v8::TryCatch try_catch;
5186 CHECK(!try_catch.HasCaught());
5187 Script::Compile(v8_str("throw 10"))->Run();
5188 CHECK(try_catch.HasCaught());
5189 CHECK_EQ(10, try_catch.Exception()->Int32Value());
5190 try_catch.Reset();
5191 CHECK(!try_catch.HasCaught());
5192 Script::Compile(v8_str("throw 0"))->Run();
5193 CHECK(try_catch.HasCaught());
5194 CHECK_EQ(0, try_catch.Exception()->Int32Value());
5195}
5196
5197
5198THREADED_TEST(CatchExceptionFromWith) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005199 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005200 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005201 v8::TryCatch try_catch;
5202 CHECK(!try_catch.HasCaught());
5203 Script::Compile(v8_str("var o = {}; with (o) { throw 42; }"))->Run();
5204 CHECK(try_catch.HasCaught());
5205}
5206
5207
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00005208THREADED_TEST(TryCatchAndFinallyHidingException) {
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00005209 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005210 v8::HandleScope scope(context->GetIsolate());
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00005211 v8::TryCatch try_catch;
5212 CHECK(!try_catch.HasCaught());
5213 CompileRun("function f(k) { try { this[k]; } finally { return 0; } };");
5214 CompileRun("f({toString: function() { throw 42; }});");
5215 CHECK(!try_catch.HasCaught());
5216}
5217
5218
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005219void WithTryCatch(const v8::FunctionCallbackInfo<v8::Value>& args) {
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00005220 v8::TryCatch try_catch;
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00005221}
5222
5223
5224THREADED_TEST(TryCatchAndFinally) {
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00005225 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00005226 v8::Isolate* isolate = context->GetIsolate();
5227 v8::HandleScope scope(isolate);
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00005228 context->Global()->Set(
5229 v8_str("native_with_try_catch"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00005230 v8::FunctionTemplate::New(isolate, WithTryCatch)->GetFunction());
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00005231 v8::TryCatch try_catch;
5232 CHECK(!try_catch.HasCaught());
5233 CompileRun(
5234 "try {\n"
5235 " throw new Error('a');\n"
5236 "} finally {\n"
5237 " native_with_try_catch();\n"
5238 "}\n");
5239 CHECK(try_catch.HasCaught());
5240}
5241
5242
mmassi@chromium.org49a44672012-12-04 13:52:03 +00005243static void TryCatchNestedHelper(int depth) {
5244 if (depth > 0) {
5245 v8::TryCatch try_catch;
5246 try_catch.SetVerbose(true);
5247 TryCatchNestedHelper(depth - 1);
5248 CHECK(try_catch.HasCaught());
5249 try_catch.ReThrow();
5250 } else {
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00005251 CcTest::isolate()->ThrowException(v8_str("back"));
mmassi@chromium.org49a44672012-12-04 13:52:03 +00005252 }
5253}
5254
5255
5256TEST(TryCatchNested) {
5257 v8::V8::Initialize();
mmassi@chromium.org49a44672012-12-04 13:52:03 +00005258 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005259 v8::HandleScope scope(context->GetIsolate());
mmassi@chromium.org49a44672012-12-04 13:52:03 +00005260 v8::TryCatch try_catch;
5261 TryCatchNestedHelper(5);
5262 CHECK(try_catch.HasCaught());
5263 CHECK_EQ(0, strcmp(*v8::String::Utf8Value(try_catch.Exception()), "back"));
5264}
5265
5266
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +00005267void TryCatchMixedNestingCheck(v8::TryCatch* try_catch) {
5268 CHECK(try_catch->HasCaught());
5269 Handle<Message> message = try_catch->Message();
5270 Handle<Value> resource = message->GetScriptResourceName();
5271 CHECK_EQ(0, strcmp(*v8::String::Utf8Value(resource), "inner"));
5272 CHECK_EQ(0, strcmp(*v8::String::Utf8Value(message->Get()),
5273 "Uncaught Error: a"));
5274 CHECK_EQ(1, message->GetLineNumber());
5275 CHECK_EQ(6, message->GetStartColumn());
5276}
5277
5278
5279void TryCatchMixedNestingHelper(
5280 const v8::FunctionCallbackInfo<v8::Value>& args) {
5281 ApiTestFuzzer::Fuzz();
5282 v8::TryCatch try_catch;
5283 CompileRunWithOrigin("throw new Error('a');\n", "inner", 0, 0);
5284 CHECK(try_catch.HasCaught());
5285 TryCatchMixedNestingCheck(&try_catch);
5286 try_catch.ReThrow();
5287}
5288
5289
5290// This test ensures that an outer TryCatch in the following situation:
5291// C++/TryCatch -> JS -> C++/TryCatch -> JS w/ SyntaxError
5292// does not clobber the Message object generated for the inner TryCatch.
5293// This exercises the ability of TryCatch.ReThrow() to restore the
5294// inner pending Message before throwing the exception again.
5295TEST(TryCatchMixedNesting) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00005296 v8::Isolate* isolate = CcTest::isolate();
5297 v8::HandleScope scope(isolate);
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +00005298 v8::V8::Initialize();
5299 v8::TryCatch try_catch;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005300 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +00005301 templ->Set(v8_str("TryCatchMixedNestingHelper"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00005302 v8::FunctionTemplate::New(isolate, TryCatchMixedNestingHelper));
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +00005303 LocalContext context(0, templ);
5304 CompileRunWithOrigin("TryCatchMixedNestingHelper();\n", "outer", 1, 1);
5305 TryCatchMixedNestingCheck(&try_catch);
5306}
5307
5308
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005309THREADED_TEST(Equality) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005310 LocalContext context;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00005311 v8::Isolate* isolate = context->GetIsolate();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005312 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005313 // Check that equality works at all before relying on CHECK_EQ
5314 CHECK(v8_str("a")->Equals(v8_str("a")));
5315 CHECK(!v8_str("a")->Equals(v8_str("b")));
5316
5317 CHECK_EQ(v8_str("a"), v8_str("a"));
5318 CHECK_NE(v8_str("a"), v8_str("b"));
5319 CHECK_EQ(v8_num(1), v8_num(1));
5320 CHECK_EQ(v8_num(1.00), v8_num(1));
5321 CHECK_NE(v8_num(1), v8_num(2));
5322
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00005323 // Assume String is not internalized.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005324 CHECK(v8_str("a")->StrictEquals(v8_str("a")));
5325 CHECK(!v8_str("a")->StrictEquals(v8_str("b")));
5326 CHECK(!v8_str("5")->StrictEquals(v8_num(5)));
5327 CHECK(v8_num(1)->StrictEquals(v8_num(1)));
5328 CHECK(!v8_num(1)->StrictEquals(v8_num(2)));
machenbach@chromium.org3d079fe2013-09-25 08:19:55 +00005329 CHECK(v8_num(0.0)->StrictEquals(v8_num(-0.0)));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005330 Local<Value> not_a_number = v8_num(i::OS::nan_value());
5331 CHECK(!not_a_number->StrictEquals(not_a_number));
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00005332 CHECK(v8::False(isolate)->StrictEquals(v8::False(isolate)));
5333 CHECK(!v8::False(isolate)->StrictEquals(v8::Undefined(isolate)));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005334
ulan@chromium.org0f13e742014-01-03 15:51:11 +00005335 v8::Handle<v8::Object> obj = v8::Object::New(isolate);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00005336 v8::Persistent<v8::Object> alias(isolate, obj);
rossberg@chromium.org79e79022013-06-03 15:43:46 +00005337 CHECK(v8::Local<v8::Object>::New(isolate, alias)->StrictEquals(obj));
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00005338 alias.Reset();
machenbach@chromium.org3d079fe2013-09-25 08:19:55 +00005339
5340 CHECK(v8_str("a")->SameValue(v8_str("a")));
5341 CHECK(!v8_str("a")->SameValue(v8_str("b")));
5342 CHECK(!v8_str("5")->SameValue(v8_num(5)));
5343 CHECK(v8_num(1)->SameValue(v8_num(1)));
5344 CHECK(!v8_num(1)->SameValue(v8_num(2)));
5345 CHECK(!v8_num(0.0)->SameValue(v8_num(-0.0)));
5346 CHECK(not_a_number->SameValue(not_a_number));
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00005347 CHECK(v8::False(isolate)->SameValue(v8::False(isolate)));
5348 CHECK(!v8::False(isolate)->SameValue(v8::Undefined(isolate)));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005349}
5350
5351
5352THREADED_TEST(MultiRun) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005353 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005354 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005355 Local<Script> script = Script::Compile(v8_str("x"));
5356 for (int i = 0; i < 10; i++)
5357 script->Run();
5358}
5359
5360
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005361static void GetXValue(Local<String> name,
5362 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005363 ApiTestFuzzer::Fuzz();
5364 CHECK_EQ(info.Data(), v8_str("donut"));
5365 CHECK_EQ(name, v8_str("x"));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005366 info.GetReturnValue().Set(name);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005367}
5368
5369
5370THREADED_TEST(SimplePropertyRead) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005371 LocalContext context;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005372 v8::Isolate* isolate = context->GetIsolate();
5373 v8::HandleScope scope(isolate);
5374 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005375 templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005376 context->Global()->Set(v8_str("obj"), templ->NewInstance());
5377 Local<Script> script = Script::Compile(v8_str("obj.x"));
5378 for (int i = 0; i < 10; i++) {
5379 Local<Value> result = script->Run();
5380 CHECK_EQ(result, v8_str("x"));
5381 }
5382}
5383
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00005384
ager@chromium.org5c838252010-02-19 08:53:10 +00005385THREADED_TEST(DefinePropertyOnAPIAccessor) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005386 LocalContext context;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005387 v8::Isolate* isolate = context->GetIsolate();
5388 v8::HandleScope scope(isolate);
5389 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +00005390 templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
ager@chromium.org5c838252010-02-19 08:53:10 +00005391 context->Global()->Set(v8_str("obj"), templ->NewInstance());
5392
5393 // Uses getOwnPropertyDescriptor to check the configurable status
5394 Local<Script> script_desc
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00005395 = Script::Compile(v8_str("var prop = Object.getOwnPropertyDescriptor( "
ager@chromium.org5c838252010-02-19 08:53:10 +00005396 "obj, 'x');"
5397 "prop.configurable;"));
5398 Local<Value> result = script_desc->Run();
5399 CHECK_EQ(result->BooleanValue(), true);
5400
5401 // Redefine get - but still configurable
5402 Local<Script> script_define
5403 = Script::Compile(v8_str("var desc = { get: function(){return 42; },"
5404 " configurable: true };"
5405 "Object.defineProperty(obj, 'x', desc);"
5406 "obj.x"));
5407 result = script_define->Run();
5408 CHECK_EQ(result, v8_num(42));
5409
5410 // Check that the accessor is still configurable
5411 result = script_desc->Run();
5412 CHECK_EQ(result->BooleanValue(), true);
5413
5414 // Redefine to a non-configurable
5415 script_define
5416 = Script::Compile(v8_str("var desc = { get: function(){return 43; },"
5417 " configurable: false };"
5418 "Object.defineProperty(obj, 'x', desc);"
5419 "obj.x"));
5420 result = script_define->Run();
5421 CHECK_EQ(result, v8_num(43));
5422 result = script_desc->Run();
5423 CHECK_EQ(result->BooleanValue(), false);
5424
5425 // Make sure that it is not possible to redefine again
5426 v8::TryCatch try_catch;
5427 result = script_define->Run();
5428 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00005429 String::Utf8Value exception_value(try_catch.Exception());
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00005430 CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x");
ager@chromium.org5c838252010-02-19 08:53:10 +00005431}
5432
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00005433
ager@chromium.org5c838252010-02-19 08:53:10 +00005434THREADED_TEST(DefinePropertyOnDefineGetterSetter) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005435 v8::Isolate* isolate = CcTest::isolate();
5436 v8::HandleScope scope(isolate);
5437 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +00005438 templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
5439 LocalContext context;
5440 context->Global()->Set(v8_str("obj"), templ->NewInstance());
5441
5442 Local<Script> script_desc = Script::Compile(v8_str("var prop ="
5443 "Object.getOwnPropertyDescriptor( "
5444 "obj, 'x');"
5445 "prop.configurable;"));
5446 Local<Value> result = script_desc->Run();
5447 CHECK_EQ(result->BooleanValue(), true);
5448
5449 Local<Script> script_define =
5450 Script::Compile(v8_str("var desc = {get: function(){return 42; },"
5451 " configurable: true };"
5452 "Object.defineProperty(obj, 'x', desc);"
5453 "obj.x"));
5454 result = script_define->Run();
5455 CHECK_EQ(result, v8_num(42));
5456
5457
5458 result = script_desc->Run();
5459 CHECK_EQ(result->BooleanValue(), true);
5460
5461
5462 script_define =
5463 Script::Compile(v8_str("var desc = {get: function(){return 43; },"
5464 " configurable: false };"
5465 "Object.defineProperty(obj, 'x', desc);"
5466 "obj.x"));
5467 result = script_define->Run();
5468 CHECK_EQ(result, v8_num(43));
5469 result = script_desc->Run();
5470
5471 CHECK_EQ(result->BooleanValue(), false);
5472
5473 v8::TryCatch try_catch;
5474 result = script_define->Run();
5475 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00005476 String::Utf8Value exception_value(try_catch.Exception());
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00005477 CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x");
ager@chromium.org5c838252010-02-19 08:53:10 +00005478}
5479
5480
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00005481static v8::Handle<v8::Object> GetGlobalProperty(LocalContext* context,
5482 char const* name) {
5483 return v8::Handle<v8::Object>::Cast((*context)->Global()->Get(v8_str(name)));
5484}
ager@chromium.org5c838252010-02-19 08:53:10 +00005485
5486
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00005487THREADED_TEST(DefineAPIAccessorOnObject) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005488 v8::Isolate* isolate = CcTest::isolate();
5489 v8::HandleScope scope(isolate);
5490 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00005491 LocalContext context;
5492
5493 context->Global()->Set(v8_str("obj1"), templ->NewInstance());
5494 CompileRun("var obj2 = {};");
5495
5496 CHECK(CompileRun("obj1.x")->IsUndefined());
5497 CHECK(CompileRun("obj2.x")->IsUndefined());
5498
5499 CHECK(GetGlobalProperty(&context, "obj1")->
5500 SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5501
5502 ExpectString("obj1.x", "x");
5503 CHECK(CompileRun("obj2.x")->IsUndefined());
5504
5505 CHECK(GetGlobalProperty(&context, "obj2")->
5506 SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5507
5508 ExpectString("obj1.x", "x");
5509 ExpectString("obj2.x", "x");
5510
5511 ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
5512 ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
5513
5514 CompileRun("Object.defineProperty(obj1, 'x',"
5515 "{ get: function() { return 'y'; }, configurable: true })");
5516
5517 ExpectString("obj1.x", "y");
5518 ExpectString("obj2.x", "x");
5519
5520 CompileRun("Object.defineProperty(obj2, 'x',"
5521 "{ get: function() { return 'y'; }, configurable: true })");
5522
5523 ExpectString("obj1.x", "y");
5524 ExpectString("obj2.x", "y");
5525
5526 ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
5527 ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
5528
5529 CHECK(GetGlobalProperty(&context, "obj1")->
5530 SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5531 CHECK(GetGlobalProperty(&context, "obj2")->
5532 SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5533
5534 ExpectString("obj1.x", "x");
5535 ExpectString("obj2.x", "x");
5536
5537 ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
5538 ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
5539
5540 // Define getters/setters, but now make them not configurable.
5541 CompileRun("Object.defineProperty(obj1, 'x',"
5542 "{ get: function() { return 'z'; }, configurable: false })");
5543 CompileRun("Object.defineProperty(obj2, 'x',"
5544 "{ get: function() { return 'z'; }, configurable: false })");
5545
5546 ExpectTrue("!Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
5547 ExpectTrue("!Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
5548
5549 ExpectString("obj1.x", "z");
5550 ExpectString("obj2.x", "z");
5551
5552 CHECK(!GetGlobalProperty(&context, "obj1")->
5553 SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5554 CHECK(!GetGlobalProperty(&context, "obj2")->
5555 SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5556
5557 ExpectString("obj1.x", "z");
5558 ExpectString("obj2.x", "z");
5559}
5560
5561
5562THREADED_TEST(DontDeleteAPIAccessorsCannotBeOverriden) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005563 v8::Isolate* isolate = CcTest::isolate();
5564 v8::HandleScope scope(isolate);
5565 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00005566 LocalContext context;
5567
5568 context->Global()->Set(v8_str("obj1"), templ->NewInstance());
5569 CompileRun("var obj2 = {};");
5570
5571 CHECK(GetGlobalProperty(&context, "obj1")->SetAccessor(
5572 v8_str("x"),
5573 GetXValue, NULL,
5574 v8_str("donut"), v8::DEFAULT, v8::DontDelete));
5575 CHECK(GetGlobalProperty(&context, "obj2")->SetAccessor(
5576 v8_str("x"),
5577 GetXValue, NULL,
5578 v8_str("donut"), v8::DEFAULT, v8::DontDelete));
5579
5580 ExpectString("obj1.x", "x");
5581 ExpectString("obj2.x", "x");
5582
5583 ExpectTrue("!Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
5584 ExpectTrue("!Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
5585
5586 CHECK(!GetGlobalProperty(&context, "obj1")->
5587 SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5588 CHECK(!GetGlobalProperty(&context, "obj2")->
5589 SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5590
5591 {
5592 v8::TryCatch try_catch;
5593 CompileRun("Object.defineProperty(obj1, 'x',"
5594 "{get: function() { return 'func'; }})");
5595 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00005596 String::Utf8Value exception_value(try_catch.Exception());
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00005597 CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x");
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00005598 }
5599 {
5600 v8::TryCatch try_catch;
5601 CompileRun("Object.defineProperty(obj2, 'x',"
5602 "{get: function() { return 'func'; }})");
5603 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00005604 String::Utf8Value exception_value(try_catch.Exception());
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00005605 CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x");
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00005606 }
5607}
5608
5609
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005610static void Get239Value(Local<String> name,
5611 const v8::PropertyCallbackInfo<v8::Value>& info) {
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00005612 ApiTestFuzzer::Fuzz();
5613 CHECK_EQ(info.Data(), v8_str("donut"));
5614 CHECK_EQ(name, v8_str("239"));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005615 info.GetReturnValue().Set(name);
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00005616}
5617
5618
5619THREADED_TEST(ElementAPIAccessor) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005620 v8::Isolate* isolate = CcTest::isolate();
5621 v8::HandleScope scope(isolate);
5622 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00005623 LocalContext context;
5624
5625 context->Global()->Set(v8_str("obj1"), templ->NewInstance());
5626 CompileRun("var obj2 = {};");
5627
5628 CHECK(GetGlobalProperty(&context, "obj1")->SetAccessor(
5629 v8_str("239"),
5630 Get239Value, NULL,
5631 v8_str("donut")));
5632 CHECK(GetGlobalProperty(&context, "obj2")->SetAccessor(
5633 v8_str("239"),
5634 Get239Value, NULL,
5635 v8_str("donut")));
5636
5637 ExpectString("obj1[239]", "239");
5638 ExpectString("obj2[239]", "239");
5639 ExpectString("obj1['239']", "239");
5640 ExpectString("obj2['239']", "239");
5641}
5642
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005643
5644v8::Persistent<Value> xValue;
5645
5646
5647static void SetXValue(Local<String> name,
5648 Local<Value> value,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005649 const v8::PropertyCallbackInfo<void>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005650 CHECK_EQ(value, v8_num(4));
5651 CHECK_EQ(info.Data(), v8_str("donut"));
5652 CHECK_EQ(name, v8_str("x"));
5653 CHECK(xValue.IsEmpty());
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00005654 xValue.Reset(info.GetIsolate(), value);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005655}
5656
5657
5658THREADED_TEST(SimplePropertyWrite) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005659 v8::Isolate* isolate = CcTest::isolate();
5660 v8::HandleScope scope(isolate);
5661 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005662 templ->SetAccessor(v8_str("x"), GetXValue, SetXValue, v8_str("donut"));
5663 LocalContext context;
5664 context->Global()->Set(v8_str("obj"), templ->NewInstance());
5665 Local<Script> script = Script::Compile(v8_str("obj.x = 4"));
5666 for (int i = 0; i < 10; i++) {
5667 CHECK(xValue.IsEmpty());
5668 script->Run();
machenbach@chromium.org528ce022013-09-23 14:09:36 +00005669 CHECK_EQ(v8_num(4), Local<Value>::New(CcTest::isolate(), xValue));
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00005670 xValue.Reset();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005671 }
5672}
5673
5674
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00005675THREADED_TEST(SetterOnly) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005676 v8::Isolate* isolate = CcTest::isolate();
5677 v8::HandleScope scope(isolate);
5678 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00005679 templ->SetAccessor(v8_str("x"), NULL, SetXValue, v8_str("donut"));
5680 LocalContext context;
5681 context->Global()->Set(v8_str("obj"), templ->NewInstance());
5682 Local<Script> script = Script::Compile(v8_str("obj.x = 4; obj.x"));
5683 for (int i = 0; i < 10; i++) {
5684 CHECK(xValue.IsEmpty());
5685 script->Run();
machenbach@chromium.org528ce022013-09-23 14:09:36 +00005686 CHECK_EQ(v8_num(4), Local<Value>::New(CcTest::isolate(), xValue));
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00005687 xValue.Reset();
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00005688 }
5689}
5690
5691
5692THREADED_TEST(NoAccessors) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005693 v8::Isolate* isolate = CcTest::isolate();
5694 v8::HandleScope scope(isolate);
5695 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00005696 templ->SetAccessor(v8_str("x"),
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005697 static_cast<v8::AccessorGetterCallback>(NULL),
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00005698 NULL,
5699 v8_str("donut"));
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00005700 LocalContext context;
5701 context->Global()->Set(v8_str("obj"), templ->NewInstance());
5702 Local<Script> script = Script::Compile(v8_str("obj.x = 4; obj.x"));
5703 for (int i = 0; i < 10; i++) {
5704 script->Run();
5705 }
5706}
5707
5708
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005709static void XPropertyGetter(Local<String> property,
5710 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005711 ApiTestFuzzer::Fuzz();
5712 CHECK(info.Data()->IsUndefined());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005713 info.GetReturnValue().Set(property);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005714}
5715
5716
ager@chromium.orgeadaf222009-06-16 09:43:10 +00005717THREADED_TEST(NamedInterceptorPropertyRead) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005718 v8::Isolate* isolate = CcTest::isolate();
5719 v8::HandleScope scope(isolate);
5720 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005721 templ->SetNamedPropertyHandler(XPropertyGetter);
5722 LocalContext context;
5723 context->Global()->Set(v8_str("obj"), templ->NewInstance());
5724 Local<Script> script = Script::Compile(v8_str("obj.x"));
5725 for (int i = 0; i < 10; i++) {
5726 Local<Value> result = script->Run();
5727 CHECK_EQ(result, v8_str("x"));
5728 }
5729}
5730
ager@chromium.orgeadaf222009-06-16 09:43:10 +00005731
ager@chromium.orgb26c50a2010-03-26 09:27:16 +00005732THREADED_TEST(NamedInterceptorDictionaryIC) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005733 v8::Isolate* isolate = CcTest::isolate();
5734 v8::HandleScope scope(isolate);
5735 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.orgb26c50a2010-03-26 09:27:16 +00005736 templ->SetNamedPropertyHandler(XPropertyGetter);
5737 LocalContext context;
5738 // Create an object with a named interceptor.
5739 context->Global()->Set(v8_str("interceptor_obj"), templ->NewInstance());
5740 Local<Script> script = Script::Compile(v8_str("interceptor_obj.x"));
5741 for (int i = 0; i < 10; i++) {
5742 Local<Value> result = script->Run();
5743 CHECK_EQ(result, v8_str("x"));
5744 }
5745 // Create a slow case object and a function accessing a property in
5746 // that slow case object (with dictionary probing in generated
5747 // code). Then force object with a named interceptor into slow-case,
5748 // pass it to the function, and check that the interceptor is called
5749 // instead of accessing the local property.
5750 Local<Value> result =
5751 CompileRun("function get_x(o) { return o.x; };"
5752 "var obj = { x : 42, y : 0 };"
5753 "delete obj.y;"
5754 "for (var i = 0; i < 10; i++) get_x(obj);"
5755 "interceptor_obj.x = 42;"
5756 "interceptor_obj.y = 10;"
5757 "delete interceptor_obj.y;"
5758 "get_x(interceptor_obj)");
5759 CHECK_EQ(result, v8_str("x"));
5760}
5761
5762
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00005763THREADED_TEST(NamedInterceptorDictionaryICMultipleContext) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00005764 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00005765 v8::HandleScope scope(isolate);
5766 v8::Local<Context> context1 = Context::New(isolate);
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00005767
5768 context1->Enter();
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005769 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00005770 templ->SetNamedPropertyHandler(XPropertyGetter);
5771 // Create an object with a named interceptor.
5772 v8::Local<v8::Object> object = templ->NewInstance();
5773 context1->Global()->Set(v8_str("interceptor_obj"), object);
5774
5775 // Force the object into the slow case.
5776 CompileRun("interceptor_obj.y = 0;"
5777 "delete interceptor_obj.y;");
5778 context1->Exit();
5779
5780 {
5781 // Introduce the object into a different context.
5782 // Repeat named loads to exercise ICs.
5783 LocalContext context2;
5784 context2->Global()->Set(v8_str("interceptor_obj"), object);
5785 Local<Value> result =
5786 CompileRun("function get_x(o) { return o.x; }"
5787 "interceptor_obj.x = 42;"
5788 "for (var i=0; i != 10; i++) {"
5789 " get_x(interceptor_obj);"
5790 "}"
5791 "get_x(interceptor_obj)");
5792 // Check that the interceptor was actually invoked.
5793 CHECK_EQ(result, v8_str("x"));
5794 }
5795
5796 // Return to the original context and force some object to the slow case
5797 // to cause the NormalizedMapCache to verify.
5798 context1->Enter();
5799 CompileRun("var obj = { x : 0 }; delete obj.x;");
5800 context1->Exit();
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00005801}
5802
5803
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005804static void SetXOnPrototypeGetter(
5805 Local<String> property,
5806 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.org5c838252010-02-19 08:53:10 +00005807 // Set x on the prototype object and do not handle the get request.
5808 v8::Handle<v8::Value> proto = info.Holder()->GetPrototype();
ulan@chromium.org0f13e742014-01-03 15:51:11 +00005809 proto.As<v8::Object>()->Set(v8_str("x"),
5810 v8::Integer::New(info.GetIsolate(), 23));
ager@chromium.org5c838252010-02-19 08:53:10 +00005811}
5812
5813
5814// This is a regression test for http://crbug.com/20104. Map
5815// transitions should not interfere with post interceptor lookup.
5816THREADED_TEST(NamedInterceptorMapTransitionRead) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00005817 v8::Isolate* isolate = CcTest::isolate();
5818 v8::HandleScope scope(isolate);
5819 Local<v8::FunctionTemplate> function_template =
5820 v8::FunctionTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +00005821 Local<v8::ObjectTemplate> instance_template
5822 = function_template->InstanceTemplate();
5823 instance_template->SetNamedPropertyHandler(SetXOnPrototypeGetter);
5824 LocalContext context;
5825 context->Global()->Set(v8_str("F"), function_template->GetFunction());
5826 // Create an instance of F and introduce a map transition for x.
5827 CompileRun("var o = new F(); o.x = 23;");
5828 // Create an instance of F and invoke the getter. The result should be 23.
5829 Local<Value> result = CompileRun("o = new F(); o.x");
5830 CHECK_EQ(result->Int32Value(), 23);
5831}
5832
5833
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005834static void IndexedPropertyGetter(
5835 uint32_t index,
5836 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.orgeadaf222009-06-16 09:43:10 +00005837 ApiTestFuzzer::Fuzz();
5838 if (index == 37) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005839 info.GetReturnValue().Set(v8_num(625));
ager@chromium.orgeadaf222009-06-16 09:43:10 +00005840 }
ager@chromium.orgeadaf222009-06-16 09:43:10 +00005841}
5842
5843
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005844static void IndexedPropertySetter(
5845 uint32_t index,
5846 Local<Value> value,
5847 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.orgeadaf222009-06-16 09:43:10 +00005848 ApiTestFuzzer::Fuzz();
5849 if (index == 39) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005850 info.GetReturnValue().Set(value);
ager@chromium.orgeadaf222009-06-16 09:43:10 +00005851 }
ager@chromium.orgeadaf222009-06-16 09:43:10 +00005852}
5853
5854
5855THREADED_TEST(IndexedInterceptorWithIndexedAccessor) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005856 v8::Isolate* isolate = CcTest::isolate();
5857 v8::HandleScope scope(isolate);
5858 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.orgeadaf222009-06-16 09:43:10 +00005859 templ->SetIndexedPropertyHandler(IndexedPropertyGetter,
5860 IndexedPropertySetter);
5861 LocalContext context;
5862 context->Global()->Set(v8_str("obj"), templ->NewInstance());
5863 Local<Script> getter_script = Script::Compile(v8_str(
5864 "obj.__defineGetter__(\"3\", function(){return 5;});obj[3];"));
5865 Local<Script> setter_script = Script::Compile(v8_str(
5866 "obj.__defineSetter__(\"17\", function(val){this.foo = val;});"
5867 "obj[17] = 23;"
5868 "obj.foo;"));
5869 Local<Script> interceptor_setter_script = Script::Compile(v8_str(
5870 "obj.__defineSetter__(\"39\", function(val){this.foo = \"hit\";});"
5871 "obj[39] = 47;"
5872 "obj.foo;")); // This setter should not run, due to the interceptor.
5873 Local<Script> interceptor_getter_script = Script::Compile(v8_str(
5874 "obj[37];"));
5875 Local<Value> result = getter_script->Run();
5876 CHECK_EQ(v8_num(5), result);
5877 result = setter_script->Run();
5878 CHECK_EQ(v8_num(23), result);
5879 result = interceptor_setter_script->Run();
5880 CHECK_EQ(v8_num(23), result);
5881 result = interceptor_getter_script->Run();
5882 CHECK_EQ(v8_num(625), result);
5883}
5884
5885
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005886static void UnboxedDoubleIndexedPropertyGetter(
ricow@chromium.org9fa09672011-07-25 11:05:35 +00005887 uint32_t index,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005888 const v8::PropertyCallbackInfo<v8::Value>& info) {
ricow@chromium.org9fa09672011-07-25 11:05:35 +00005889 ApiTestFuzzer::Fuzz();
5890 if (index < 25) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005891 info.GetReturnValue().Set(v8_num(index));
ricow@chromium.org9fa09672011-07-25 11:05:35 +00005892 }
ricow@chromium.org9fa09672011-07-25 11:05:35 +00005893}
5894
5895
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005896static void UnboxedDoubleIndexedPropertySetter(
ricow@chromium.org9fa09672011-07-25 11:05:35 +00005897 uint32_t index,
5898 Local<Value> value,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005899 const v8::PropertyCallbackInfo<v8::Value>& info) {
ricow@chromium.org9fa09672011-07-25 11:05:35 +00005900 ApiTestFuzzer::Fuzz();
5901 if (index < 25) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005902 info.GetReturnValue().Set(v8_num(index));
ricow@chromium.org9fa09672011-07-25 11:05:35 +00005903 }
ricow@chromium.org9fa09672011-07-25 11:05:35 +00005904}
5905
5906
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005907void UnboxedDoubleIndexedPropertyEnumerator(
5908 const v8::PropertyCallbackInfo<v8::Array>& info) {
ricow@chromium.org9fa09672011-07-25 11:05:35 +00005909 // Force the list of returned keys to be stored in a FastDoubleArray.
5910 Local<Script> indexed_property_names_script = Script::Compile(v8_str(
5911 "keys = new Array(); keys[125000] = 1;"
5912 "for(i = 0; i < 80000; i++) { keys[i] = i; };"
5913 "keys.length = 25; keys;"));
5914 Local<Value> result = indexed_property_names_script->Run();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005915 info.GetReturnValue().Set(Local<v8::Array>::Cast(result));
ricow@chromium.org9fa09672011-07-25 11:05:35 +00005916}
5917
5918
5919// Make sure that the the interceptor code in the runtime properly handles
5920// merging property name lists for double-array-backed arrays.
5921THREADED_TEST(IndexedInterceptorUnboxedDoubleWithIndexedAccessor) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005922 v8::Isolate* isolate = CcTest::isolate();
5923 v8::HandleScope scope(isolate);
5924 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ricow@chromium.org9fa09672011-07-25 11:05:35 +00005925 templ->SetIndexedPropertyHandler(UnboxedDoubleIndexedPropertyGetter,
5926 UnboxedDoubleIndexedPropertySetter,
5927 0,
5928 0,
5929 UnboxedDoubleIndexedPropertyEnumerator);
5930 LocalContext context;
5931 context->Global()->Set(v8_str("obj"), templ->NewInstance());
5932 // When obj is created, force it to be Stored in a FastDoubleArray.
5933 Local<Script> create_unboxed_double_script = Script::Compile(v8_str(
5934 "obj[125000] = 1; for(i = 0; i < 80000; i+=2) { obj[i] = i; } "
5935 "key_count = 0; "
5936 "for (x in obj) {key_count++;};"
5937 "obj;"));
5938 Local<Value> result = create_unboxed_double_script->Run();
5939 CHECK(result->ToObject()->HasRealIndexedProperty(2000));
5940 Local<Script> key_count_check = Script::Compile(v8_str(
5941 "key_count;"));
5942 result = key_count_check->Run();
5943 CHECK_EQ(v8_num(40013), result);
5944}
5945
5946
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005947void NonStrictArgsIndexedPropertyEnumerator(
5948 const v8::PropertyCallbackInfo<v8::Array>& info) {
rossberg@chromium.org28a37082011-08-22 11:03:23 +00005949 // Force the list of returned keys to be stored in a Arguments object.
5950 Local<Script> indexed_property_names_script = Script::Compile(v8_str(
5951 "function f(w,x) {"
5952 " return arguments;"
5953 "}"
5954 "keys = f(0, 1, 2, 3);"
5955 "keys;"));
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00005956 Local<Object> result =
5957 Local<Object>::Cast(indexed_property_names_script->Run());
5958 // Have to populate the handle manually, as it's not Cast-able.
5959 i::Handle<i::JSObject> o =
5960 v8::Utils::OpenHandle<Object, i::JSObject>(result);
5961 i::Handle<i::JSArray> array(reinterpret_cast<i::JSArray*>(*o));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005962 info.GetReturnValue().Set(v8::Utils::ToLocal(array));
rossberg@chromium.org28a37082011-08-22 11:03:23 +00005963}
5964
5965
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005966static void NonStrictIndexedPropertyGetter(
rossberg@chromium.org28a37082011-08-22 11:03:23 +00005967 uint32_t index,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005968 const v8::PropertyCallbackInfo<v8::Value>& info) {
rossberg@chromium.org28a37082011-08-22 11:03:23 +00005969 ApiTestFuzzer::Fuzz();
5970 if (index < 4) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005971 info.GetReturnValue().Set(v8_num(index));
rossberg@chromium.org28a37082011-08-22 11:03:23 +00005972 }
rossberg@chromium.org28a37082011-08-22 11:03:23 +00005973}
5974
5975
5976// Make sure that the the interceptor code in the runtime properly handles
5977// merging property name lists for non-string arguments arrays.
5978THREADED_TEST(IndexedInterceptorNonStrictArgsWithIndexedAccessor) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005979 v8::Isolate* isolate = CcTest::isolate();
5980 v8::HandleScope scope(isolate);
5981 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
rossberg@chromium.org28a37082011-08-22 11:03:23 +00005982 templ->SetIndexedPropertyHandler(NonStrictIndexedPropertyGetter,
5983 0,
5984 0,
5985 0,
5986 NonStrictArgsIndexedPropertyEnumerator);
5987 LocalContext context;
5988 context->Global()->Set(v8_str("obj"), templ->NewInstance());
5989 Local<Script> create_args_script =
5990 Script::Compile(v8_str(
5991 "var key_count = 0;"
5992 "for (x in obj) {key_count++;} key_count;"));
5993 Local<Value> result = create_args_script->Run();
5994 CHECK_EQ(v8_num(4), result);
5995}
5996
5997
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005998static void IdentityIndexedPropertyGetter(
kasperl@chromium.orgeac059f2010-01-25 11:02:06 +00005999 uint32_t index,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00006000 const v8::PropertyCallbackInfo<v8::Value>& info) {
6001 info.GetReturnValue().Set(index);
kasperl@chromium.orgeac059f2010-01-25 11:02:06 +00006002}
6003
6004
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00006005THREADED_TEST(IndexedInterceptorWithGetOwnPropertyDescriptor) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00006006 v8::Isolate* isolate = CcTest::isolate();
6007 v8::HandleScope scope(isolate);
6008 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00006009 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
6010
6011 LocalContext context;
6012 context->Global()->Set(v8_str("obj"), templ->NewInstance());
6013
6014 // Check fast object case.
6015 const char* fast_case_code =
6016 "Object.getOwnPropertyDescriptor(obj, 0).value.toString()";
6017 ExpectString(fast_case_code, "0");
6018
6019 // Check slow case.
6020 const char* slow_case_code =
6021 "obj.x = 1; delete obj.x;"
6022 "Object.getOwnPropertyDescriptor(obj, 1).value.toString()";
6023 ExpectString(slow_case_code, "1");
6024}
6025
6026
kasperl@chromium.orgeac059f2010-01-25 11:02:06 +00006027THREADED_TEST(IndexedInterceptorWithNoSetter) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00006028 v8::Isolate* isolate = CcTest::isolate();
6029 v8::HandleScope scope(isolate);
6030 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
kasperl@chromium.orgeac059f2010-01-25 11:02:06 +00006031 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
6032
6033 LocalContext context;
6034 context->Global()->Set(v8_str("obj"), templ->NewInstance());
6035
6036 const char* code =
6037 "try {"
6038 " obj[0] = 239;"
6039 " for (var i = 0; i < 100; i++) {"
6040 " var v = obj[0];"
6041 " if (v != 0) throw 'Wrong value ' + v + ' at iteration ' + i;"
6042 " }"
6043 " 'PASSED'"
6044 "} catch(e) {"
6045 " e"
6046 "}";
6047 ExpectString(code, "PASSED");
6048}
6049
6050
ager@chromium.org5c838252010-02-19 08:53:10 +00006051THREADED_TEST(IndexedInterceptorWithAccessorCheck) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00006052 v8::Isolate* isolate = CcTest::isolate();
6053 v8::HandleScope scope(isolate);
6054 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +00006055 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
6056
6057 LocalContext context;
6058 Local<v8::Object> obj = templ->NewInstance();
6059 obj->TurnOnAccessCheck();
6060 context->Global()->Set(v8_str("obj"), obj);
6061
6062 const char* code =
6063 "try {"
6064 " for (var i = 0; i < 100; i++) {"
6065 " var v = obj[0];"
6066 " if (v != undefined) throw 'Wrong value ' + v + ' at iteration ' + i;"
6067 " }"
6068 " 'PASSED'"
6069 "} catch(e) {"
6070 " e"
6071 "}";
6072 ExpectString(code, "PASSED");
6073}
6074
6075
6076THREADED_TEST(IndexedInterceptorWithAccessorCheckSwitchedOn) {
6077 i::FLAG_allow_natives_syntax = true;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00006078 v8::Isolate* isolate = CcTest::isolate();
6079 v8::HandleScope scope(isolate);
6080 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +00006081 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
6082
6083 LocalContext context;
6084 Local<v8::Object> obj = templ->NewInstance();
6085 context->Global()->Set(v8_str("obj"), obj);
6086
6087 const char* code =
6088 "try {"
6089 " for (var i = 0; i < 100; i++) {"
6090 " var expected = i;"
6091 " if (i == 5) {"
6092 " %EnableAccessChecks(obj);"
6093 " expected = undefined;"
6094 " }"
6095 " var v = obj[i];"
6096 " if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
6097 " if (i == 5) %DisableAccessChecks(obj);"
6098 " }"
6099 " 'PASSED'"
6100 "} catch(e) {"
6101 " e"
6102 "}";
6103 ExpectString(code, "PASSED");
6104}
6105
6106
6107THREADED_TEST(IndexedInterceptorWithDifferentIndices) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00006108 v8::Isolate* isolate = CcTest::isolate();
6109 v8::HandleScope scope(isolate);
6110 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +00006111 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
6112
6113 LocalContext context;
6114 Local<v8::Object> obj = templ->NewInstance();
6115 context->Global()->Set(v8_str("obj"), obj);
6116
6117 const char* code =
6118 "try {"
6119 " for (var i = 0; i < 100; i++) {"
6120 " var v = obj[i];"
6121 " if (v != i) throw 'Wrong value ' + v + ' at iteration ' + i;"
6122 " }"
6123 " 'PASSED'"
6124 "} catch(e) {"
6125 " e"
6126 "}";
6127 ExpectString(code, "PASSED");
6128}
6129
6130
kmillikin@chromium.orgf05f2912010-09-30 10:07:24 +00006131THREADED_TEST(IndexedInterceptorWithNegativeIndices) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00006132 v8::Isolate* isolate = CcTest::isolate();
6133 v8::HandleScope scope(isolate);
6134 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
kmillikin@chromium.orgf05f2912010-09-30 10:07:24 +00006135 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
6136
6137 LocalContext context;
6138 Local<v8::Object> obj = templ->NewInstance();
6139 context->Global()->Set(v8_str("obj"), obj);
6140
6141 const char* code =
6142 "try {"
6143 " for (var i = 0; i < 100; i++) {"
6144 " var expected = i;"
6145 " var key = i;"
6146 " if (i == 25) {"
6147 " key = -1;"
6148 " expected = undefined;"
6149 " }"
6150 " if (i == 50) {"
6151 " /* probe minimal Smi number on 32-bit platforms */"
6152 " key = -(1 << 30);"
6153 " expected = undefined;"
6154 " }"
6155 " if (i == 75) {"
6156 " /* probe minimal Smi number on 64-bit platforms */"
6157 " key = 1 << 31;"
6158 " expected = undefined;"
6159 " }"
6160 " var v = obj[key];"
6161 " if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
6162 " }"
6163 " 'PASSED'"
6164 "} catch(e) {"
6165 " e"
6166 "}";
6167 ExpectString(code, "PASSED");
6168}
6169
6170
ager@chromium.org5c838252010-02-19 08:53:10 +00006171THREADED_TEST(IndexedInterceptorWithNotSmiLookup) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00006172 v8::Isolate* isolate = CcTest::isolate();
6173 v8::HandleScope scope(isolate);
6174 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +00006175 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
6176
6177 LocalContext context;
6178 Local<v8::Object> obj = templ->NewInstance();
6179 context->Global()->Set(v8_str("obj"), obj);
6180
6181 const char* code =
6182 "try {"
6183 " for (var i = 0; i < 100; i++) {"
6184 " var expected = i;"
kmillikin@chromium.orgf05f2912010-09-30 10:07:24 +00006185 " var key = i;"
ager@chromium.org5c838252010-02-19 08:53:10 +00006186 " if (i == 50) {"
kmillikin@chromium.orgf05f2912010-09-30 10:07:24 +00006187 " key = 'foobar';"
ager@chromium.org5c838252010-02-19 08:53:10 +00006188 " expected = undefined;"
6189 " }"
kmillikin@chromium.orgf05f2912010-09-30 10:07:24 +00006190 " var v = obj[key];"
ager@chromium.org5c838252010-02-19 08:53:10 +00006191 " if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
6192 " }"
6193 " 'PASSED'"
6194 "} catch(e) {"
6195 " e"
6196 "}";
6197 ExpectString(code, "PASSED");
6198}
6199
6200
6201THREADED_TEST(IndexedInterceptorGoingMegamorphic) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00006202 v8::Isolate* isolate = CcTest::isolate();
6203 v8::HandleScope scope(isolate);
6204 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +00006205 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
6206
6207 LocalContext context;
6208 Local<v8::Object> obj = templ->NewInstance();
6209 context->Global()->Set(v8_str("obj"), obj);
6210
6211 const char* code =
6212 "var original = obj;"
6213 "try {"
6214 " for (var i = 0; i < 100; i++) {"
6215 " var expected = i;"
6216 " if (i == 50) {"
6217 " obj = {50: 'foobar'};"
6218 " expected = 'foobar';"
6219 " }"
6220 " var v = obj[i];"
6221 " if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
6222 " if (i == 50) obj = original;"
6223 " }"
6224 " 'PASSED'"
6225 "} catch(e) {"
6226 " e"
6227 "}";
6228 ExpectString(code, "PASSED");
6229}
6230
6231
6232THREADED_TEST(IndexedInterceptorReceiverTurningSmi) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00006233 v8::Isolate* isolate = CcTest::isolate();
6234 v8::HandleScope scope(isolate);
6235 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +00006236 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
6237
6238 LocalContext context;
6239 Local<v8::Object> obj = templ->NewInstance();
6240 context->Global()->Set(v8_str("obj"), obj);
6241
6242 const char* code =
6243 "var original = obj;"
6244 "try {"
6245 " for (var i = 0; i < 100; i++) {"
6246 " var expected = i;"
6247 " if (i == 5) {"
6248 " obj = 239;"
6249 " expected = undefined;"
6250 " }"
6251 " var v = obj[i];"
6252 " if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
6253 " if (i == 5) obj = original;"
6254 " }"
6255 " 'PASSED'"
6256 "} catch(e) {"
6257 " e"
6258 "}";
6259 ExpectString(code, "PASSED");
6260}
6261
6262
6263THREADED_TEST(IndexedInterceptorOnProto) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00006264 v8::Isolate* isolate = CcTest::isolate();
6265 v8::HandleScope scope(isolate);
6266 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +00006267 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
6268
6269 LocalContext context;
6270 Local<v8::Object> obj = templ->NewInstance();
6271 context->Global()->Set(v8_str("obj"), obj);
6272
6273 const char* code =
6274 "var o = {__proto__: obj};"
6275 "try {"
6276 " for (var i = 0; i < 100; i++) {"
6277 " var v = o[i];"
6278 " if (v != i) throw 'Wrong value ' + v + ' at iteration ' + i;"
6279 " }"
6280 " 'PASSED'"
6281 "} catch(e) {"
6282 " e"
6283 "}";
6284 ExpectString(code, "PASSED");
6285}
6286
6287
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006288THREADED_TEST(MultiContexts) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00006289 v8::Isolate* isolate = CcTest::isolate();
6290 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00006291 v8::Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00006292 templ->Set(v8_str("dummy"), v8::FunctionTemplate::New(isolate,
6293 DummyCallHandler));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006294
6295 Local<String> password = v8_str("Password");
6296
6297 // Create an environment
6298 LocalContext context0(0, templ);
6299 context0->SetSecurityToken(password);
6300 v8::Handle<v8::Object> global0 = context0->Global();
6301 global0->Set(v8_str("custom"), v8_num(1234));
6302 CHECK_EQ(1234, global0->Get(v8_str("custom"))->Int32Value());
6303
6304 // Create an independent environment
6305 LocalContext context1(0, templ);
6306 context1->SetSecurityToken(password);
6307 v8::Handle<v8::Object> global1 = context1->Global();
6308 global1->Set(v8_str("custom"), v8_num(1234));
6309 CHECK_NE(global0, global1);
6310 CHECK_EQ(1234, global0->Get(v8_str("custom"))->Int32Value());
6311 CHECK_EQ(1234, global1->Get(v8_str("custom"))->Int32Value());
6312
6313 // Now create a new context with the old global
6314 LocalContext context2(0, templ, global1);
6315 context2->SetSecurityToken(password);
6316 v8::Handle<v8::Object> global2 = context2->Global();
6317 CHECK_EQ(global1, global2);
6318 CHECK_EQ(0, global1->Get(v8_str("custom"))->Int32Value());
6319 CHECK_EQ(0, global2->Get(v8_str("custom"))->Int32Value());
6320}
6321
6322
6323THREADED_TEST(FunctionPrototypeAcrossContexts) {
6324 // Make sure that functions created by cloning boilerplates cannot
6325 // communicate through their __proto__ field.
6326
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006327 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006328
6329 LocalContext env0;
6330 v8::Handle<v8::Object> global0 =
6331 env0->Global();
6332 v8::Handle<v8::Object> object0 =
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00006333 global0->Get(v8_str("Object")).As<v8::Object>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006334 v8::Handle<v8::Object> tostring0 =
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00006335 object0->Get(v8_str("toString")).As<v8::Object>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006336 v8::Handle<v8::Object> proto0 =
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00006337 tostring0->Get(v8_str("__proto__")).As<v8::Object>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006338 proto0->Set(v8_str("custom"), v8_num(1234));
6339
6340 LocalContext env1;
6341 v8::Handle<v8::Object> global1 =
6342 env1->Global();
6343 v8::Handle<v8::Object> object1 =
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00006344 global1->Get(v8_str("Object")).As<v8::Object>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006345 v8::Handle<v8::Object> tostring1 =
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00006346 object1->Get(v8_str("toString")).As<v8::Object>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006347 v8::Handle<v8::Object> proto1 =
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00006348 tostring1->Get(v8_str("__proto__")).As<v8::Object>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006349 CHECK(!proto1->Has(v8_str("custom")));
6350}
6351
6352
6353THREADED_TEST(Regress892105) {
6354 // Make sure that object and array literals created by cloning
6355 // boilerplates cannot communicate through their __proto__
6356 // field. This is rather difficult to check, but we try to add stuff
6357 // to Object.prototype and Array.prototype and create a new
6358 // environment. This should succeed.
6359
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006360 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006361
6362 Local<String> source = v8_str("Object.prototype.obj = 1234;"
6363 "Array.prototype.arr = 4567;"
6364 "8901");
6365
6366 LocalContext env0;
6367 Local<Script> script0 = Script::Compile(source);
6368 CHECK_EQ(8901.0, script0->Run()->NumberValue());
6369
6370 LocalContext env1;
6371 Local<Script> script1 = Script::Compile(source);
6372 CHECK_EQ(8901.0, script1->Run()->NumberValue());
6373}
6374
6375
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006376THREADED_TEST(UndetectableObject) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006377 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00006378 v8::HandleScope scope(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006379
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00006380 Local<v8::FunctionTemplate> desc =
6381 v8::FunctionTemplate::New(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006382 desc->InstanceTemplate()->MarkAsUndetectable(); // undetectable
6383
6384 Local<v8::Object> obj = desc->GetFunction()->NewInstance();
6385 env->Global()->Set(v8_str("undetectable"), obj);
6386
6387 ExpectString("undetectable.toString()", "[object Object]");
6388 ExpectString("typeof undetectable", "undefined");
6389 ExpectString("typeof(undetectable)", "undefined");
6390 ExpectBoolean("typeof undetectable == 'undefined'", true);
6391 ExpectBoolean("typeof undetectable == 'object'", false);
6392 ExpectBoolean("if (undetectable) { true; } else { false; }", false);
6393 ExpectBoolean("!undetectable", true);
6394
6395 ExpectObject("true&&undetectable", obj);
6396 ExpectBoolean("false&&undetectable", false);
6397 ExpectBoolean("true||undetectable", true);
6398 ExpectObject("false||undetectable", obj);
6399
6400 ExpectObject("undetectable&&true", obj);
6401 ExpectObject("undetectable&&false", obj);
6402 ExpectBoolean("undetectable||true", true);
6403 ExpectBoolean("undetectable||false", false);
6404
6405 ExpectBoolean("undetectable==null", true);
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00006406 ExpectBoolean("null==undetectable", true);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006407 ExpectBoolean("undetectable==undefined", true);
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00006408 ExpectBoolean("undefined==undetectable", true);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006409 ExpectBoolean("undetectable==undetectable", true);
6410
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00006411
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006412 ExpectBoolean("undetectable===null", false);
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00006413 ExpectBoolean("null===undetectable", false);
6414 ExpectBoolean("undetectable===undefined", false);
6415 ExpectBoolean("undefined===undetectable", false);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006416 ExpectBoolean("undetectable===undetectable", true);
6417}
6418
6419
ager@chromium.org04921a82011-06-27 13:21:41 +00006420THREADED_TEST(VoidLiteral) {
ager@chromium.org04921a82011-06-27 13:21:41 +00006421 LocalContext env;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00006422 v8::Isolate* isolate = env->GetIsolate();
6423 v8::HandleScope scope(isolate);
ager@chromium.org04921a82011-06-27 13:21:41 +00006424
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00006425 Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
ager@chromium.org04921a82011-06-27 13:21:41 +00006426 desc->InstanceTemplate()->MarkAsUndetectable(); // undetectable
6427
6428 Local<v8::Object> obj = desc->GetFunction()->NewInstance();
6429 env->Global()->Set(v8_str("undetectable"), obj);
6430
6431 ExpectBoolean("undefined == void 0", true);
6432 ExpectBoolean("undetectable == void 0", true);
6433 ExpectBoolean("null == void 0", true);
6434 ExpectBoolean("undefined === void 0", true);
6435 ExpectBoolean("undetectable === void 0", false);
6436 ExpectBoolean("null === void 0", false);
6437
6438 ExpectBoolean("void 0 == undefined", true);
6439 ExpectBoolean("void 0 == undetectable", true);
6440 ExpectBoolean("void 0 == null", true);
6441 ExpectBoolean("void 0 === undefined", true);
6442 ExpectBoolean("void 0 === undetectable", false);
6443 ExpectBoolean("void 0 === null", false);
6444
6445 ExpectString("(function() {"
6446 " try {"
6447 " return x === void 0;"
6448 " } catch(e) {"
6449 " return e.toString();"
6450 " }"
6451 "})()",
6452 "ReferenceError: x is not defined");
6453 ExpectString("(function() {"
6454 " try {"
6455 " return void 0 === x;"
6456 " } catch(e) {"
6457 " return e.toString();"
6458 " }"
6459 "})()",
6460 "ReferenceError: x is not defined");
6461}
6462
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00006463
6464THREADED_TEST(ExtensibleOnUndetectable) {
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00006465 LocalContext env;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00006466 v8::Isolate* isolate = env->GetIsolate();
6467 v8::HandleScope scope(isolate);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00006468
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00006469 Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00006470 desc->InstanceTemplate()->MarkAsUndetectable(); // undetectable
6471
6472 Local<v8::Object> obj = desc->GetFunction()->NewInstance();
6473 env->Global()->Set(v8_str("undetectable"), obj);
6474
6475 Local<String> source = v8_str("undetectable.x = 42;"
6476 "undetectable.x");
6477
6478 Local<Script> script = Script::Compile(source);
6479
ulan@chromium.org0f13e742014-01-03 15:51:11 +00006480 CHECK_EQ(v8::Integer::New(isolate, 42), script->Run());
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00006481
6482 ExpectBoolean("Object.isExtensible(undetectable)", true);
6483
6484 source = v8_str("Object.preventExtensions(undetectable);");
6485 script = Script::Compile(source);
6486 script->Run();
6487 ExpectBoolean("Object.isExtensible(undetectable)", false);
6488
6489 source = v8_str("undetectable.y = 2000;");
6490 script = Script::Compile(source);
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00006491 script->Run();
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00006492 ExpectBoolean("undetectable.y == undefined", true);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00006493}
6494
6495
6496
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006497THREADED_TEST(UndetectableString) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006498 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00006499 v8::HandleScope scope(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006500
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00006501 Local<String> obj = String::NewFromUtf8(env->GetIsolate(), "foo",
6502 String::kUndetectableString);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006503 env->Global()->Set(v8_str("undetectable"), obj);
6504
6505 ExpectString("undetectable", "foo");
6506 ExpectString("typeof undetectable", "undefined");
6507 ExpectString("typeof(undetectable)", "undefined");
6508 ExpectBoolean("typeof undetectable == 'undefined'", true);
6509 ExpectBoolean("typeof undetectable == 'string'", false);
6510 ExpectBoolean("if (undetectable) { true; } else { false; }", false);
6511 ExpectBoolean("!undetectable", true);
6512
6513 ExpectObject("true&&undetectable", obj);
6514 ExpectBoolean("false&&undetectable", false);
6515 ExpectBoolean("true||undetectable", true);
6516 ExpectObject("false||undetectable", obj);
6517
6518 ExpectObject("undetectable&&true", obj);
6519 ExpectObject("undetectable&&false", obj);
6520 ExpectBoolean("undetectable||true", true);
6521 ExpectBoolean("undetectable||false", false);
6522
6523 ExpectBoolean("undetectable==null", true);
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00006524 ExpectBoolean("null==undetectable", true);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006525 ExpectBoolean("undetectable==undefined", true);
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00006526 ExpectBoolean("undefined==undetectable", true);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006527 ExpectBoolean("undetectable==undetectable", true);
6528
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00006529
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006530 ExpectBoolean("undetectable===null", false);
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00006531 ExpectBoolean("null===undetectable", false);
6532 ExpectBoolean("undetectable===undefined", false);
6533 ExpectBoolean("undefined===undetectable", false);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006534 ExpectBoolean("undetectable===undetectable", true);
6535}
6536
6537
vegorov@chromium.org7304bca2011-05-16 12:14:13 +00006538TEST(UndetectableOptimized) {
6539 i::FLAG_allow_natives_syntax = true;
vegorov@chromium.org7304bca2011-05-16 12:14:13 +00006540 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00006541 v8::HandleScope scope(env->GetIsolate());
vegorov@chromium.org7304bca2011-05-16 12:14:13 +00006542
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00006543 Local<String> obj = String::NewFromUtf8(env->GetIsolate(), "foo",
6544 String::kUndetectableString);
vegorov@chromium.org7304bca2011-05-16 12:14:13 +00006545 env->Global()->Set(v8_str("undetectable"), obj);
6546 env->Global()->Set(v8_str("detectable"), v8_str("bar"));
6547
6548 ExpectString(
6549 "function testBranch() {"
6550 " if (!%_IsUndetectableObject(undetectable)) throw 1;"
6551 " if (%_IsUndetectableObject(detectable)) throw 2;"
6552 "}\n"
6553 "function testBool() {"
6554 " var b1 = !%_IsUndetectableObject(undetectable);"
6555 " var b2 = %_IsUndetectableObject(detectable);"
6556 " if (b1) throw 3;"
6557 " if (b2) throw 4;"
6558 " return b1 == b2;"
6559 "}\n"
6560 "%OptimizeFunctionOnNextCall(testBranch);"
6561 "%OptimizeFunctionOnNextCall(testBool);"
6562 "for (var i = 0; i < 10; i++) {"
6563 " testBranch();"
6564 " testBool();"
6565 "}\n"
6566 "\"PASS\"",
6567 "PASS");
6568}
6569
6570
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006571template <typename T> static void USE(T) { }
6572
6573
machenbach@chromium.orgafbdadc2013-12-09 16:12:18 +00006574// The point of this test is type checking. We run it only so compilers
6575// don't complain about an unused function.
6576TEST(PersistentHandles) {
6577 LocalContext env;
6578 v8::Isolate* isolate = CcTest::isolate();
6579 v8::HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006580 Local<String> str = v8_str("foo");
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00006581 v8::Persistent<String> p_str(isolate, str);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00006582 p_str.Reset();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006583 Local<Script> scr = Script::Compile(v8_str(""));
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00006584 v8::Persistent<Script> p_scr(isolate, scr);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00006585 p_scr.Reset();
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00006586 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00006587 v8::Persistent<ObjectTemplate> p_templ(isolate, templ);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00006588 p_templ.Reset();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006589}
6590
6591
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00006592static void HandleLogDelegator(
6593 const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006594 ApiTestFuzzer::Fuzz();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006595}
6596
6597
6598THREADED_TEST(GlobalObjectTemplate) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006599 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006600 v8::HandleScope handle_scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00006601 Local<ObjectTemplate> global_template = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006602 global_template->Set(v8_str("JSNI_Log"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00006603 v8::FunctionTemplate::New(isolate, HandleLogDelegator));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006604 v8::Local<Context> context = Context::New(isolate, 0, global_template);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006605 Context::Scope context_scope(context);
6606 Script::Compile(v8_str("JSNI_Log('LOG')"))->Run();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006607}
6608
6609
6610static const char* kSimpleExtensionSource =
6611 "function Foo() {"
6612 " return 4;"
6613 "}";
6614
6615
6616THREADED_TEST(SimpleExtensions) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006617 v8::HandleScope handle_scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006618 v8::RegisterExtension(new Extension("simpletest", kSimpleExtensionSource));
6619 const char* extension_names[] = { "simpletest" };
6620 v8::ExtensionConfiguration extensions(1, extension_names);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006621 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006622 Context::New(CcTest::isolate(), &extensions);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006623 Context::Scope lock(context);
6624 v8::Handle<Value> result = Script::Compile(v8_str("Foo()"))->Run();
ulan@chromium.org0f13e742014-01-03 15:51:11 +00006625 CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 4));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006626}
6627
6628
danno@chromium.org412fa512012-09-14 13:28:26 +00006629THREADED_TEST(NullExtensions) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006630 v8::HandleScope handle_scope(CcTest::isolate());
danno@chromium.org412fa512012-09-14 13:28:26 +00006631 v8::RegisterExtension(new Extension("nulltest", NULL));
6632 const char* extension_names[] = { "nulltest" };
6633 v8::ExtensionConfiguration extensions(1, extension_names);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006634 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006635 Context::New(CcTest::isolate(), &extensions);
danno@chromium.org412fa512012-09-14 13:28:26 +00006636 Context::Scope lock(context);
6637 v8::Handle<Value> result = Script::Compile(v8_str("1+3"))->Run();
ulan@chromium.org0f13e742014-01-03 15:51:11 +00006638 CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 4));
danno@chromium.org412fa512012-09-14 13:28:26 +00006639}
6640
6641
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00006642static const char* kEmbeddedExtensionSource =
6643 "function Ret54321(){return 54321;}~~@@$"
6644 "$%% THIS IS A SERIES OF NON-NULL-TERMINATED STRINGS.";
6645static const int kEmbeddedExtensionSourceValidLen = 34;
6646
6647
6648THREADED_TEST(ExtensionMissingSourceLength) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006649 v8::HandleScope handle_scope(CcTest::isolate());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00006650 v8::RegisterExtension(new Extension("srclentest_fail",
6651 kEmbeddedExtensionSource));
6652 const char* extension_names[] = { "srclentest_fail" };
6653 v8::ExtensionConfiguration extensions(1, extension_names);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006654 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006655 Context::New(CcTest::isolate(), &extensions);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00006656 CHECK_EQ(0, *context);
6657}
6658
6659
6660THREADED_TEST(ExtensionWithSourceLength) {
6661 for (int source_len = kEmbeddedExtensionSourceValidLen - 1;
6662 source_len <= kEmbeddedExtensionSourceValidLen + 1; ++source_len) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006663 v8::HandleScope handle_scope(CcTest::isolate());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00006664 i::ScopedVector<char> extension_name(32);
6665 i::OS::SNPrintF(extension_name, "ext #%d", source_len);
6666 v8::RegisterExtension(new Extension(extension_name.start(),
6667 kEmbeddedExtensionSource, 0, 0,
6668 source_len));
6669 const char* extension_names[1] = { extension_name.start() };
6670 v8::ExtensionConfiguration extensions(1, extension_names);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006671 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006672 Context::New(CcTest::isolate(), &extensions);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00006673 if (source_len == kEmbeddedExtensionSourceValidLen) {
6674 Context::Scope lock(context);
6675 v8::Handle<Value> result = Script::Compile(v8_str("Ret54321()"))->Run();
ulan@chromium.org0f13e742014-01-03 15:51:11 +00006676 CHECK_EQ(v8::Integer::New(CcTest::isolate(), 54321), result);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00006677 } else {
6678 // Anything but exactly the right length should fail to compile.
6679 CHECK_EQ(0, *context);
6680 }
6681 }
6682}
6683
6684
ager@chromium.org18ad94b2009-09-02 08:22:29 +00006685static const char* kEvalExtensionSource1 =
6686 "function UseEval1() {"
kasperl@chromium.org2d18d102009-04-15 13:27:32 +00006687 " var x = 42;"
6688 " return eval('x');"
6689 "}";
6690
6691
ager@chromium.org18ad94b2009-09-02 08:22:29 +00006692static const char* kEvalExtensionSource2 =
6693 "(function() {"
6694 " var x = 42;"
6695 " function e() {"
6696 " return eval('x');"
6697 " }"
6698 " this.UseEval2 = e;"
6699 "})()";
6700
6701
kasperl@chromium.org2d18d102009-04-15 13:27:32 +00006702THREADED_TEST(UseEvalFromExtension) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006703 v8::HandleScope handle_scope(CcTest::isolate());
ager@chromium.org18ad94b2009-09-02 08:22:29 +00006704 v8::RegisterExtension(new Extension("evaltest1", kEvalExtensionSource1));
6705 v8::RegisterExtension(new Extension("evaltest2", kEvalExtensionSource2));
6706 const char* extension_names[] = { "evaltest1", "evaltest2" };
6707 v8::ExtensionConfiguration extensions(2, extension_names);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006708 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006709 Context::New(CcTest::isolate(), &extensions);
kasperl@chromium.org2d18d102009-04-15 13:27:32 +00006710 Context::Scope lock(context);
ager@chromium.org18ad94b2009-09-02 08:22:29 +00006711 v8::Handle<Value> result = Script::Compile(v8_str("UseEval1()"))->Run();
ulan@chromium.org0f13e742014-01-03 15:51:11 +00006712 CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 42));
ager@chromium.org18ad94b2009-09-02 08:22:29 +00006713 result = Script::Compile(v8_str("UseEval2()"))->Run();
ulan@chromium.org0f13e742014-01-03 15:51:11 +00006714 CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 42));
kasperl@chromium.org2d18d102009-04-15 13:27:32 +00006715}
6716
6717
ager@chromium.org18ad94b2009-09-02 08:22:29 +00006718static const char* kWithExtensionSource1 =
6719 "function UseWith1() {"
kasperl@chromium.org2d18d102009-04-15 13:27:32 +00006720 " var x = 42;"
6721 " with({x:87}) { return x; }"
6722 "}";
6723
6724
ager@chromium.org18ad94b2009-09-02 08:22:29 +00006725
6726static const char* kWithExtensionSource2 =
6727 "(function() {"
6728 " var x = 42;"
6729 " function e() {"
6730 " with ({x:87}) { return x; }"
6731 " }"
6732 " this.UseWith2 = e;"
6733 "})()";
6734
6735
kasperl@chromium.org2d18d102009-04-15 13:27:32 +00006736THREADED_TEST(UseWithFromExtension) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006737 v8::HandleScope handle_scope(CcTest::isolate());
ager@chromium.org18ad94b2009-09-02 08:22:29 +00006738 v8::RegisterExtension(new Extension("withtest1", kWithExtensionSource1));
6739 v8::RegisterExtension(new Extension("withtest2", kWithExtensionSource2));
6740 const char* extension_names[] = { "withtest1", "withtest2" };
6741 v8::ExtensionConfiguration extensions(2, extension_names);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006742 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006743 Context::New(CcTest::isolate(), &extensions);
kasperl@chromium.org2d18d102009-04-15 13:27:32 +00006744 Context::Scope lock(context);
ager@chromium.org18ad94b2009-09-02 08:22:29 +00006745 v8::Handle<Value> result = Script::Compile(v8_str("UseWith1()"))->Run();
ulan@chromium.org0f13e742014-01-03 15:51:11 +00006746 CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 87));
ager@chromium.org18ad94b2009-09-02 08:22:29 +00006747 result = Script::Compile(v8_str("UseWith2()"))->Run();
ulan@chromium.org0f13e742014-01-03 15:51:11 +00006748 CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 87));
kasperl@chromium.org2d18d102009-04-15 13:27:32 +00006749}
6750
6751
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006752THREADED_TEST(AutoExtensions) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006753 v8::HandleScope handle_scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006754 Extension* extension = new Extension("autotest", kSimpleExtensionSource);
6755 extension->set_auto_enable(true);
6756 v8::RegisterExtension(extension);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006757 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006758 Context::New(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006759 Context::Scope lock(context);
6760 v8::Handle<Value> result = Script::Compile(v8_str("Foo()"))->Run();
ulan@chromium.org0f13e742014-01-03 15:51:11 +00006761 CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 4));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006762}
6763
6764
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00006765static const char* kSyntaxErrorInExtensionSource =
6766 "[";
6767
6768
6769// Test that a syntax error in an extension does not cause a fatal
6770// error but results in an empty context.
6771THREADED_TEST(SyntaxErrorExtensions) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006772 v8::HandleScope handle_scope(CcTest::isolate());
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00006773 v8::RegisterExtension(new Extension("syntaxerror",
6774 kSyntaxErrorInExtensionSource));
6775 const char* extension_names[] = { "syntaxerror" };
6776 v8::ExtensionConfiguration extensions(1, extension_names);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006777 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006778 Context::New(CcTest::isolate(), &extensions);
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00006779 CHECK(context.IsEmpty());
6780}
6781
6782
6783static const char* kExceptionInExtensionSource =
6784 "throw 42";
6785
6786
6787// Test that an exception when installing an extension does not cause
6788// a fatal error but results in an empty context.
6789THREADED_TEST(ExceptionExtensions) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006790 v8::HandleScope handle_scope(CcTest::isolate());
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00006791 v8::RegisterExtension(new Extension("exception",
6792 kExceptionInExtensionSource));
6793 const char* extension_names[] = { "exception" };
6794 v8::ExtensionConfiguration extensions(1, extension_names);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006795 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006796 Context::New(CcTest::isolate(), &extensions);
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00006797 CHECK(context.IsEmpty());
6798}
6799
6800
ager@chromium.org5b2fbee2010-09-08 06:38:15 +00006801static const char* kNativeCallInExtensionSource =
6802 "function call_runtime_last_index_of(x) {"
6803 " return %StringLastIndexOf(x, 'bob', 10);"
6804 "}";
6805
6806
6807static const char* kNativeCallTest =
6808 "call_runtime_last_index_of('bobbobboellebobboellebobbob');";
6809
6810// Test that a native runtime calls are supported in extensions.
6811THREADED_TEST(NativeCallInExtensions) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006812 v8::HandleScope handle_scope(CcTest::isolate());
ager@chromium.org5b2fbee2010-09-08 06:38:15 +00006813 v8::RegisterExtension(new Extension("nativecall",
6814 kNativeCallInExtensionSource));
6815 const char* extension_names[] = { "nativecall" };
6816 v8::ExtensionConfiguration extensions(1, extension_names);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006817 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006818 Context::New(CcTest::isolate(), &extensions);
ager@chromium.org5b2fbee2010-09-08 06:38:15 +00006819 Context::Scope lock(context);
6820 v8::Handle<Value> result = Script::Compile(v8_str(kNativeCallTest))->Run();
ulan@chromium.org0f13e742014-01-03 15:51:11 +00006821 CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 3));
ager@chromium.org5b2fbee2010-09-08 06:38:15 +00006822}
6823
6824
whesse@chromium.org7b260152011-06-20 15:33:18 +00006825class NativeFunctionExtension : public Extension {
6826 public:
6827 NativeFunctionExtension(const char* name,
6828 const char* source,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00006829 v8::FunctionCallback fun = &Echo)
whesse@chromium.org7b260152011-06-20 15:33:18 +00006830 : Extension(name, source),
6831 function_(fun) { }
6832
machenbach@chromium.org9f18d912013-11-28 13:42:41 +00006833 virtual v8::Handle<v8::FunctionTemplate> GetNativeFunctionTemplate(
6834 v8::Isolate* isolate,
whesse@chromium.org7b260152011-06-20 15:33:18 +00006835 v8::Handle<v8::String> name) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00006836 return v8::FunctionTemplate::New(isolate, function_);
whesse@chromium.org7b260152011-06-20 15:33:18 +00006837 }
6838
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00006839 static void Echo(const v8::FunctionCallbackInfo<v8::Value>& args) {
6840 if (args.Length() >= 1) args.GetReturnValue().Set(args[0]);
whesse@chromium.org7b260152011-06-20 15:33:18 +00006841 }
6842 private:
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00006843 v8::FunctionCallback function_;
whesse@chromium.org7b260152011-06-20 15:33:18 +00006844};
6845
6846
6847THREADED_TEST(NativeFunctionDeclaration) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006848 v8::HandleScope handle_scope(CcTest::isolate());
whesse@chromium.org7b260152011-06-20 15:33:18 +00006849 const char* name = "nativedecl";
6850 v8::RegisterExtension(new NativeFunctionExtension(name,
6851 "native function foo();"));
6852 const char* extension_names[] = { name };
6853 v8::ExtensionConfiguration extensions(1, extension_names);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006854 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006855 Context::New(CcTest::isolate(), &extensions);
whesse@chromium.org7b260152011-06-20 15:33:18 +00006856 Context::Scope lock(context);
6857 v8::Handle<Value> result = Script::Compile(v8_str("foo(42);"))->Run();
ulan@chromium.org0f13e742014-01-03 15:51:11 +00006858 CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 42));
whesse@chromium.org7b260152011-06-20 15:33:18 +00006859}
6860
6861
6862THREADED_TEST(NativeFunctionDeclarationError) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006863 v8::HandleScope handle_scope(CcTest::isolate());
lrn@chromium.org67e236d2011-06-23 10:18:16 +00006864 const char* name = "nativedeclerr";
whesse@chromium.org7b260152011-06-20 15:33:18 +00006865 // Syntax error in extension code.
6866 v8::RegisterExtension(new NativeFunctionExtension(name,
6867 "native\nfunction foo();"));
6868 const char* extension_names[] = { name };
6869 v8::ExtensionConfiguration extensions(1, extension_names);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006870 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006871 Context::New(CcTest::isolate(), &extensions);
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00006872 CHECK(context.IsEmpty());
whesse@chromium.org7b260152011-06-20 15:33:18 +00006873}
6874
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00006875
whesse@chromium.org7b260152011-06-20 15:33:18 +00006876THREADED_TEST(NativeFunctionDeclarationErrorEscape) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006877 v8::HandleScope handle_scope(CcTest::isolate());
lrn@chromium.org67e236d2011-06-23 10:18:16 +00006878 const char* name = "nativedeclerresc";
whesse@chromium.org7b260152011-06-20 15:33:18 +00006879 // Syntax error in extension code - escape code in "native" means that
6880 // it's not treated as a keyword.
6881 v8::RegisterExtension(new NativeFunctionExtension(
6882 name,
6883 "nativ\\u0065 function foo();"));
6884 const char* extension_names[] = { name };
6885 v8::ExtensionConfiguration extensions(1, extension_names);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006886 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006887 Context::New(CcTest::isolate(), &extensions);
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00006888 CHECK(context.IsEmpty());
whesse@chromium.org7b260152011-06-20 15:33:18 +00006889}
6890
6891
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006892static void CheckDependencies(const char* name, const char* expected) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006893 v8::HandleScope handle_scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006894 v8::ExtensionConfiguration config(1, &name);
6895 LocalContext context(&config);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00006896 CHECK_EQ(String::NewFromUtf8(CcTest::isolate(), expected),
6897 context->Global()->Get(v8_str("loaded")));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006898}
6899
6900
6901/*
6902 * Configuration:
6903 *
6904 * /-- B <--\
6905 * A <- -- D <-- E
6906 * \-- C <--/
6907 */
6908THREADED_TEST(ExtensionDependency) {
6909 static const char* kEDeps[] = { "D" };
6910 v8::RegisterExtension(new Extension("E", "this.loaded += 'E';", 1, kEDeps));
6911 static const char* kDDeps[] = { "B", "C" };
6912 v8::RegisterExtension(new Extension("D", "this.loaded += 'D';", 2, kDDeps));
6913 static const char* kBCDeps[] = { "A" };
6914 v8::RegisterExtension(new Extension("B", "this.loaded += 'B';", 1, kBCDeps));
6915 v8::RegisterExtension(new Extension("C", "this.loaded += 'C';", 1, kBCDeps));
6916 v8::RegisterExtension(new Extension("A", "this.loaded += 'A';"));
6917 CheckDependencies("A", "undefinedA");
6918 CheckDependencies("B", "undefinedAB");
6919 CheckDependencies("C", "undefinedAC");
6920 CheckDependencies("D", "undefinedABCD");
6921 CheckDependencies("E", "undefinedABCDE");
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006922 v8::HandleScope handle_scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006923 static const char* exts[2] = { "C", "E" };
6924 v8::ExtensionConfiguration config(2, exts);
6925 LocalContext context(&config);
6926 CHECK_EQ(v8_str("undefinedACBDE"), context->Global()->Get(v8_str("loaded")));
6927}
6928
6929
6930static const char* kExtensionTestScript =
6931 "native function A();"
6932 "native function B();"
6933 "native function C();"
6934 "function Foo(i) {"
6935 " if (i == 0) return A();"
6936 " if (i == 1) return B();"
6937 " if (i == 2) return C();"
6938 "}";
6939
6940
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00006941static void CallFun(const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006942 ApiTestFuzzer::Fuzz();
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00006943 if (args.IsConstructCall()) {
6944 args.This()->Set(v8_str("data"), args.Data());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00006945 args.GetReturnValue().SetNull();
6946 return;
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00006947 }
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00006948 args.GetReturnValue().Set(args.Data());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006949}
6950
6951
6952class FunctionExtension : public Extension {
6953 public:
6954 FunctionExtension() : Extension("functiontest", kExtensionTestScript) { }
machenbach@chromium.org9f18d912013-11-28 13:42:41 +00006955 virtual v8::Handle<v8::FunctionTemplate> GetNativeFunctionTemplate(
6956 v8::Isolate* isolate,
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006957 v8::Handle<String> name);
6958};
6959
6960
6961static int lookup_count = 0;
machenbach@chromium.org9f18d912013-11-28 13:42:41 +00006962v8::Handle<v8::FunctionTemplate> FunctionExtension::GetNativeFunctionTemplate(
6963 v8::Isolate* isolate, v8::Handle<String> name) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006964 lookup_count++;
6965 if (name->Equals(v8_str("A"))) {
ulan@chromium.org0f13e742014-01-03 15:51:11 +00006966 return v8::FunctionTemplate::New(
6967 isolate, CallFun, v8::Integer::New(isolate, 8));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006968 } else if (name->Equals(v8_str("B"))) {
ulan@chromium.org0f13e742014-01-03 15:51:11 +00006969 return v8::FunctionTemplate::New(
6970 isolate, CallFun, v8::Integer::New(isolate, 7));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006971 } else if (name->Equals(v8_str("C"))) {
ulan@chromium.org0f13e742014-01-03 15:51:11 +00006972 return v8::FunctionTemplate::New(
6973 isolate, CallFun, v8::Integer::New(isolate, 6));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006974 } else {
6975 return v8::Handle<v8::FunctionTemplate>();
6976 }
6977}
6978
6979
6980THREADED_TEST(FunctionLookup) {
6981 v8::RegisterExtension(new FunctionExtension());
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006982 v8::HandleScope handle_scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006983 static const char* exts[1] = { "functiontest" };
6984 v8::ExtensionConfiguration config(1, exts);
6985 LocalContext context(&config);
6986 CHECK_EQ(3, lookup_count);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00006987 CHECK_EQ(v8::Integer::New(CcTest::isolate(), 8),
6988 Script::Compile(v8_str("Foo(0)"))->Run());
6989 CHECK_EQ(v8::Integer::New(CcTest::isolate(), 7),
6990 Script::Compile(v8_str("Foo(1)"))->Run());
6991 CHECK_EQ(v8::Integer::New(CcTest::isolate(), 6),
6992 Script::Compile(v8_str("Foo(2)"))->Run());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006993}
6994
6995
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00006996THREADED_TEST(NativeFunctionConstructCall) {
6997 v8::RegisterExtension(new FunctionExtension());
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006998 v8::HandleScope handle_scope(CcTest::isolate());
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00006999 static const char* exts[1] = { "functiontest" };
7000 v8::ExtensionConfiguration config(1, exts);
7001 LocalContext context(&config);
7002 for (int i = 0; i < 10; i++) {
7003 // Run a few times to ensure that allocation of objects doesn't
7004 // change behavior of a constructor function.
ulan@chromium.org0f13e742014-01-03 15:51:11 +00007005 CHECK_EQ(v8::Integer::New(CcTest::isolate(), 8),
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00007006 Script::Compile(v8_str("(new A()).data"))->Run());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00007007 CHECK_EQ(v8::Integer::New(CcTest::isolate(), 7),
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00007008 Script::Compile(v8_str("(new B()).data"))->Run());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00007009 CHECK_EQ(v8::Integer::New(CcTest::isolate(), 6),
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00007010 Script::Compile(v8_str("(new C()).data"))->Run());
7011 }
7012}
7013
7014
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007015static const char* last_location;
7016static const char* last_message;
7017void StoringErrorCallback(const char* location, const char* message) {
7018 if (last_location == NULL) {
7019 last_location = location;
7020 last_message = message;
7021 }
7022}
7023
7024
7025// ErrorReporting creates a circular extensions configuration and
7026// tests that the fatal error handler gets called. This renders V8
7027// unusable and therefore this test cannot be run in parallel.
7028TEST(ErrorReporting) {
7029 v8::V8::SetFatalErrorHandler(StoringErrorCallback);
7030 static const char* aDeps[] = { "B" };
7031 v8::RegisterExtension(new Extension("A", "", 1, aDeps));
7032 static const char* bDeps[] = { "A" };
7033 v8::RegisterExtension(new Extension("B", "", 1, bDeps));
7034 last_location = NULL;
7035 v8::ExtensionConfiguration config(1, bDeps);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007036 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007037 Context::New(CcTest::isolate(), &config);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007038 CHECK(context.IsEmpty());
7039 CHECK_NE(last_location, NULL);
7040}
7041
7042
ager@chromium.org7c537e22008-10-16 08:43:32 +00007043static const char* js_code_causing_huge_string_flattening =
7044 "var str = 'X';"
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +00007045 "for (var i = 0; i < 30; i++) {"
ager@chromium.org7c537e22008-10-16 08:43:32 +00007046 " str = str + str;"
7047 "}"
7048 "str.match(/X/);";
7049
7050
ager@chromium.org7c537e22008-10-16 08:43:32 +00007051TEST(RegexpOutOfMemory) {
7052 // Execute a script that causes out of memory when flattening a string.
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007053 v8::HandleScope scope(CcTest::isolate());
ager@chromium.org7c537e22008-10-16 08:43:32 +00007054 v8::V8::SetFatalErrorHandler(OOMCallback);
7055 LocalContext context;
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00007056 Local<Script> script = Script::Compile(String::NewFromUtf8(
7057 CcTest::isolate(), js_code_causing_huge_string_flattening));
ager@chromium.org7c537e22008-10-16 08:43:32 +00007058 last_location = NULL;
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00007059 script->Run();
ager@chromium.org7c537e22008-10-16 08:43:32 +00007060
7061 CHECK(false); // Should not return.
7062}
7063
7064
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007065static void MissingScriptInfoMessageListener(v8::Handle<v8::Message> message,
7066 v8::Handle<Value> data) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00007067 CHECK(message->GetScriptResourceName()->IsUndefined());
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00007068 CHECK_EQ(v8::Undefined(CcTest::isolate()), message->GetScriptResourceName());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007069 message->GetLineNumber();
7070 message->GetSourceLine();
7071}
7072
7073
7074THREADED_TEST(ErrorWithMissingScriptInfo) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007075 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00007076 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007077 v8::V8::AddMessageListener(MissingScriptInfoMessageListener);
7078 Script::Compile(v8_str("throw Error()"))->Run();
7079 v8::V8::RemoveMessageListeners(MissingScriptInfoMessageListener);
7080}
7081
7082
7083int global_index = 0;
7084
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007085template<typename T>
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007086class Snorkel {
7087 public:
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007088 explicit Snorkel(v8::Persistent<T>* handle) : handle_(handle) {
7089 index_ = global_index++;
7090 }
7091 v8::Persistent<T>* handle_;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007092 int index_;
7093};
7094
7095class Whammy {
7096 public:
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00007097 explicit Whammy(v8::Isolate* isolate) : cursor_(0), isolate_(isolate) { }
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00007098 ~Whammy() { script_.Reset(); }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007099 v8::Handle<Script> getScript() {
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00007100 if (script_.IsEmpty()) script_.Reset(isolate_, v8_compile("({}).blammo"));
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00007101 return Local<Script>::New(isolate_, script_);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007102 }
7103
7104 public:
7105 static const int kObjectCount = 256;
7106 int cursor_;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00007107 v8::Isolate* isolate_;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007108 v8::Persistent<v8::Object> objects_[kObjectCount];
7109 v8::Persistent<Script> script_;
7110};
7111
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007112static void HandleWeakReference(
7113 const v8::WeakCallbackData<v8::Value, Snorkel<v8::Value> >& data) {
7114 data.GetParameter()->handle_->ClearWeak();
7115 delete data.GetParameter();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007116}
7117
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007118void WhammyPropertyGetter(Local<String> name,
7119 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007120 Whammy* whammy =
7121 static_cast<Whammy*>(v8::Handle<v8::External>::Cast(info.Data())->Value());
7122
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00007123 v8::Persistent<v8::Object>& prev = whammy->objects_[whammy->cursor_];
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007124
ulan@chromium.org0f13e742014-01-03 15:51:11 +00007125 v8::Handle<v8::Object> obj = v8::Object::New(info.GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007126 if (!prev.IsEmpty()) {
rossberg@chromium.org79e79022013-06-03 15:43:46 +00007127 v8::Local<v8::Object>::New(info.GetIsolate(), prev)
7128 ->Set(v8_str("next"), obj);
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007129 prev.SetWeak<Value, Snorkel<Value> >(new Snorkel<Value>(&prev.As<Value>()),
7130 &HandleWeakReference);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007131 }
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00007132 whammy->objects_[whammy->cursor_].Reset(info.GetIsolate(), obj);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007133 whammy->cursor_ = (whammy->cursor_ + 1) % Whammy::kObjectCount;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007134 info.GetReturnValue().Set(whammy->getScript()->Run());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007135}
7136
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00007137
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007138THREADED_TEST(WeakReference) {
machenbach@chromium.orgc8cbc432014-01-21 09:01:57 +00007139 i::FLAG_expose_gc = true;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00007140 v8::Isolate* isolate = CcTest::isolate();
7141 v8::HandleScope handle_scope(isolate);
7142 v8::Handle<v8::ObjectTemplate> templ= v8::ObjectTemplate::New(isolate);
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007143 Whammy* whammy = new Whammy(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007144 templ->SetNamedPropertyHandler(WhammyPropertyGetter,
7145 0, 0, 0, 0,
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00007146 v8::External::New(CcTest::isolate(), whammy));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007147 const char* extension_list[] = { "v8/gc" };
7148 v8::ExtensionConfiguration extensions(1, extension_list);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007149 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007150 Context::New(CcTest::isolate(), &extensions);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007151 Context::Scope context_scope(context);
7152
7153 v8::Handle<v8::Object> interceptor = templ->NewInstance();
7154 context->Global()->Set(v8_str("whammy"), interceptor);
7155 const char* code =
7156 "var last;"
7157 "for (var i = 0; i < 10000; i++) {"
7158 " var obj = whammy.length;"
7159 " if (last) last.next = obj;"
7160 " last = obj;"
7161 "}"
7162 "gc();"
7163 "4";
7164 v8::Handle<Value> result = CompileRun(code);
7165 CHECK_EQ(4.0, result->NumberValue());
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +00007166 delete whammy;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007167}
7168
7169
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007170struct FlagAndPersistent {
7171 bool flag;
7172 v8::Persistent<v8::Object> handle;
7173};
7174
7175
7176static void DisposeAndSetFlag(
7177 const v8::WeakCallbackData<v8::Object, FlagAndPersistent>& data) {
7178 data.GetParameter()->handle.Reset();
7179 data.GetParameter()->flag = true;
ager@chromium.orgc4c92722009-11-18 14:12:51 +00007180}
7181
ager@chromium.orgc4c92722009-11-18 14:12:51 +00007182
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007183THREADED_TEST(IndependentWeakHandle) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007184 v8::Isolate* iso = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007185 v8::HandleScope scope(iso);
7186 v8::Handle<Context> context = Context::New(iso);
ager@chromium.orgc4c92722009-11-18 14:12:51 +00007187 Context::Scope context_scope(context);
7188
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007189 FlagAndPersistent object_a, object_b;
ager@chromium.orgc4c92722009-11-18 14:12:51 +00007190
7191 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00007192 v8::HandleScope handle_scope(iso);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00007193 object_a.handle.Reset(iso, v8::Object::New(iso));
7194 object_b.handle.Reset(iso, v8::Object::New(iso));
ager@chromium.orgc4c92722009-11-18 14:12:51 +00007195 }
7196
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007197 object_a.flag = false;
7198 object_b.flag = false;
7199 object_a.handle.SetWeak(&object_a, &DisposeAndSetFlag);
7200 object_b.handle.SetWeak(&object_b, &DisposeAndSetFlag);
7201 CHECK(!object_b.handle.IsIndependent());
7202 object_a.handle.MarkIndependent();
7203 object_b.handle.MarkIndependent();
7204 CHECK(object_b.handle.IsIndependent());
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007205 CcTest::heap()->PerformScavenge();
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007206 CHECK(object_a.flag);
7207 CHECK(object_b.flag);
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007208}
ager@chromium.orgc4c92722009-11-18 14:12:51 +00007209
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007210
7211static void InvokeScavenge() {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007212 CcTest::heap()->PerformScavenge();
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007213}
7214
7215
7216static void InvokeMarkSweep() {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007217 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007218}
7219
7220
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007221static void ForceScavenge(
7222 const v8::WeakCallbackData<v8::Object, FlagAndPersistent>& data) {
7223 data.GetParameter()->handle.Reset();
7224 data.GetParameter()->flag = true;
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007225 InvokeScavenge();
7226}
7227
7228
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007229static void ForceMarkSweep(
7230 const v8::WeakCallbackData<v8::Object, FlagAndPersistent>& data) {
7231 data.GetParameter()->handle.Reset();
7232 data.GetParameter()->flag = true;
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007233 InvokeMarkSweep();
7234}
7235
7236
7237THREADED_TEST(GCFromWeakCallbacks) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007238 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007239 v8::HandleScope scope(isolate);
7240 v8::Handle<Context> context = Context::New(isolate);
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007241 Context::Scope context_scope(context);
7242
7243 static const int kNumberOfGCTypes = 2;
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007244 typedef v8::WeakCallbackData<v8::Object, FlagAndPersistent>::Callback
7245 Callback;
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007246 Callback gc_forcing_callback[kNumberOfGCTypes] =
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007247 {&ForceScavenge, &ForceMarkSweep};
7248
7249 typedef void (*GCInvoker)();
7250 GCInvoker invoke_gc[kNumberOfGCTypes] = {&InvokeScavenge, &InvokeMarkSweep};
7251
7252 for (int outer_gc = 0; outer_gc < kNumberOfGCTypes; outer_gc++) {
7253 for (int inner_gc = 0; inner_gc < kNumberOfGCTypes; inner_gc++) {
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007254 FlagAndPersistent object;
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007255 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00007256 v8::HandleScope handle_scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00007257 object.handle.Reset(isolate, v8::Object::New(isolate));
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007258 }
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007259 object.flag = false;
7260 object.handle.SetWeak(&object, gc_forcing_callback[inner_gc]);
7261 object.handle.MarkIndependent();
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007262 invoke_gc[outer_gc]();
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007263 CHECK(object.flag);
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007264 }
ager@chromium.orgc4c92722009-11-18 14:12:51 +00007265 }
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007266}
7267
7268
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007269static void RevivingCallback(
7270 const v8::WeakCallbackData<v8::Object, FlagAndPersistent>& data) {
7271 data.GetParameter()->handle.ClearWeak();
7272 data.GetParameter()->flag = true;
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007273}
7274
7275
7276THREADED_TEST(IndependentHandleRevival) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007277 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007278 v8::HandleScope scope(isolate);
7279 v8::Handle<Context> context = Context::New(isolate);
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007280 Context::Scope context_scope(context);
7281
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007282 FlagAndPersistent object;
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007283 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00007284 v8::HandleScope handle_scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00007285 v8::Local<v8::Object> o = v8::Object::New(isolate);
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007286 object.handle.Reset(isolate, o);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00007287 o->Set(v8_str("x"), v8::Integer::New(isolate, 1));
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007288 v8::Local<String> y_str = v8_str("y");
rossberg@chromium.org79e79022013-06-03 15:43:46 +00007289 o->Set(y_str, y_str);
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007290 }
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007291 object.flag = false;
7292 object.handle.SetWeak(&object, &RevivingCallback);
7293 object.handle.MarkIndependent();
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007294 CcTest::heap()->PerformScavenge();
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007295 CHECK(object.flag);
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007296 CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007297 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00007298 v8::HandleScope handle_scope(isolate);
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007299 v8::Local<v8::Object> o =
7300 v8::Local<v8::Object>::New(isolate, object.handle);
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007301 v8::Local<String> y_str = v8_str("y");
ulan@chromium.org0f13e742014-01-03 15:51:11 +00007302 CHECK_EQ(v8::Integer::New(isolate, 1), o->Get(v8_str("x")));
rossberg@chromium.org79e79022013-06-03 15:43:46 +00007303 CHECK(o->Get(y_str)->Equals(y_str));
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007304 }
ager@chromium.orgc4c92722009-11-18 14:12:51 +00007305}
7306
7307
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007308v8::Handle<Function> args_fun;
7309
7310
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007311static void ArgumentsTestCallback(
7312 const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007313 ApiTestFuzzer::Fuzz();
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00007314 v8::Isolate* isolate = args.GetIsolate();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007315 CHECK_EQ(args_fun, args.Callee());
7316 CHECK_EQ(3, args.Length());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00007317 CHECK_EQ(v8::Integer::New(isolate, 1), args[0]);
7318 CHECK_EQ(v8::Integer::New(isolate, 2), args[1]);
7319 CHECK_EQ(v8::Integer::New(isolate, 3), args[2]);
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00007320 CHECK_EQ(v8::Undefined(isolate), args[3]);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00007321 v8::HandleScope scope(args.GetIsolate());
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007322 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007323}
7324
7325
7326THREADED_TEST(Arguments) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00007327 v8::Isolate* isolate = CcTest::isolate();
7328 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00007329 v8::Handle<v8::ObjectTemplate> global = ObjectTemplate::New(isolate);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00007330 global->Set(v8_str("f"),
7331 v8::FunctionTemplate::New(isolate, ArgumentsTestCallback));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007332 LocalContext context(NULL, global);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00007333 args_fun = context->Global()->Get(v8_str("f")).As<Function>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007334 v8_compile("f(1, 2, 3)")->Run();
7335}
7336
7337
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007338static void NoBlockGetterX(Local<String> name,
7339 const v8::PropertyCallbackInfo<v8::Value>&) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007340}
7341
7342
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007343static void NoBlockGetterI(uint32_t index,
7344 const v8::PropertyCallbackInfo<v8::Value>&) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007345}
7346
7347
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007348static void PDeleter(Local<String> name,
7349 const v8::PropertyCallbackInfo<v8::Boolean>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007350 if (!name->Equals(v8_str("foo"))) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007351 return; // not intercepted
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007352 }
7353
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007354 info.GetReturnValue().Set(false); // intercepted, don't delete the property
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007355}
7356
7357
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007358static void IDeleter(uint32_t index,
7359 const v8::PropertyCallbackInfo<v8::Boolean>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007360 if (index != 2) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007361 return; // not intercepted
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007362 }
7363
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007364 info.GetReturnValue().Set(false); // intercepted, don't delete the property
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007365}
7366
7367
7368THREADED_TEST(Deleter) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00007369 v8::Isolate* isolate = CcTest::isolate();
7370 v8::HandleScope scope(isolate);
7371 v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007372 obj->SetNamedPropertyHandler(NoBlockGetterX, NULL, NULL, PDeleter, NULL);
7373 obj->SetIndexedPropertyHandler(NoBlockGetterI, NULL, NULL, IDeleter, NULL);
7374 LocalContext context;
7375 context->Global()->Set(v8_str("k"), obj->NewInstance());
7376 CompileRun(
7377 "k.foo = 'foo';"
7378 "k.bar = 'bar';"
7379 "k[2] = 2;"
7380 "k[4] = 4;");
7381 CHECK(v8_compile("delete k.foo")->Run()->IsFalse());
7382 CHECK(v8_compile("delete k.bar")->Run()->IsTrue());
7383
7384 CHECK_EQ(v8_compile("k.foo")->Run(), v8_str("foo"));
7385 CHECK(v8_compile("k.bar")->Run()->IsUndefined());
7386
7387 CHECK(v8_compile("delete k[2]")->Run()->IsFalse());
7388 CHECK(v8_compile("delete k[4]")->Run()->IsTrue());
7389
7390 CHECK_EQ(v8_compile("k[2]")->Run(), v8_num(2));
7391 CHECK(v8_compile("k[4]")->Run()->IsUndefined());
7392}
7393
7394
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007395static void GetK(Local<String> name,
7396 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007397 ApiTestFuzzer::Fuzz();
ager@chromium.org65dad4b2009-04-23 08:48:43 +00007398 if (name->Equals(v8_str("foo")) ||
7399 name->Equals(v8_str("bar")) ||
7400 name->Equals(v8_str("baz"))) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007401 info.GetReturnValue().SetUndefined();
ager@chromium.org65dad4b2009-04-23 08:48:43 +00007402 }
ager@chromium.org65dad4b2009-04-23 08:48:43 +00007403}
7404
7405
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007406static void IndexedGetK(uint32_t index,
7407 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.org65dad4b2009-04-23 08:48:43 +00007408 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007409 if (index == 0 || index == 1) info.GetReturnValue().SetUndefined();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007410}
7411
7412
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007413static void NamedEnum(const v8::PropertyCallbackInfo<v8::Array>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007414 ApiTestFuzzer::Fuzz();
machenbach@chromium.org9f18d912013-11-28 13:42:41 +00007415 v8::Handle<v8::Array> result = v8::Array::New(info.GetIsolate(), 3);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00007416 result->Set(v8::Integer::New(info.GetIsolate(), 0), v8_str("foo"));
7417 result->Set(v8::Integer::New(info.GetIsolate(), 1), v8_str("bar"));
7418 result->Set(v8::Integer::New(info.GetIsolate(), 2), v8_str("baz"));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007419 info.GetReturnValue().Set(result);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007420}
7421
7422
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007423static void IndexedEnum(const v8::PropertyCallbackInfo<v8::Array>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007424 ApiTestFuzzer::Fuzz();
machenbach@chromium.org9f18d912013-11-28 13:42:41 +00007425 v8::Handle<v8::Array> result = v8::Array::New(info.GetIsolate(), 2);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00007426 result->Set(v8::Integer::New(info.GetIsolate(), 0), v8_str("0"));
7427 result->Set(v8::Integer::New(info.GetIsolate(), 1), v8_str("1"));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007428 info.GetReturnValue().Set(result);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007429}
7430
7431
7432THREADED_TEST(Enumerators) {
ulan@chromium.org0f13e742014-01-03 15:51:11 +00007433 v8::Isolate* isolate = CcTest::isolate();
7434 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00007435 v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007436 obj->SetNamedPropertyHandler(GetK, NULL, NULL, NULL, NamedEnum);
ager@chromium.org65dad4b2009-04-23 08:48:43 +00007437 obj->SetIndexedPropertyHandler(IndexedGetK, NULL, NULL, NULL, IndexedEnum);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007438 LocalContext context;
7439 context->Global()->Set(v8_str("k"), obj->NewInstance());
7440 v8::Handle<v8::Array> result = v8::Handle<v8::Array>::Cast(CompileRun(
ager@chromium.org65dad4b2009-04-23 08:48:43 +00007441 "k[10] = 0;"
7442 "k.a = 0;"
7443 "k[5] = 0;"
7444 "k.b = 0;"
7445 "k[4294967295] = 0;"
7446 "k.c = 0;"
7447 "k[4294967296] = 0;"
7448 "k.d = 0;"
7449 "k[140000] = 0;"
7450 "k.e = 0;"
7451 "k[30000000000] = 0;"
7452 "k.f = 0;"
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007453 "var result = [];"
7454 "for (var prop in k) {"
7455 " result.push(prop);"
7456 "}"
7457 "result"));
ager@chromium.org65dad4b2009-04-23 08:48:43 +00007458 // Check that we get all the property names returned including the
7459 // ones from the enumerators in the right order: indexed properties
7460 // in numerical order, indexed interceptor properties, named
7461 // properties in insertion order, named interceptor properties.
7462 // This order is not mandated by the spec, so this test is just
7463 // documenting our behavior.
7464 CHECK_EQ(17, result->Length());
7465 // Indexed properties in numerical order.
ulan@chromium.org0f13e742014-01-03 15:51:11 +00007466 CHECK_EQ(v8_str("5"), result->Get(v8::Integer::New(isolate, 0)));
7467 CHECK_EQ(v8_str("10"), result->Get(v8::Integer::New(isolate, 1)));
7468 CHECK_EQ(v8_str("140000"), result->Get(v8::Integer::New(isolate, 2)));
7469 CHECK_EQ(v8_str("4294967295"), result->Get(v8::Integer::New(isolate, 3)));
ager@chromium.org65dad4b2009-04-23 08:48:43 +00007470 // Indexed interceptor properties in the order they are returned
7471 // from the enumerator interceptor.
ulan@chromium.org0f13e742014-01-03 15:51:11 +00007472 CHECK_EQ(v8_str("0"), result->Get(v8::Integer::New(isolate, 4)));
7473 CHECK_EQ(v8_str("1"), result->Get(v8::Integer::New(isolate, 5)));
ager@chromium.org65dad4b2009-04-23 08:48:43 +00007474 // Named properties in insertion order.
ulan@chromium.org0f13e742014-01-03 15:51:11 +00007475 CHECK_EQ(v8_str("a"), result->Get(v8::Integer::New(isolate, 6)));
7476 CHECK_EQ(v8_str("b"), result->Get(v8::Integer::New(isolate, 7)));
7477 CHECK_EQ(v8_str("c"), result->Get(v8::Integer::New(isolate, 8)));
7478 CHECK_EQ(v8_str("4294967296"), result->Get(v8::Integer::New(isolate, 9)));
7479 CHECK_EQ(v8_str("d"), result->Get(v8::Integer::New(isolate, 10)));
7480 CHECK_EQ(v8_str("e"), result->Get(v8::Integer::New(isolate, 11)));
7481 CHECK_EQ(v8_str("30000000000"), result->Get(v8::Integer::New(isolate, 12)));
7482 CHECK_EQ(v8_str("f"), result->Get(v8::Integer::New(isolate, 13)));
ager@chromium.org65dad4b2009-04-23 08:48:43 +00007483 // Named interceptor properties.
ulan@chromium.org0f13e742014-01-03 15:51:11 +00007484 CHECK_EQ(v8_str("foo"), result->Get(v8::Integer::New(isolate, 14)));
7485 CHECK_EQ(v8_str("bar"), result->Get(v8::Integer::New(isolate, 15)));
7486 CHECK_EQ(v8_str("baz"), result->Get(v8::Integer::New(isolate, 16)));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007487}
7488
7489
7490int p_getter_count;
7491int p_getter_count2;
7492
7493
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007494static void PGetter(Local<String> name,
7495 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007496 ApiTestFuzzer::Fuzz();
7497 p_getter_count++;
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007498 v8::Handle<v8::Object> global =
7499 info.GetIsolate()->GetCurrentContext()->Global();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007500 CHECK_EQ(info.Holder(), global->Get(v8_str("o1")));
7501 if (name->Equals(v8_str("p1"))) {
7502 CHECK_EQ(info.This(), global->Get(v8_str("o1")));
7503 } else if (name->Equals(v8_str("p2"))) {
7504 CHECK_EQ(info.This(), global->Get(v8_str("o2")));
7505 } else if (name->Equals(v8_str("p3"))) {
7506 CHECK_EQ(info.This(), global->Get(v8_str("o3")));
7507 } else if (name->Equals(v8_str("p4"))) {
7508 CHECK_EQ(info.This(), global->Get(v8_str("o4")));
7509 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007510}
7511
7512
7513static void RunHolderTest(v8::Handle<v8::ObjectTemplate> obj) {
7514 ApiTestFuzzer::Fuzz();
7515 LocalContext context;
7516 context->Global()->Set(v8_str("o1"), obj->NewInstance());
7517 CompileRun(
7518 "o1.__proto__ = { };"
7519 "var o2 = { __proto__: o1 };"
7520 "var o3 = { __proto__: o2 };"
7521 "var o4 = { __proto__: o3 };"
7522 "for (var i = 0; i < 10; i++) o4.p4;"
7523 "for (var i = 0; i < 10; i++) o3.p3;"
7524 "for (var i = 0; i < 10; i++) o2.p2;"
7525 "for (var i = 0; i < 10; i++) o1.p1;");
7526}
7527
7528
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007529static void PGetter2(Local<String> name,
7530 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007531 ApiTestFuzzer::Fuzz();
7532 p_getter_count2++;
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007533 v8::Handle<v8::Object> global =
7534 info.GetIsolate()->GetCurrentContext()->Global();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007535 CHECK_EQ(info.Holder(), global->Get(v8_str("o1")));
7536 if (name->Equals(v8_str("p1"))) {
7537 CHECK_EQ(info.This(), global->Get(v8_str("o1")));
7538 } else if (name->Equals(v8_str("p2"))) {
7539 CHECK_EQ(info.This(), global->Get(v8_str("o2")));
7540 } else if (name->Equals(v8_str("p3"))) {
7541 CHECK_EQ(info.This(), global->Get(v8_str("o3")));
7542 } else if (name->Equals(v8_str("p4"))) {
7543 CHECK_EQ(info.This(), global->Get(v8_str("o4")));
7544 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007545}
7546
7547
7548THREADED_TEST(GetterHolders) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00007549 v8::Isolate* isolate = CcTest::isolate();
7550 v8::HandleScope scope(isolate);
7551 v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007552 obj->SetAccessor(v8_str("p1"), PGetter);
7553 obj->SetAccessor(v8_str("p2"), PGetter);
7554 obj->SetAccessor(v8_str("p3"), PGetter);
7555 obj->SetAccessor(v8_str("p4"), PGetter);
7556 p_getter_count = 0;
7557 RunHolderTest(obj);
7558 CHECK_EQ(40, p_getter_count);
7559}
7560
7561
7562THREADED_TEST(PreInterceptorHolders) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00007563 v8::Isolate* isolate = CcTest::isolate();
7564 v8::HandleScope scope(isolate);
7565 v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007566 obj->SetNamedPropertyHandler(PGetter2);
7567 p_getter_count2 = 0;
7568 RunHolderTest(obj);
7569 CHECK_EQ(40, p_getter_count2);
7570}
7571
7572
7573THREADED_TEST(ObjectInstantiation) {
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00007574 v8::Isolate* isolate = CcTest::isolate();
7575 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00007576 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007577 templ->SetAccessor(v8_str("t"), PGetter2);
7578 LocalContext context;
7579 context->Global()->Set(v8_str("o"), templ->NewInstance());
7580 for (int i = 0; i < 100; i++) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007581 v8::HandleScope inner_scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007582 v8::Handle<v8::Object> obj = templ->NewInstance();
7583 CHECK_NE(obj, context->Global()->Get(v8_str("o")));
7584 context->Global()->Set(v8_str("o2"), obj);
7585 v8::Handle<Value> value =
7586 Script::Compile(v8_str("o.__proto__ === o2.__proto__"))->Run();
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00007587 CHECK_EQ(v8::True(isolate), value);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007588 context->Global()->Set(v8_str("o"), obj);
7589 }
7590}
7591
7592
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007593static int StrCmp16(uint16_t* a, uint16_t* b) {
7594 while (true) {
7595 if (*a == 0 && *b == 0) return 0;
7596 if (*a != *b) return 0 + *a - *b;
7597 a++;
7598 b++;
7599 }
7600}
7601
7602
7603static int StrNCmp16(uint16_t* a, uint16_t* b, int n) {
7604 while (true) {
7605 if (n-- == 0) return 0;
7606 if (*a == 0 && *b == 0) return 0;
7607 if (*a != *b) return 0 + *a - *b;
7608 a++;
7609 b++;
7610 }
7611}
7612
7613
yangguo@chromium.org154ff992012-03-13 08:09:54 +00007614int GetUtf8Length(Handle<String> str) {
7615 int len = str->Utf8Length();
7616 if (len < 0) {
7617 i::Handle<i::String> istr(v8::Utils::OpenHandle(*str));
7618 i::FlattenString(istr);
7619 len = str->Utf8Length();
7620 }
7621 return len;
7622}
7623
7624
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007625THREADED_TEST(StringWrite) {
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007626 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00007627 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007628 v8::Handle<String> str = v8_str("abcde");
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007629 // abc<Icelandic eth><Unicode snowman>.
7630 v8::Handle<String> str2 = v8_str("abc\303\260\342\230\203");
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00007631 v8::Handle<String> str3 = v8::String::NewFromUtf8(
7632 context->GetIsolate(), "abc\0def", v8::String::kNormalString, 7);
machenbach@chromium.orgc8cbc432014-01-21 09:01:57 +00007633 // "ab" + lead surrogate + "cd" + trail surrogate + "ef"
7634 uint16_t orphans[8] = { 0x61, 0x62, 0xd800, 0x63, 0x64, 0xdc00, 0x65, 0x66 };
7635 v8::Handle<String> orphans_str = v8::String::NewFromTwoByte(
7636 context->GetIsolate(), orphans, v8::String::kNormalString, 8);
7637 // single lead surrogate
7638 uint16_t lead[1] = { 0xd800 };
7639 v8::Handle<String> lead_str = v8::String::NewFromTwoByte(
7640 context->GetIsolate(), lead, v8::String::kNormalString, 1);
7641 // single trail surrogate
7642 uint16_t trail[1] = { 0xdc00 };
7643 v8::Handle<String> trail_str = v8::String::NewFromTwoByte(
7644 context->GetIsolate(), trail, v8::String::kNormalString, 1);
7645 // surrogate pair
7646 uint16_t pair[2] = { 0xd800, 0xdc00 };
7647 v8::Handle<String> pair_str = v8::String::NewFromTwoByte(
7648 context->GetIsolate(), pair, v8::String::kNormalString, 2);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007649 const int kStride = 4; // Must match stride in for loops in JS below.
7650 CompileRun(
7651 "var left = '';"
7652 "for (var i = 0; i < 0xd800; i += 4) {"
7653 " left = left + String.fromCharCode(i);"
7654 "}");
7655 CompileRun(
7656 "var right = '';"
7657 "for (var i = 0; i < 0xd800; i += 4) {"
7658 " right = String.fromCharCode(i) + right;"
7659 "}");
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007660 v8::Handle<v8::Object> global = context->Global();
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007661 Handle<String> left_tree = global->Get(v8_str("left")).As<String>();
7662 Handle<String> right_tree = global->Get(v8_str("right")).As<String>();
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007663
7664 CHECK_EQ(5, str2->Length());
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007665 CHECK_EQ(0xd800 / kStride, left_tree->Length());
7666 CHECK_EQ(0xd800 / kStride, right_tree->Length());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007667
7668 char buf[100];
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007669 char utf8buf[0xd800 * 3];
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007670 uint16_t wbuf[100];
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007671 int len;
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007672 int charlen;
7673
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007674 memset(utf8buf, 0x1, 1000);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007675 len = str2->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007676 CHECK_EQ(9, len);
7677 CHECK_EQ(5, charlen);
7678 CHECK_EQ(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007679
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007680 memset(utf8buf, 0x1, 1000);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007681 len = str2->WriteUtf8(utf8buf, 8, &charlen);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007682 CHECK_EQ(8, len);
7683 CHECK_EQ(5, charlen);
7684 CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\342\230\203\1", 9));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007685
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007686 memset(utf8buf, 0x1, 1000);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007687 len = str2->WriteUtf8(utf8buf, 7, &charlen);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007688 CHECK_EQ(5, len);
7689 CHECK_EQ(4, charlen);
7690 CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007691
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007692 memset(utf8buf, 0x1, 1000);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007693 len = str2->WriteUtf8(utf8buf, 6, &charlen);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007694 CHECK_EQ(5, len);
7695 CHECK_EQ(4, charlen);
7696 CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007697
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007698 memset(utf8buf, 0x1, 1000);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007699 len = str2->WriteUtf8(utf8buf, 5, &charlen);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007700 CHECK_EQ(5, len);
7701 CHECK_EQ(4, charlen);
7702 CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007703
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007704 memset(utf8buf, 0x1, 1000);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007705 len = str2->WriteUtf8(utf8buf, 4, &charlen);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007706 CHECK_EQ(3, len);
7707 CHECK_EQ(3, charlen);
7708 CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007709
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007710 memset(utf8buf, 0x1, 1000);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007711 len = str2->WriteUtf8(utf8buf, 3, &charlen);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007712 CHECK_EQ(3, len);
7713 CHECK_EQ(3, charlen);
7714 CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007715
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007716 memset(utf8buf, 0x1, 1000);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007717 len = str2->WriteUtf8(utf8buf, 2, &charlen);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007718 CHECK_EQ(2, len);
7719 CHECK_EQ(2, charlen);
7720 CHECK_EQ(0, strncmp(utf8buf, "ab\1", 3));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007721
machenbach@chromium.orgc8cbc432014-01-21 09:01:57 +00007722 // allow orphan surrogates by default
7723 memset(utf8buf, 0x1, 1000);
7724 len = orphans_str->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen);
7725 CHECK_EQ(13, len);
7726 CHECK_EQ(8, charlen);
7727 CHECK_EQ(0, strcmp(utf8buf, "ab\355\240\200cd\355\260\200ef"));
7728
7729 // replace orphan surrogates with unicode replacement character
7730 memset(utf8buf, 0x1, 1000);
7731 len = orphans_str->WriteUtf8(utf8buf,
7732 sizeof(utf8buf),
7733 &charlen,
7734 String::REPLACE_INVALID_UTF8);
7735 CHECK_EQ(13, len);
7736 CHECK_EQ(8, charlen);
7737 CHECK_EQ(0, strcmp(utf8buf, "ab\357\277\275cd\357\277\275ef"));
7738
7739 // replace single lead surrogate with unicode replacement character
7740 memset(utf8buf, 0x1, 1000);
7741 len = lead_str->WriteUtf8(utf8buf,
7742 sizeof(utf8buf),
7743 &charlen,
7744 String::REPLACE_INVALID_UTF8);
7745 CHECK_EQ(4, len);
7746 CHECK_EQ(1, charlen);
7747 CHECK_EQ(0, strcmp(utf8buf, "\357\277\275"));
7748
7749 // replace single trail surrogate with unicode replacement character
7750 memset(utf8buf, 0x1, 1000);
7751 len = trail_str->WriteUtf8(utf8buf,
7752 sizeof(utf8buf),
7753 &charlen,
7754 String::REPLACE_INVALID_UTF8);
7755 CHECK_EQ(4, len);
7756 CHECK_EQ(1, charlen);
7757 CHECK_EQ(0, strcmp(utf8buf, "\357\277\275"));
7758
7759 // do not replace / write anything if surrogate pair does not fit the buffer
7760 // space
7761 memset(utf8buf, 0x1, 1000);
7762 len = pair_str->WriteUtf8(utf8buf,
7763 3,
7764 &charlen,
7765 String::REPLACE_INVALID_UTF8);
7766 CHECK_EQ(0, len);
7767 CHECK_EQ(0, charlen);
7768
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007769 memset(utf8buf, 0x1, sizeof(utf8buf));
yangguo@chromium.org154ff992012-03-13 08:09:54 +00007770 len = GetUtf8Length(left_tree);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007771 int utf8_expected =
7772 (0x80 + (0x800 - 0x80) * 2 + (0xd800 - 0x800) * 3) / kStride;
7773 CHECK_EQ(utf8_expected, len);
7774 len = left_tree->WriteUtf8(utf8buf, utf8_expected, &charlen);
7775 CHECK_EQ(utf8_expected, len);
7776 CHECK_EQ(0xd800 / kStride, charlen);
7777 CHECK_EQ(0xed, static_cast<unsigned char>(utf8buf[utf8_expected - 3]));
7778 CHECK_EQ(0x9f, static_cast<unsigned char>(utf8buf[utf8_expected - 2]));
7779 CHECK_EQ(0xc0 - kStride,
7780 static_cast<unsigned char>(utf8buf[utf8_expected - 1]));
7781 CHECK_EQ(1, utf8buf[utf8_expected]);
7782
7783 memset(utf8buf, 0x1, sizeof(utf8buf));
yangguo@chromium.org154ff992012-03-13 08:09:54 +00007784 len = GetUtf8Length(right_tree);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007785 CHECK_EQ(utf8_expected, len);
7786 len = right_tree->WriteUtf8(utf8buf, utf8_expected, &charlen);
7787 CHECK_EQ(utf8_expected, len);
7788 CHECK_EQ(0xd800 / kStride, charlen);
7789 CHECK_EQ(0xed, static_cast<unsigned char>(utf8buf[0]));
7790 CHECK_EQ(0x9f, static_cast<unsigned char>(utf8buf[1]));
7791 CHECK_EQ(0xc0 - kStride, static_cast<unsigned char>(utf8buf[2]));
7792 CHECK_EQ(1, utf8buf[utf8_expected]);
7793
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007794 memset(buf, 0x1, sizeof(buf));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007795 memset(wbuf, 0x1, sizeof(wbuf));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007796 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf));
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007797 CHECK_EQ(5, len);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007798 len = str->Write(wbuf);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007799 CHECK_EQ(5, len);
7800 CHECK_EQ(0, strcmp("abcde", buf));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007801 uint16_t answer1[] = {'a', 'b', 'c', 'd', 'e', '\0'};
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007802 CHECK_EQ(0, StrCmp16(answer1, wbuf));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007803
7804 memset(buf, 0x1, sizeof(buf));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007805 memset(wbuf, 0x1, sizeof(wbuf));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007806 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 4);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007807 CHECK_EQ(4, len);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007808 len = str->Write(wbuf, 0, 4);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007809 CHECK_EQ(4, len);
7810 CHECK_EQ(0, strncmp("abcd\1", buf, 5));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007811 uint16_t answer2[] = {'a', 'b', 'c', 'd', 0x101};
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007812 CHECK_EQ(0, StrNCmp16(answer2, wbuf, 5));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007813
7814 memset(buf, 0x1, sizeof(buf));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007815 memset(wbuf, 0x1, sizeof(wbuf));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007816 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 5);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007817 CHECK_EQ(5, len);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007818 len = str->Write(wbuf, 0, 5);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007819 CHECK_EQ(5, len);
7820 CHECK_EQ(0, strncmp("abcde\1", buf, 6));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007821 uint16_t answer3[] = {'a', 'b', 'c', 'd', 'e', 0x101};
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007822 CHECK_EQ(0, StrNCmp16(answer3, wbuf, 6));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007823
7824 memset(buf, 0x1, sizeof(buf));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007825 memset(wbuf, 0x1, sizeof(wbuf));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007826 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 6);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007827 CHECK_EQ(5, len);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007828 len = str->Write(wbuf, 0, 6);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007829 CHECK_EQ(5, len);
7830 CHECK_EQ(0, strcmp("abcde", buf));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007831 uint16_t answer4[] = {'a', 'b', 'c', 'd', 'e', '\0'};
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007832 CHECK_EQ(0, StrCmp16(answer4, wbuf));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007833
7834 memset(buf, 0x1, sizeof(buf));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007835 memset(wbuf, 0x1, sizeof(wbuf));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007836 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, -1);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007837 CHECK_EQ(1, len);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007838 len = str->Write(wbuf, 4, -1);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007839 CHECK_EQ(1, len);
7840 CHECK_EQ(0, strcmp("e", buf));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007841 uint16_t answer5[] = {'e', '\0'};
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007842 CHECK_EQ(0, StrCmp16(answer5, wbuf));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007843
7844 memset(buf, 0x1, sizeof(buf));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007845 memset(wbuf, 0x1, sizeof(wbuf));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007846 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, 6);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007847 CHECK_EQ(1, len);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007848 len = str->Write(wbuf, 4, 6);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007849 CHECK_EQ(1, len);
7850 CHECK_EQ(0, strcmp("e", buf));
7851 CHECK_EQ(0, StrCmp16(answer5, wbuf));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007852
7853 memset(buf, 0x1, sizeof(buf));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007854 memset(wbuf, 0x1, sizeof(wbuf));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007855 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, 1);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007856 CHECK_EQ(1, len);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007857 len = str->Write(wbuf, 4, 1);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007858 CHECK_EQ(1, len);
7859 CHECK_EQ(0, strncmp("e\1", buf, 2));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007860 uint16_t answer6[] = {'e', 0x101};
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007861 CHECK_EQ(0, StrNCmp16(answer6, wbuf, 2));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007862
7863 memset(buf, 0x1, sizeof(buf));
7864 memset(wbuf, 0x1, sizeof(wbuf));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007865 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 3, 1);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007866 CHECK_EQ(1, len);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007867 len = str->Write(wbuf, 3, 1);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007868 CHECK_EQ(1, len);
7869 CHECK_EQ(0, strncmp("d\1", buf, 2));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007870 uint16_t answer7[] = {'d', 0x101};
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007871 CHECK_EQ(0, StrNCmp16(answer7, wbuf, 2));
ricow@chromium.orgddd545c2011-08-24 12:02:41 +00007872
7873 memset(wbuf, 0x1, sizeof(wbuf));
7874 wbuf[5] = 'X';
7875 len = str->Write(wbuf, 0, 6, String::NO_NULL_TERMINATION);
7876 CHECK_EQ(5, len);
7877 CHECK_EQ('X', wbuf[5]);
7878 uint16_t answer8a[] = {'a', 'b', 'c', 'd', 'e'};
7879 uint16_t answer8b[] = {'a', 'b', 'c', 'd', 'e', '\0'};
7880 CHECK_EQ(0, StrNCmp16(answer8a, wbuf, 5));
7881 CHECK_NE(0, StrCmp16(answer8b, wbuf));
7882 wbuf[5] = '\0';
7883 CHECK_EQ(0, StrCmp16(answer8b, wbuf));
7884
7885 memset(buf, 0x1, sizeof(buf));
7886 buf[5] = 'X';
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007887 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf),
7888 0,
7889 6,
7890 String::NO_NULL_TERMINATION);
ricow@chromium.orgddd545c2011-08-24 12:02:41 +00007891 CHECK_EQ(5, len);
7892 CHECK_EQ('X', buf[5]);
7893 CHECK_EQ(0, strncmp("abcde", buf, 5));
7894 CHECK_NE(0, strcmp("abcde", buf));
7895 buf[5] = '\0';
7896 CHECK_EQ(0, strcmp("abcde", buf));
7897
7898 memset(utf8buf, 0x1, sizeof(utf8buf));
7899 utf8buf[8] = 'X';
7900 len = str2->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen,
7901 String::NO_NULL_TERMINATION);
7902 CHECK_EQ(8, len);
7903 CHECK_EQ('X', utf8buf[8]);
7904 CHECK_EQ(5, charlen);
7905 CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\342\230\203", 8));
7906 CHECK_NE(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
7907 utf8buf[8] = '\0';
7908 CHECK_EQ(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
yangguo@chromium.org304cc332012-07-24 07:59:48 +00007909
7910 memset(utf8buf, 0x1, sizeof(utf8buf));
7911 utf8buf[5] = 'X';
7912 len = str->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen,
7913 String::NO_NULL_TERMINATION);
7914 CHECK_EQ(5, len);
7915 CHECK_EQ('X', utf8buf[5]); // Test that the sixth character is untouched.
7916 CHECK_EQ(5, charlen);
7917 utf8buf[5] = '\0';
7918 CHECK_EQ(0, strcmp(utf8buf, "abcde"));
7919
7920 memset(buf, 0x1, sizeof(buf));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007921 len = str3->WriteOneByte(reinterpret_cast<uint8_t*>(buf));
yangguo@chromium.org304cc332012-07-24 07:59:48 +00007922 CHECK_EQ(7, len);
7923 CHECK_EQ(0, strcmp("abc", buf));
7924 CHECK_EQ(0, buf[3]);
7925 CHECK_EQ(0, strcmp("def", buf + 4));
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00007926
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007927 CHECK_EQ(0, str->WriteOneByte(NULL, 0, 0, String::NO_NULL_TERMINATION));
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00007928 CHECK_EQ(0, str->WriteUtf8(NULL, 0, 0, String::NO_NULL_TERMINATION));
7929 CHECK_EQ(0, str->Write(NULL, 0, 0, String::NO_NULL_TERMINATION));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007930}
7931
7932
yangguo@chromium.org154ff992012-03-13 08:09:54 +00007933static void Utf16Helper(
7934 LocalContext& context,
7935 const char* name,
7936 const char* lengths_name,
7937 int len) {
7938 Local<v8::Array> a =
7939 Local<v8::Array>::Cast(context->Global()->Get(v8_str(name)));
7940 Local<v8::Array> alens =
7941 Local<v8::Array>::Cast(context->Global()->Get(v8_str(lengths_name)));
7942 for (int i = 0; i < len; i++) {
7943 Local<v8::String> string =
7944 Local<v8::String>::Cast(a->Get(i));
7945 Local<v8::Number> expected_len =
7946 Local<v8::Number>::Cast(alens->Get(i));
7947 int length = GetUtf8Length(string);
7948 CHECK_EQ(static_cast<int>(expected_len->Value()), length);
7949 }
7950}
7951
7952
7953static uint16_t StringGet(Handle<String> str, int index) {
7954 i::Handle<i::String> istring =
7955 v8::Utils::OpenHandle(String::Cast(*str));
7956 return istring->Get(index);
7957}
7958
7959
7960static void WriteUtf8Helper(
7961 LocalContext& context,
7962 const char* name,
7963 const char* lengths_name,
7964 int len) {
7965 Local<v8::Array> b =
7966 Local<v8::Array>::Cast(context->Global()->Get(v8_str(name)));
7967 Local<v8::Array> alens =
7968 Local<v8::Array>::Cast(context->Global()->Get(v8_str(lengths_name)));
7969 char buffer[1000];
7970 char buffer2[1000];
7971 for (int i = 0; i < len; i++) {
7972 Local<v8::String> string =
7973 Local<v8::String>::Cast(b->Get(i));
7974 Local<v8::Number> expected_len =
7975 Local<v8::Number>::Cast(alens->Get(i));
7976 int utf8_length = static_cast<int>(expected_len->Value());
7977 for (int j = utf8_length + 1; j >= 0; j--) {
7978 memset(reinterpret_cast<void*>(&buffer), 42, sizeof(buffer));
7979 memset(reinterpret_cast<void*>(&buffer2), 42, sizeof(buffer2));
7980 int nchars;
7981 int utf8_written =
7982 string->WriteUtf8(buffer, j, &nchars, String::NO_OPTIONS);
7983 int utf8_written2 =
7984 string->WriteUtf8(buffer2, j, &nchars, String::NO_NULL_TERMINATION);
7985 CHECK_GE(utf8_length + 1, utf8_written);
7986 CHECK_GE(utf8_length, utf8_written2);
7987 for (int k = 0; k < utf8_written2; k++) {
7988 CHECK_EQ(buffer[k], buffer2[k]);
7989 }
7990 CHECK(nchars * 3 >= utf8_written - 1);
7991 CHECK(nchars <= utf8_written);
7992 if (j == utf8_length + 1) {
7993 CHECK_EQ(utf8_written2, utf8_length);
7994 CHECK_EQ(utf8_written2 + 1, utf8_written);
7995 }
7996 CHECK_EQ(buffer[utf8_written], 42);
7997 if (j > utf8_length) {
7998 if (utf8_written != 0) CHECK_EQ(buffer[utf8_written - 1], 0);
7999 if (utf8_written > 1) CHECK_NE(buffer[utf8_written - 2], 42);
8000 Handle<String> roundtrip = v8_str(buffer);
8001 CHECK(roundtrip->Equals(string));
8002 } else {
8003 if (utf8_written != 0) CHECK_NE(buffer[utf8_written - 1], 42);
8004 }
8005 if (utf8_written2 != 0) CHECK_NE(buffer[utf8_written - 1], 42);
8006 if (nchars >= 2) {
8007 uint16_t trail = StringGet(string, nchars - 1);
8008 uint16_t lead = StringGet(string, nchars - 2);
8009 if (((lead & 0xfc00) == 0xd800) &&
8010 ((trail & 0xfc00) == 0xdc00)) {
8011 unsigned char u1 = buffer2[utf8_written2 - 4];
8012 unsigned char u2 = buffer2[utf8_written2 - 3];
8013 unsigned char u3 = buffer2[utf8_written2 - 2];
8014 unsigned char u4 = buffer2[utf8_written2 - 1];
8015 CHECK_EQ((u1 & 0xf8), 0xf0);
8016 CHECK_EQ((u2 & 0xc0), 0x80);
8017 CHECK_EQ((u3 & 0xc0), 0x80);
8018 CHECK_EQ((u4 & 0xc0), 0x80);
8019 uint32_t c = 0x10000 + ((lead & 0x3ff) << 10) + (trail & 0x3ff);
8020 CHECK_EQ((u4 & 0x3f), (c & 0x3f));
8021 CHECK_EQ((u3 & 0x3f), ((c >> 6) & 0x3f));
8022 CHECK_EQ((u2 & 0x3f), ((c >> 12) & 0x3f));
8023 CHECK_EQ((u1 & 0x3), c >> 18);
8024 }
8025 }
8026 }
8027 }
8028}
8029
8030
8031THREADED_TEST(Utf16) {
8032 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008033 v8::HandleScope scope(context->GetIsolate());
yangguo@chromium.org154ff992012-03-13 08:09:54 +00008034 CompileRun(
8035 "var pad = '01234567890123456789';"
8036 "var p = [];"
8037 "var plens = [20, 3, 3];"
8038 "p.push('01234567890123456789');"
8039 "var lead = 0xd800;"
8040 "var trail = 0xdc00;"
8041 "p.push(String.fromCharCode(0xd800));"
8042 "p.push(String.fromCharCode(0xdc00));"
8043 "var a = [];"
8044 "var b = [];"
danno@chromium.org88aa0582012-03-23 15:11:57 +00008045 "var c = [];"
yangguo@chromium.org154ff992012-03-13 08:09:54 +00008046 "var alens = [];"
8047 "for (var i = 0; i < 3; i++) {"
8048 " p[1] = String.fromCharCode(lead++);"
8049 " for (var j = 0; j < 3; j++) {"
8050 " p[2] = String.fromCharCode(trail++);"
8051 " a.push(p[i] + p[j]);"
8052 " b.push(p[i] + p[j]);"
danno@chromium.org88aa0582012-03-23 15:11:57 +00008053 " c.push(p[i] + p[j]);"
yangguo@chromium.org154ff992012-03-13 08:09:54 +00008054 " alens.push(plens[i] + plens[j]);"
8055 " }"
8056 "}"
8057 "alens[5] -= 2;" // Here the surrogate pairs match up.
8058 "var a2 = [];"
8059 "var b2 = [];"
danno@chromium.org88aa0582012-03-23 15:11:57 +00008060 "var c2 = [];"
yangguo@chromium.org154ff992012-03-13 08:09:54 +00008061 "var a2lens = [];"
8062 "for (var m = 0; m < 9; m++) {"
8063 " for (var n = 0; n < 9; n++) {"
8064 " a2.push(a[m] + a[n]);"
8065 " b2.push(b[m] + b[n]);"
danno@chromium.org88aa0582012-03-23 15:11:57 +00008066 " var newc = 'x' + c[m] + c[n] + 'y';"
8067 " c2.push(newc.substring(1, newc.length - 1));"
yangguo@chromium.org154ff992012-03-13 08:09:54 +00008068 " var utf = alens[m] + alens[n];" // And here.
8069 // The 'n's that start with 0xdc.. are 6-8
8070 // The 'm's that end with 0xd8.. are 1, 4 and 7
8071 " if ((m % 3) == 1 && n >= 6) utf -= 2;"
8072 " a2lens.push(utf);"
8073 " }"
8074 "}");
8075 Utf16Helper(context, "a", "alens", 9);
8076 Utf16Helper(context, "a2", "a2lens", 81);
8077 WriteUtf8Helper(context, "b", "alens", 9);
8078 WriteUtf8Helper(context, "b2", "a2lens", 81);
danno@chromium.org88aa0582012-03-23 15:11:57 +00008079 WriteUtf8Helper(context, "c2", "a2lens", 81);
yangguo@chromium.org154ff992012-03-13 08:09:54 +00008080}
8081
8082
8083static bool SameSymbol(Handle<String> s1, Handle<String> s2) {
8084 i::Handle<i::String> is1(v8::Utils::OpenHandle(*s1));
8085 i::Handle<i::String> is2(v8::Utils::OpenHandle(*s2));
8086 return *is1 == *is2;
8087}
8088
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00008089static void SameSymbolHelper(v8::Isolate* isolate, const char* a,
8090 const char* b) {
8091 Handle<String> symbol1 =
8092 v8::String::NewFromUtf8(isolate, a, v8::String::kInternalizedString);
8093 Handle<String> symbol2 =
8094 v8::String::NewFromUtf8(isolate, b, v8::String::kInternalizedString);
yangguo@chromium.org154ff992012-03-13 08:09:54 +00008095 CHECK(SameSymbol(symbol1, symbol2));
8096}
8097
8098
8099THREADED_TEST(Utf16Symbol) {
8100 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008101 v8::HandleScope scope(context->GetIsolate());
yangguo@chromium.org154ff992012-03-13 08:09:54 +00008102
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00008103 Handle<String> symbol1 = v8::String::NewFromUtf8(
8104 context->GetIsolate(), "abc", v8::String::kInternalizedString);
8105 Handle<String> symbol2 = v8::String::NewFromUtf8(
8106 context->GetIsolate(), "abc", v8::String::kInternalizedString);
yangguo@chromium.org154ff992012-03-13 08:09:54 +00008107 CHECK(SameSymbol(symbol1, symbol2));
8108
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00008109 SameSymbolHelper(context->GetIsolate(),
8110 "\360\220\220\205", // 4 byte encoding.
yangguo@chromium.org154ff992012-03-13 08:09:54 +00008111 "\355\240\201\355\260\205"); // 2 3-byte surrogates.
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00008112 SameSymbolHelper(context->GetIsolate(),
8113 "\355\240\201\355\260\206", // 2 3-byte surrogates.
yangguo@chromium.org154ff992012-03-13 08:09:54 +00008114 "\360\220\220\206"); // 4 byte encoding.
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00008115 SameSymbolHelper(context->GetIsolate(),
8116 "x\360\220\220\205", // 4 byte encoding.
yangguo@chromium.org154ff992012-03-13 08:09:54 +00008117 "x\355\240\201\355\260\205"); // 2 3-byte surrogates.
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00008118 SameSymbolHelper(context->GetIsolate(),
8119 "x\355\240\201\355\260\206", // 2 3-byte surrogates.
yangguo@chromium.org154ff992012-03-13 08:09:54 +00008120 "x\360\220\220\206"); // 4 byte encoding.
8121 CompileRun(
8122 "var sym0 = 'benedictus';"
8123 "var sym0b = 'S\303\270ren';"
8124 "var sym1 = '\355\240\201\355\260\207';"
8125 "var sym2 = '\360\220\220\210';"
8126 "var sym3 = 'x\355\240\201\355\260\207';"
8127 "var sym4 = 'x\360\220\220\210';"
8128 "if (sym1.length != 2) throw sym1;"
8129 "if (sym1.charCodeAt(1) != 0xdc07) throw sym1.charCodeAt(1);"
8130 "if (sym2.length != 2) throw sym2;"
8131 "if (sym2.charCodeAt(1) != 0xdc08) throw sym2.charCodeAt(2);"
8132 "if (sym3.length != 3) throw sym3;"
8133 "if (sym3.charCodeAt(2) != 0xdc07) throw sym1.charCodeAt(2);"
8134 "if (sym4.length != 3) throw sym4;"
8135 "if (sym4.charCodeAt(2) != 0xdc08) throw sym2.charCodeAt(2);");
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00008136 Handle<String> sym0 = v8::String::NewFromUtf8(
8137 context->GetIsolate(), "benedictus", v8::String::kInternalizedString);
8138 Handle<String> sym0b = v8::String::NewFromUtf8(
8139 context->GetIsolate(), "S\303\270ren", v8::String::kInternalizedString);
8140 Handle<String> sym1 =
8141 v8::String::NewFromUtf8(context->GetIsolate(), "\355\240\201\355\260\207",
8142 v8::String::kInternalizedString);
8143 Handle<String> sym2 =
8144 v8::String::NewFromUtf8(context->GetIsolate(), "\360\220\220\210",
8145 v8::String::kInternalizedString);
8146 Handle<String> sym3 = v8::String::NewFromUtf8(
8147 context->GetIsolate(), "x\355\240\201\355\260\207",
8148 v8::String::kInternalizedString);
8149 Handle<String> sym4 =
8150 v8::String::NewFromUtf8(context->GetIsolate(), "x\360\220\220\210",
8151 v8::String::kInternalizedString);
yangguo@chromium.org154ff992012-03-13 08:09:54 +00008152 v8::Local<v8::Object> global = context->Global();
8153 Local<Value> s0 = global->Get(v8_str("sym0"));
8154 Local<Value> s0b = global->Get(v8_str("sym0b"));
8155 Local<Value> s1 = global->Get(v8_str("sym1"));
8156 Local<Value> s2 = global->Get(v8_str("sym2"));
8157 Local<Value> s3 = global->Get(v8_str("sym3"));
8158 Local<Value> s4 = global->Get(v8_str("sym4"));
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00008159 CHECK(SameSymbol(sym0, Handle<String>::Cast(s0)));
8160 CHECK(SameSymbol(sym0b, Handle<String>::Cast(s0b)));
8161 CHECK(SameSymbol(sym1, Handle<String>::Cast(s1)));
8162 CHECK(SameSymbol(sym2, Handle<String>::Cast(s2)));
8163 CHECK(SameSymbol(sym3, Handle<String>::Cast(s3)));
8164 CHECK(SameSymbol(sym4, Handle<String>::Cast(s4)));
yangguo@chromium.org154ff992012-03-13 08:09:54 +00008165}
8166
8167
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008168THREADED_TEST(ToArrayIndex) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008169 LocalContext context;
ulan@chromium.org0f13e742014-01-03 15:51:11 +00008170 v8::Isolate* isolate = context->GetIsolate();
8171 v8::HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008172
8173 v8::Handle<String> str = v8_str("42");
8174 v8::Handle<v8::Uint32> index = str->ToArrayIndex();
8175 CHECK(!index.IsEmpty());
8176 CHECK_EQ(42.0, index->Uint32Value());
8177 str = v8_str("42asdf");
8178 index = str->ToArrayIndex();
8179 CHECK(index.IsEmpty());
8180 str = v8_str("-42");
8181 index = str->ToArrayIndex();
8182 CHECK(index.IsEmpty());
8183 str = v8_str("4294967295");
8184 index = str->ToArrayIndex();
8185 CHECK(!index.IsEmpty());
8186 CHECK_EQ(4294967295.0, index->Uint32Value());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00008187 v8::Handle<v8::Number> num = v8::Number::New(isolate, 1);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008188 index = num->ToArrayIndex();
8189 CHECK(!index.IsEmpty());
8190 CHECK_EQ(1.0, index->Uint32Value());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00008191 num = v8::Number::New(isolate, -1);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008192 index = num->ToArrayIndex();
8193 CHECK(index.IsEmpty());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00008194 v8::Handle<v8::Object> obj = v8::Object::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008195 index = obj->ToArrayIndex();
8196 CHECK(index.IsEmpty());
8197}
8198
8199
8200THREADED_TEST(ErrorConstruction) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008201 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008202 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008203
8204 v8::Handle<String> foo = v8_str("foo");
8205 v8::Handle<String> message = v8_str("message");
8206 v8::Handle<Value> range_error = v8::Exception::RangeError(foo);
8207 CHECK(range_error->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00008208 CHECK(range_error.As<v8::Object>()->Get(message)->Equals(foo));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008209 v8::Handle<Value> reference_error = v8::Exception::ReferenceError(foo);
8210 CHECK(reference_error->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00008211 CHECK(reference_error.As<v8::Object>()->Get(message)->Equals(foo));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008212 v8::Handle<Value> syntax_error = v8::Exception::SyntaxError(foo);
8213 CHECK(syntax_error->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00008214 CHECK(syntax_error.As<v8::Object>()->Get(message)->Equals(foo));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008215 v8::Handle<Value> type_error = v8::Exception::TypeError(foo);
8216 CHECK(type_error->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00008217 CHECK(type_error.As<v8::Object>()->Get(message)->Equals(foo));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008218 v8::Handle<Value> error = v8::Exception::Error(foo);
8219 CHECK(error->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00008220 CHECK(error.As<v8::Object>()->Get(message)->Equals(foo));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008221}
8222
8223
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00008224static void YGetter(Local<String> name,
8225 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008226 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00008227 info.GetReturnValue().Set(v8_num(10));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008228}
8229
8230
8231static void YSetter(Local<String> name,
8232 Local<Value> value,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00008233 const v8::PropertyCallbackInfo<void>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008234 if (info.This()->Has(name)) {
8235 info.This()->Delete(name);
8236 }
8237 info.This()->Set(name, value);
8238}
8239
8240
8241THREADED_TEST(DeleteAccessor) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00008242 v8::Isolate* isolate = CcTest::isolate();
8243 v8::HandleScope scope(isolate);
8244 v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008245 obj->SetAccessor(v8_str("y"), YGetter, YSetter);
8246 LocalContext context;
8247 v8::Handle<v8::Object> holder = obj->NewInstance();
8248 context->Global()->Set(v8_str("holder"), holder);
8249 v8::Handle<Value> result = CompileRun(
8250 "holder.y = 11; holder.y = 12; holder.y");
8251 CHECK_EQ(12, result->Uint32Value());
8252}
8253
8254
8255THREADED_TEST(TypeSwitch) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00008256 v8::Isolate* isolate = CcTest::isolate();
8257 v8::HandleScope scope(isolate);
8258 v8::Handle<v8::FunctionTemplate> templ1 = v8::FunctionTemplate::New(isolate);
8259 v8::Handle<v8::FunctionTemplate> templ2 = v8::FunctionTemplate::New(isolate);
8260 v8::Handle<v8::FunctionTemplate> templ3 = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008261 v8::Handle<v8::FunctionTemplate> templs[3] = { templ1, templ2, templ3 };
8262 v8::Handle<v8::TypeSwitch> type_switch = v8::TypeSwitch::New(3, templs);
8263 LocalContext context;
ulan@chromium.org0f13e742014-01-03 15:51:11 +00008264 v8::Handle<v8::Object> obj0 = v8::Object::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008265 v8::Handle<v8::Object> obj1 = templ1->GetFunction()->NewInstance();
8266 v8::Handle<v8::Object> obj2 = templ2->GetFunction()->NewInstance();
8267 v8::Handle<v8::Object> obj3 = templ3->GetFunction()->NewInstance();
8268 for (int i = 0; i < 10; i++) {
8269 CHECK_EQ(0, type_switch->match(obj0));
8270 CHECK_EQ(1, type_switch->match(obj1));
8271 CHECK_EQ(2, type_switch->match(obj2));
8272 CHECK_EQ(3, type_switch->match(obj3));
8273 CHECK_EQ(3, type_switch->match(obj3));
8274 CHECK_EQ(2, type_switch->match(obj2));
8275 CHECK_EQ(1, type_switch->match(obj1));
8276 CHECK_EQ(0, type_switch->match(obj0));
8277 }
8278}
8279
8280
8281// For use within the TestSecurityHandler() test.
8282static bool g_security_callback_result = false;
8283static bool NamedSecurityTestCallback(Local<v8::Object> global,
8284 Local<Value> name,
8285 v8::AccessType type,
8286 Local<Value> data) {
8287 // Always allow read access.
8288 if (type == v8::ACCESS_GET)
8289 return true;
8290
8291 // Sometimes allow other access.
8292 return g_security_callback_result;
8293}
8294
8295
8296static bool IndexedSecurityTestCallback(Local<v8::Object> global,
8297 uint32_t key,
8298 v8::AccessType type,
8299 Local<Value> data) {
8300 // Always allow read access.
8301 if (type == v8::ACCESS_GET)
8302 return true;
8303
8304 // Sometimes allow other access.
8305 return g_security_callback_result;
8306}
8307
8308
8309static int trouble_nesting = 0;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00008310static void TroubleCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008311 ApiTestFuzzer::Fuzz();
8312 trouble_nesting++;
8313
8314 // Call a JS function that throws an uncaught exception.
machenbach@chromium.org528ce022013-09-23 14:09:36 +00008315 Local<v8::Object> arg_this =
8316 args.GetIsolate()->GetCurrentContext()->Global();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008317 Local<Value> trouble_callee = (trouble_nesting == 3) ?
8318 arg_this->Get(v8_str("trouble_callee")) :
8319 arg_this->Get(v8_str("trouble_caller"));
8320 CHECK(trouble_callee->IsFunction());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00008321 args.GetReturnValue().Set(
8322 Function::Cast(*trouble_callee)->Call(arg_this, 0, NULL));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008323}
8324
8325
8326static int report_count = 0;
8327static void ApiUncaughtExceptionTestListener(v8::Handle<v8::Message>,
8328 v8::Handle<Value>) {
8329 report_count++;
8330}
8331
8332
8333// Counts uncaught exceptions, but other tests running in parallel
8334// also have uncaught exceptions.
8335TEST(ApiUncaughtException) {
ager@chromium.org8bb60582008-12-11 12:02:20 +00008336 report_count = 0;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008337 LocalContext env;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00008338 v8::Isolate* isolate = env->GetIsolate();
8339 v8::HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008340 v8::V8::AddMessageListener(ApiUncaughtExceptionTestListener);
8341
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00008342 Local<v8::FunctionTemplate> fun =
8343 v8::FunctionTemplate::New(isolate, TroubleCallback);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008344 v8::Local<v8::Object> global = env->Global();
8345 global->Set(v8_str("trouble"), fun->GetFunction());
8346
8347 Script::Compile(v8_str("function trouble_callee() {"
8348 " var x = null;"
8349 " return x.foo;"
8350 "};"
8351 "function trouble_caller() {"
8352 " trouble();"
8353 "};"))->Run();
8354 Local<Value> trouble = global->Get(v8_str("trouble"));
8355 CHECK(trouble->IsFunction());
8356 Local<Value> trouble_callee = global->Get(v8_str("trouble_callee"));
8357 CHECK(trouble_callee->IsFunction());
8358 Local<Value> trouble_caller = global->Get(v8_str("trouble_caller"));
8359 CHECK(trouble_caller->IsFunction());
8360 Function::Cast(*trouble_caller)->Call(global, 0, NULL);
8361 CHECK_EQ(1, report_count);
ager@chromium.org8bb60582008-12-11 12:02:20 +00008362 v8::V8::RemoveMessageListeners(ApiUncaughtExceptionTestListener);
8363}
8364
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00008365static const char* script_resource_name = "ExceptionInNativeScript.js";
8366static void ExceptionInNativeScriptTestListener(v8::Handle<v8::Message> message,
8367 v8::Handle<Value>) {
8368 v8::Handle<v8::Value> name_val = message->GetScriptResourceName();
8369 CHECK(!name_val.IsEmpty() && name_val->IsString());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00008370 v8::String::Utf8Value name(message->GetScriptResourceName());
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00008371 CHECK_EQ(script_resource_name, *name);
8372 CHECK_EQ(3, message->GetLineNumber());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00008373 v8::String::Utf8Value source_line(message->GetSourceLine());
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00008374 CHECK_EQ(" new o.foo();", *source_line);
8375}
8376
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00008377
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00008378TEST(ExceptionInNativeScript) {
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00008379 LocalContext env;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00008380 v8::Isolate* isolate = env->GetIsolate();
8381 v8::HandleScope scope(isolate);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00008382 v8::V8::AddMessageListener(ExceptionInNativeScriptTestListener);
8383
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00008384 Local<v8::FunctionTemplate> fun =
8385 v8::FunctionTemplate::New(isolate, TroubleCallback);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00008386 v8::Local<v8::Object> global = env->Global();
8387 global->Set(v8_str("trouble"), fun->GetFunction());
8388
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00008389 Script::Compile(
8390 v8_str(
8391 "function trouble() {\n"
8392 " var o = {};\n"
8393 " new o.foo();\n"
8394 "};"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00008395 v8::String::NewFromUtf8(isolate, script_resource_name))->Run();
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00008396 Local<Value> trouble = global->Get(v8_str("trouble"));
8397 CHECK(trouble->IsFunction());
8398 Function::Cast(*trouble)->Call(global, 0, NULL);
8399 v8::V8::RemoveMessageListeners(ExceptionInNativeScriptTestListener);
8400}
8401
ager@chromium.org8bb60582008-12-11 12:02:20 +00008402
8403TEST(CompilationErrorUsingTryCatchHandler) {
ager@chromium.org8bb60582008-12-11 12:02:20 +00008404 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008405 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org8bb60582008-12-11 12:02:20 +00008406 v8::TryCatch try_catch;
8407 Script::Compile(v8_str("This doesn't &*&@#$&*^ compile."));
8408 CHECK_NE(NULL, *try_catch.Exception());
8409 CHECK(try_catch.HasCaught());
8410}
8411
8412
8413TEST(TryCatchFinallyUsingTryCatchHandler) {
ager@chromium.org8bb60582008-12-11 12:02:20 +00008414 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008415 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org8bb60582008-12-11 12:02:20 +00008416 v8::TryCatch try_catch;
8417 Script::Compile(v8_str("try { throw ''; } catch (e) {}"))->Run();
8418 CHECK(!try_catch.HasCaught());
8419 Script::Compile(v8_str("try { throw ''; } finally {}"))->Run();
8420 CHECK(try_catch.HasCaught());
8421 try_catch.Reset();
8422 Script::Compile(v8_str("(function() {"
8423 "try { throw ''; } finally { return; }"
8424 "})()"))->Run();
8425 CHECK(!try_catch.HasCaught());
8426 Script::Compile(v8_str("(function()"
8427 " { try { throw ''; } finally { throw 0; }"
8428 "})()"))->Run();
8429 CHECK(try_catch.HasCaught());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008430}
8431
8432
8433// SecurityHandler can't be run twice
8434TEST(SecurityHandler) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00008435 v8::Isolate* isolate = CcTest::isolate();
8436 v8::HandleScope scope0(isolate);
8437 v8::Handle<v8::ObjectTemplate> global_template =
8438 v8::ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008439 global_template->SetAccessCheckCallbacks(NamedSecurityTestCallback,
8440 IndexedSecurityTestCallback);
8441 // Create an environment
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00008442 v8::Handle<Context> context0 = Context::New(isolate, NULL, global_template);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008443 context0->Enter();
8444
8445 v8::Handle<v8::Object> global0 = context0->Global();
8446 v8::Handle<Script> script0 = v8_compile("foo = 111");
8447 script0->Run();
8448 global0->Set(v8_str("0"), v8_num(999));
8449 v8::Handle<Value> foo0 = global0->Get(v8_str("foo"));
8450 CHECK_EQ(111, foo0->Int32Value());
8451 v8::Handle<Value> z0 = global0->Get(v8_str("0"));
8452 CHECK_EQ(999, z0->Int32Value());
8453
8454 // Create another environment, should fail security checks.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00008455 v8::HandleScope scope1(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008456
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008457 v8::Handle<Context> context1 =
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00008458 Context::New(isolate, NULL, global_template);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008459 context1->Enter();
8460
8461 v8::Handle<v8::Object> global1 = context1->Global();
8462 global1->Set(v8_str("othercontext"), global0);
8463 // This set will fail the security check.
8464 v8::Handle<Script> script1 =
8465 v8_compile("othercontext.foo = 222; othercontext[0] = 888;");
8466 script1->Run();
8467 // This read will pass the security check.
8468 v8::Handle<Value> foo1 = global0->Get(v8_str("foo"));
8469 CHECK_EQ(111, foo1->Int32Value());
8470 // This read will pass the security check.
8471 v8::Handle<Value> z1 = global0->Get(v8_str("0"));
8472 CHECK_EQ(999, z1->Int32Value());
8473
8474 // Create another environment, should pass security checks.
8475 { g_security_callback_result = true; // allow security handler to pass.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00008476 v8::HandleScope scope2(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008477 LocalContext context2;
8478 v8::Handle<v8::Object> global2 = context2->Global();
8479 global2->Set(v8_str("othercontext"), global0);
8480 v8::Handle<Script> script2 =
8481 v8_compile("othercontext.foo = 333; othercontext[0] = 888;");
8482 script2->Run();
8483 v8::Handle<Value> foo2 = global0->Get(v8_str("foo"));
8484 CHECK_EQ(333, foo2->Int32Value());
8485 v8::Handle<Value> z2 = global0->Get(v8_str("0"));
8486 CHECK_EQ(888, z2->Int32Value());
8487 }
8488
8489 context1->Exit();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008490 context0->Exit();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008491}
8492
8493
8494THREADED_TEST(SecurityChecks) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008495 LocalContext env1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008496 v8::HandleScope handle_scope(env1->GetIsolate());
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008497 v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008498
8499 Local<Value> foo = v8_str("foo");
8500 Local<Value> bar = v8_str("bar");
8501
8502 // Set to the same domain.
8503 env1->SetSecurityToken(foo);
8504
8505 // Create a function in env1.
8506 Script::Compile(v8_str("spy=function(){return spy;}"))->Run();
8507 Local<Value> spy = env1->Global()->Get(v8_str("spy"));
8508 CHECK(spy->IsFunction());
8509
8510 // Create another function accessing global objects.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00008511 Script::Compile(v8_str("spy2=function(){return new this.Array();}"))->Run();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008512 Local<Value> spy2 = env1->Global()->Get(v8_str("spy2"));
8513 CHECK(spy2->IsFunction());
8514
8515 // Switch to env2 in the same domain and invoke spy on env2.
8516 {
8517 env2->SetSecurityToken(foo);
8518 // Enter env2
8519 Context::Scope scope_env2(env2);
8520 Local<Value> result = Function::Cast(*spy)->Call(env2->Global(), 0, NULL);
8521 CHECK(result->IsFunction());
8522 }
8523
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008524 {
8525 env2->SetSecurityToken(bar);
8526 Context::Scope scope_env2(env2);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008527
8528 // Call cross_domain_call, it should throw an exception
8529 v8::TryCatch try_catch;
8530 Function::Cast(*spy2)->Call(env2->Global(), 0, NULL);
8531 CHECK(try_catch.HasCaught());
8532 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008533}
8534
8535
8536// Regression test case for issue 1183439.
8537THREADED_TEST(SecurityChecksForPrototypeChain) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008538 LocalContext current;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008539 v8::HandleScope scope(current->GetIsolate());
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008540 v8::Handle<Context> other = Context::New(current->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008541
8542 // Change context to be able to get to the Object function in the
8543 // other context without hitting the security checks.
8544 v8::Local<Value> other_object;
8545 { Context::Scope scope(other);
8546 other_object = other->Global()->Get(v8_str("Object"));
8547 other->Global()->Set(v8_num(42), v8_num(87));
8548 }
8549
8550 current->Global()->Set(v8_str("other"), other->Global());
8551 CHECK(v8_compile("other")->Run()->Equals(other->Global()));
8552
8553 // Make sure the security check fails here and we get an undefined
8554 // result instead of getting the Object function. Repeat in a loop
8555 // to make sure to exercise the IC code.
8556 v8::Local<Script> access_other0 = v8_compile("other.Object");
8557 v8::Local<Script> access_other1 = v8_compile("other[42]");
8558 for (int i = 0; i < 5; i++) {
8559 CHECK(!access_other0->Run()->Equals(other_object));
8560 CHECK(access_other0->Run()->IsUndefined());
8561 CHECK(!access_other1->Run()->Equals(v8_num(87)));
8562 CHECK(access_other1->Run()->IsUndefined());
8563 }
8564
8565 // Create an object that has 'other' in its prototype chain and make
8566 // sure we cannot access the Object function indirectly through
8567 // that. Repeat in a loop to make sure to exercise the IC code.
8568 v8_compile("function F() { };"
8569 "F.prototype = other;"
8570 "var f = new F();")->Run();
8571 v8::Local<Script> access_f0 = v8_compile("f.Object");
8572 v8::Local<Script> access_f1 = v8_compile("f[42]");
8573 for (int j = 0; j < 5; j++) {
8574 CHECK(!access_f0->Run()->Equals(other_object));
8575 CHECK(access_f0->Run()->IsUndefined());
8576 CHECK(!access_f1->Run()->Equals(v8_num(87)));
8577 CHECK(access_f1->Run()->IsUndefined());
8578 }
8579
8580 // Now it gets hairy: Set the prototype for the other global object
8581 // to be the current global object. The prototype chain for 'f' now
8582 // goes through 'other' but ends up in the current global object.
8583 { Context::Scope scope(other);
8584 other->Global()->Set(v8_str("__proto__"), current->Global());
8585 }
8586 // Set a named and an index property on the current global
8587 // object. To force the lookup to go through the other global object,
8588 // the properties must not exist in the other global object.
8589 current->Global()->Set(v8_str("foo"), v8_num(100));
8590 current->Global()->Set(v8_num(99), v8_num(101));
8591 // Try to read the properties from f and make sure that the access
8592 // gets stopped by the security checks on the other global object.
8593 Local<Script> access_f2 = v8_compile("f.foo");
8594 Local<Script> access_f3 = v8_compile("f[99]");
8595 for (int k = 0; k < 5; k++) {
8596 CHECK(!access_f2->Run()->Equals(v8_num(100)));
8597 CHECK(access_f2->Run()->IsUndefined());
8598 CHECK(!access_f3->Run()->Equals(v8_num(101)));
8599 CHECK(access_f3->Run()->IsUndefined());
8600 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008601}
8602
8603
8604THREADED_TEST(CrossDomainDelete) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008605 LocalContext env1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008606 v8::HandleScope handle_scope(env1->GetIsolate());
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008607 v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008608
8609 Local<Value> foo = v8_str("foo");
8610 Local<Value> bar = v8_str("bar");
8611
8612 // Set to the same domain.
8613 env1->SetSecurityToken(foo);
8614 env2->SetSecurityToken(foo);
8615
8616 env1->Global()->Set(v8_str("prop"), v8_num(3));
8617 env2->Global()->Set(v8_str("env1"), env1->Global());
8618
8619 // Change env2 to a different domain and delete env1.prop.
8620 env2->SetSecurityToken(bar);
8621 {
8622 Context::Scope scope_env2(env2);
8623 Local<Value> result =
8624 Script::Compile(v8_str("delete env1.prop"))->Run();
8625 CHECK(result->IsFalse());
8626 }
8627
8628 // Check that env1.prop still exists.
8629 Local<Value> v = env1->Global()->Get(v8_str("prop"));
8630 CHECK(v->IsNumber());
8631 CHECK_EQ(3, v->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008632}
8633
8634
ager@chromium.org870a0b62008-11-04 11:43:05 +00008635THREADED_TEST(CrossDomainIsPropertyEnumerable) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00008636 LocalContext env1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008637 v8::HandleScope handle_scope(env1->GetIsolate());
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008638 v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
ager@chromium.org870a0b62008-11-04 11:43:05 +00008639
8640 Local<Value> foo = v8_str("foo");
8641 Local<Value> bar = v8_str("bar");
8642
8643 // Set to the same domain.
8644 env1->SetSecurityToken(foo);
8645 env2->SetSecurityToken(foo);
8646
8647 env1->Global()->Set(v8_str("prop"), v8_num(3));
8648 env2->Global()->Set(v8_str("env1"), env1->Global());
8649
8650 // env1.prop is enumerable in env2.
8651 Local<String> test = v8_str("propertyIsEnumerable.call(env1, 'prop')");
8652 {
8653 Context::Scope scope_env2(env2);
8654 Local<Value> result = Script::Compile(test)->Run();
8655 CHECK(result->IsTrue());
8656 }
8657
8658 // Change env2 to a different domain and test again.
8659 env2->SetSecurityToken(bar);
8660 {
8661 Context::Scope scope_env2(env2);
8662 Local<Value> result = Script::Compile(test)->Run();
8663 CHECK(result->IsFalse());
8664 }
ager@chromium.org870a0b62008-11-04 11:43:05 +00008665}
8666
8667
ager@chromium.org236ad962008-09-25 09:45:57 +00008668THREADED_TEST(CrossDomainForIn) {
ager@chromium.org236ad962008-09-25 09:45:57 +00008669 LocalContext env1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008670 v8::HandleScope handle_scope(env1->GetIsolate());
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008671 v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
ager@chromium.org236ad962008-09-25 09:45:57 +00008672
8673 Local<Value> foo = v8_str("foo");
8674 Local<Value> bar = v8_str("bar");
8675
8676 // Set to the same domain.
8677 env1->SetSecurityToken(foo);
8678 env2->SetSecurityToken(foo);
8679
8680 env1->Global()->Set(v8_str("prop"), v8_num(3));
8681 env2->Global()->Set(v8_str("env1"), env1->Global());
8682
8683 // Change env2 to a different domain and set env1's global object
8684 // as the __proto__ of an object in env2 and enumerate properties
8685 // in for-in. It shouldn't enumerate properties on env1's global
8686 // object.
8687 env2->SetSecurityToken(bar);
8688 {
8689 Context::Scope scope_env2(env2);
8690 Local<Value> result =
8691 CompileRun("(function(){var obj = {'__proto__':env1};"
8692 "for (var p in obj)"
8693 " if (p == 'prop') return false;"
8694 "return true;})()");
8695 CHECK(result->IsTrue());
8696 }
ager@chromium.org236ad962008-09-25 09:45:57 +00008697}
8698
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008699
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00008700TEST(ContextDetachGlobal) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00008701 LocalContext env1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008702 v8::HandleScope handle_scope(env1->GetIsolate());
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008703 v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00008704
8705 Local<v8::Object> global1 = env1->Global();
8706
8707 Local<Value> foo = v8_str("foo");
8708
8709 // Set to the same domain.
8710 env1->SetSecurityToken(foo);
8711 env2->SetSecurityToken(foo);
8712
8713 // Enter env2
8714 env2->Enter();
8715
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +00008716 // Create a function in env2 and add a reference to it in env1.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00008717 Local<v8::Object> global2 = env2->Global();
ulan@chromium.org0f13e742014-01-03 15:51:11 +00008718 global2->Set(v8_str("prop"), v8::Integer::New(env2->GetIsolate(), 1));
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00008719 CompileRun("function getProp() {return prop;}");
8720
8721 env1->Global()->Set(v8_str("getProp"),
8722 global2->Get(v8_str("getProp")));
8723
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +00008724 // Detach env2's global, and reuse the global object of env2
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00008725 env2->Exit();
8726 env2->DetachGlobal();
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00008727
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008728 v8::Handle<Context> env3 = Context::New(env1->GetIsolate(),
8729 0,
8730 v8::Handle<v8::ObjectTemplate>(),
8731 global2);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00008732 env3->SetSecurityToken(v8_str("bar"));
8733 env3->Enter();
8734
8735 Local<v8::Object> global3 = env3->Global();
8736 CHECK_EQ(global2, global3);
8737 CHECK(global3->Get(v8_str("prop"))->IsUndefined());
8738 CHECK(global3->Get(v8_str("getProp"))->IsUndefined());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00008739 global3->Set(v8_str("prop"), v8::Integer::New(env3->GetIsolate(), -1));
8740 global3->Set(v8_str("prop2"), v8::Integer::New(env3->GetIsolate(), 2));
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00008741 env3->Exit();
8742
8743 // Call getProp in env1, and it should return the value 1
8744 {
8745 Local<Value> get_prop = global1->Get(v8_str("getProp"));
8746 CHECK(get_prop->IsFunction());
8747 v8::TryCatch try_catch;
8748 Local<Value> r = Function::Cast(*get_prop)->Call(global1, 0, NULL);
8749 CHECK(!try_catch.HasCaught());
8750 CHECK_EQ(1, r->Int32Value());
8751 }
8752
8753 // Check that env3 is not accessible from env1
8754 {
8755 Local<Value> r = global3->Get(v8_str("prop2"));
8756 CHECK(r->IsUndefined());
8757 }
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00008758}
8759
8760
jkummerow@chromium.org113035e2013-12-13 15:13:40 +00008761TEST(DetachGlobal) {
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +00008762 LocalContext env1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008763 v8::HandleScope scope(env1->GetIsolate());
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +00008764
8765 // Create second environment.
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008766 v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +00008767
8768 Local<Value> foo = v8_str("foo");
8769
8770 // Set same security token for env1 and env2.
8771 env1->SetSecurityToken(foo);
8772 env2->SetSecurityToken(foo);
8773
8774 // Create a property on the global object in env2.
8775 {
8776 v8::Context::Scope scope(env2);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00008777 env2->Global()->Set(v8_str("p"), v8::Integer::New(env2->GetIsolate(), 42));
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +00008778 }
8779
8780 // Create a reference to env2 global from env1 global.
8781 env1->Global()->Set(v8_str("other"), env2->Global());
8782
8783 // Check that we have access to other.p in env2 from env1.
8784 Local<Value> result = CompileRun("other.p");
8785 CHECK(result->IsInt32());
8786 CHECK_EQ(42, result->Int32Value());
8787
8788 // Hold on to global from env2 and detach global from env2.
8789 Local<v8::Object> global2 = env2->Global();
8790 env2->DetachGlobal();
8791
8792 // Check that the global has been detached. No other.p property can
8793 // be found.
8794 result = CompileRun("other.p");
8795 CHECK(result->IsUndefined());
8796
8797 // Reuse global2 for env3.
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008798 v8::Handle<Context> env3 = Context::New(env1->GetIsolate(),
8799 0,
8800 v8::Handle<v8::ObjectTemplate>(),
8801 global2);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +00008802 CHECK_EQ(global2, env3->Global());
8803
8804 // Start by using the same security token for env3 as for env1 and env2.
8805 env3->SetSecurityToken(foo);
8806
8807 // Create a property on the global object in env3.
8808 {
8809 v8::Context::Scope scope(env3);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00008810 env3->Global()->Set(v8_str("p"), v8::Integer::New(env3->GetIsolate(), 24));
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +00008811 }
8812
8813 // Check that other.p is now the property in env3 and that we have access.
8814 result = CompileRun("other.p");
8815 CHECK(result->IsInt32());
8816 CHECK_EQ(24, result->Int32Value());
8817
8818 // Change security token for env3 to something different from env1 and env2.
8819 env3->SetSecurityToken(v8_str("bar"));
8820
8821 // Check that we do not have access to other.p in env1. |other| is now
8822 // the global object for env3 which has a different security token,
8823 // so access should be blocked.
8824 result = CompileRun("other.p");
8825 CHECK(result->IsUndefined());
jkummerow@chromium.org113035e2013-12-13 15:13:40 +00008826}
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +00008827
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +00008828
rossberg@chromium.org9ed27462014-01-07 14:16:41 +00008829void GetThisX(const v8::FunctionCallbackInfo<v8::Value>& info) {
8830 info.GetReturnValue().Set(
8831 info.GetIsolate()->GetCurrentContext()->Global()->Get(v8_str("x")));
8832}
8833
8834
jkummerow@chromium.org113035e2013-12-13 15:13:40 +00008835TEST(DetachedAccesses) {
8836 LocalContext env1;
8837 v8::HandleScope scope(env1->GetIsolate());
8838
8839 // Create second environment.
rossberg@chromium.org9ed27462014-01-07 14:16:41 +00008840 Local<ObjectTemplate> inner_global_template =
8841 FunctionTemplate::New(env1->GetIsolate())->InstanceTemplate();
8842 inner_global_template ->SetAccessorProperty(
8843 v8_str("this_x"), FunctionTemplate::New(env1->GetIsolate(), GetThisX));
8844 v8::Local<Context> env2 =
8845 Context::New(env1->GetIsolate(), NULL, inner_global_template);
jkummerow@chromium.org113035e2013-12-13 15:13:40 +00008846
8847 Local<Value> foo = v8_str("foo");
8848
8849 // Set same security token for env1 and env2.
8850 env1->SetSecurityToken(foo);
8851 env2->SetSecurityToken(foo);
8852
rossberg@chromium.org9ed27462014-01-07 14:16:41 +00008853 env1->Global()->Set(v8_str("x"), v8_str("env1_x"));
8854
jkummerow@chromium.org113035e2013-12-13 15:13:40 +00008855 {
8856 v8::Context::Scope scope(env2);
rossberg@chromium.org9ed27462014-01-07 14:16:41 +00008857 env2->Global()->Set(v8_str("x"), v8_str("env2_x"));
jkummerow@chromium.org113035e2013-12-13 15:13:40 +00008858 CompileRun(
rossberg@chromium.org9ed27462014-01-07 14:16:41 +00008859 "function bound_x() { return x; }"
8860 "function get_x() { return this.x; }"
8861 "function get_x_w() { return (function() {return this.x;})(); }");
8862 env1->Global()->Set(v8_str("bound_x"), CompileRun("bound_x"));
jkummerow@chromium.org113035e2013-12-13 15:13:40 +00008863 env1->Global()->Set(v8_str("get_x"), CompileRun("get_x"));
8864 env1->Global()->Set(v8_str("get_x_w"), CompileRun("get_x_w"));
rossberg@chromium.org9ed27462014-01-07 14:16:41 +00008865 env1->Global()->Set(
8866 v8_str("this_x"),
8867 CompileRun("Object.getOwnPropertyDescriptor(this, 'this_x').get"));
jkummerow@chromium.org113035e2013-12-13 15:13:40 +00008868 }
8869
8870 Local<Object> env2_global = env2->Global();
8871 env2_global->TurnOnAccessCheck();
8872 env2->DetachGlobal();
8873
8874 Local<Value> result;
rossberg@chromium.org9ed27462014-01-07 14:16:41 +00008875 result = CompileRun("bound_x()");
8876 CHECK_EQ(v8_str("env2_x"), result);
jkummerow@chromium.org113035e2013-12-13 15:13:40 +00008877 result = CompileRun("get_x()");
8878 CHECK(result->IsUndefined());
8879 result = CompileRun("get_x_w()");
8880 CHECK(result->IsUndefined());
rossberg@chromium.org9ed27462014-01-07 14:16:41 +00008881 result = CompileRun("this_x()");
8882 CHECK_EQ(v8_str("env2_x"), result);
jkummerow@chromium.org113035e2013-12-13 15:13:40 +00008883
8884 // Reattach env2's proxy
8885 env2 = Context::New(env1->GetIsolate(),
8886 0,
8887 v8::Handle<v8::ObjectTemplate>(),
8888 env2_global);
8889 env2->SetSecurityToken(foo);
8890 {
8891 v8::Context::Scope scope(env2);
rossberg@chromium.org9ed27462014-01-07 14:16:41 +00008892 env2->Global()->Set(v8_str("x"), v8_str("env3_x"));
8893 env2->Global()->Set(v8_str("env1"), env1->Global());
8894 result = CompileRun(
8895 "results = [];"
8896 "for (var i = 0; i < 4; i++ ) {"
8897 " results.push(env1.bound_x());"
8898 " results.push(env1.get_x());"
8899 " results.push(env1.get_x_w());"
8900 " results.push(env1.this_x());"
8901 "}"
8902 "results");
8903 Local<v8::Array> results = Local<v8::Array>::Cast(result);
8904 CHECK_EQ(16, results->Length());
8905 for (int i = 0; i < 16; i += 4) {
8906 CHECK_EQ(v8_str("env2_x"), results->Get(i + 0));
8907 CHECK_EQ(v8_str("env1_x"), results->Get(i + 1));
8908 CHECK_EQ(v8_str("env3_x"), results->Get(i + 2));
8909 CHECK_EQ(v8_str("env2_x"), results->Get(i + 3));
8910 }
jkummerow@chromium.org113035e2013-12-13 15:13:40 +00008911 }
8912
rossberg@chromium.org9ed27462014-01-07 14:16:41 +00008913 result = CompileRun(
8914 "results = [];"
8915 "for (var i = 0; i < 4; i++ ) {"
8916 " results.push(bound_x());"
8917 " results.push(get_x());"
8918 " results.push(get_x_w());"
8919 " results.push(this_x());"
8920 "}"
8921 "results");
8922 Local<v8::Array> results = Local<v8::Array>::Cast(result);
8923 CHECK_EQ(16, results->Length());
8924 for (int i = 0; i < 16; i += 4) {
8925 CHECK_EQ(v8_str("env2_x"), results->Get(i + 0));
8926 CHECK_EQ(v8_str("env3_x"), results->Get(i + 1));
8927 CHECK_EQ(v8_str("env3_x"), results->Get(i + 2));
8928 CHECK_EQ(v8_str("env2_x"), results->Get(i + 3));
8929 }
8930
8931 result = CompileRun(
8932 "results = [];"
8933 "for (var i = 0; i < 4; i++ ) {"
8934 " results.push(this.bound_x());"
8935 " results.push(this.get_x());"
8936 " results.push(this.get_x_w());"
8937 " results.push(this.this_x());"
8938 "}"
8939 "results");
8940 results = Local<v8::Array>::Cast(result);
8941 CHECK_EQ(16, results->Length());
8942 for (int i = 0; i < 16; i += 4) {
8943 CHECK_EQ(v8_str("env2_x"), results->Get(i + 0));
8944 CHECK_EQ(v8_str("env1_x"), results->Get(i + 1));
8945 CHECK_EQ(v8_str("env3_x"), results->Get(i + 2));
8946 CHECK_EQ(v8_str("env2_x"), results->Get(i + 3));
8947 }
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +00008948}
8949
8950
ricow@chromium.org83aa5492011-02-07 12:42:56 +00008951static bool allowed_access_type[v8::ACCESS_KEYS + 1] = { false };
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008952static bool NamedAccessBlocker(Local<v8::Object> global,
8953 Local<Value> name,
8954 v8::AccessType type,
8955 Local<Value> data) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00008956 return CcTest::isolate()->GetCurrentContext()->Global()->Equals(global) ||
ricow@chromium.org83aa5492011-02-07 12:42:56 +00008957 allowed_access_type[type];
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008958}
8959
8960
8961static bool IndexedAccessBlocker(Local<v8::Object> global,
8962 uint32_t key,
8963 v8::AccessType type,
8964 Local<Value> data) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00008965 return CcTest::isolate()->GetCurrentContext()->Global()->Equals(global) ||
ricow@chromium.org83aa5492011-02-07 12:42:56 +00008966 allowed_access_type[type];
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008967}
8968
8969
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00008970static int g_echo_value_1 = -1;
8971static int g_echo_value_2 = -1;
8972
8973
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00008974static void EchoGetter(
8975 Local<String> name,
8976 const v8::PropertyCallbackInfo<v8::Value>& info) {
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00008977 info.GetReturnValue().Set(v8_num(g_echo_value_1));
8978}
8979
8980
8981static void EchoGetter(const v8::FunctionCallbackInfo<v8::Value>& info) {
8982 info.GetReturnValue().Set(v8_num(g_echo_value_2));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008983}
8984
8985
8986static void EchoSetter(Local<String> name,
8987 Local<Value> value,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00008988 const v8::PropertyCallbackInfo<void>&) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008989 if (value->IsNumber())
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00008990 g_echo_value_1 = value->Int32Value();
8991}
8992
8993
8994static void EchoSetter(const v8::FunctionCallbackInfo<v8::Value>& info) {
8995 v8::Handle<v8::Value> value = info[0];
8996 if (value->IsNumber())
8997 g_echo_value_2 = value->Int32Value();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008998}
8999
9000
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009001static void UnreachableGetter(
9002 Local<String> name,
9003 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009004 CHECK(false); // This function should not be called..
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009005}
9006
9007
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009008static void UnreachableSetter(Local<String>,
9009 Local<Value>,
9010 const v8::PropertyCallbackInfo<void>&) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009011 CHECK(false); // This function should nto be called.
9012}
9013
9014
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00009015static void UnreachableFunction(
9016 const v8::FunctionCallbackInfo<v8::Value>& info) {
9017 CHECK(false); // This function should not be called..
9018}
9019
9020
ricow@chromium.org83aa5492011-02-07 12:42:56 +00009021TEST(AccessControl) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00009022 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009023 v8::HandleScope handle_scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00009024 v8::Handle<v8::ObjectTemplate> global_template =
9025 v8::ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009026
9027 global_template->SetAccessCheckCallbacks(NamedAccessBlocker,
9028 IndexedAccessBlocker);
9029
9030 // Add an accessor accessible by cross-domain JS code.
9031 global_template->SetAccessor(
9032 v8_str("accessible_prop"),
9033 EchoGetter, EchoSetter,
9034 v8::Handle<Value>(),
9035 v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
9036
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00009037
9038 global_template->SetAccessorProperty(
9039 v8_str("accessible_js_prop"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00009040 v8::FunctionTemplate::New(isolate, EchoGetter),
9041 v8::FunctionTemplate::New(isolate, EchoSetter),
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00009042 v8::None,
9043 v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
9044
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009045 // Add an accessor that is not accessible by cross-domain JS code.
ager@chromium.org870a0b62008-11-04 11:43:05 +00009046 global_template->SetAccessor(v8_str("blocked_prop"),
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009047 UnreachableGetter, UnreachableSetter,
9048 v8::Handle<Value>(),
9049 v8::DEFAULT);
9050
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00009051 global_template->SetAccessorProperty(
9052 v8_str("blocked_js_prop"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00009053 v8::FunctionTemplate::New(isolate, UnreachableFunction),
9054 v8::FunctionTemplate::New(isolate, UnreachableFunction),
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00009055 v8::None,
9056 v8::DEFAULT);
9057
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009058 // Create an environment
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009059 v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009060 context0->Enter();
9061
9062 v8::Handle<v8::Object> global0 = context0->Global();
9063
ricow@chromium.org83aa5492011-02-07 12:42:56 +00009064 // Define a property with JS getter and setter.
9065 CompileRun(
9066 "function getter() { return 'getter'; };\n"
9067 "function setter() { return 'setter'; }\n"
9068 "Object.defineProperty(this, 'js_accessor_p', {get:getter, set:setter})");
9069
9070 Local<Value> getter = global0->Get(v8_str("getter"));
9071 Local<Value> setter = global0->Get(v8_str("setter"));
9072
9073 // And define normal element.
9074 global0->Set(239, v8_str("239"));
9075
9076 // Define an element with JS getter and setter.
9077 CompileRun(
9078 "function el_getter() { return 'el_getter'; };\n"
9079 "function el_setter() { return 'el_setter'; };\n"
9080 "Object.defineProperty(this, '42', {get: el_getter, set: el_setter});");
9081
9082 Local<Value> el_getter = global0->Get(v8_str("el_getter"));
9083 Local<Value> el_setter = global0->Get(v8_str("el_setter"));
9084
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009085 v8::HandleScope scope1(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009086
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009087 v8::Local<Context> context1 = Context::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009088 context1->Enter();
9089
9090 v8::Handle<v8::Object> global1 = context1->Global();
9091 global1->Set(v8_str("other"), global0);
9092
ricow@chromium.org83aa5492011-02-07 12:42:56 +00009093 // Access blocked property.
9094 CompileRun("other.blocked_prop = 1");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009095
ricow@chromium.org83aa5492011-02-07 12:42:56 +00009096 ExpectUndefined("other.blocked_prop");
9097 ExpectUndefined(
9098 "Object.getOwnPropertyDescriptor(other, 'blocked_prop')");
9099 ExpectFalse("propertyIsEnumerable.call(other, 'blocked_prop')");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009100
ricow@chromium.org83aa5492011-02-07 12:42:56 +00009101 // Enable ACCESS_HAS
9102 allowed_access_type[v8::ACCESS_HAS] = true;
9103 ExpectUndefined("other.blocked_prop");
9104 // ... and now we can get the descriptor...
9105 ExpectUndefined(
antonm@chromium.orgdca01352011-01-31 17:15:05 +00009106 "Object.getOwnPropertyDescriptor(other, 'blocked_prop').value");
ricow@chromium.org83aa5492011-02-07 12:42:56 +00009107 // ... and enumerate the property.
9108 ExpectTrue("propertyIsEnumerable.call(other, 'blocked_prop')");
9109 allowed_access_type[v8::ACCESS_HAS] = false;
antonm@chromium.orgdca01352011-01-31 17:15:05 +00009110
ricow@chromium.org83aa5492011-02-07 12:42:56 +00009111 // Access blocked element.
9112 CompileRun("other[239] = 1");
9113
9114 ExpectUndefined("other[239]");
9115 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '239')");
9116 ExpectFalse("propertyIsEnumerable.call(other, '239')");
9117
9118 // Enable ACCESS_HAS
9119 allowed_access_type[v8::ACCESS_HAS] = true;
9120 ExpectUndefined("other[239]");
9121 // ... and now we can get the descriptor...
9122 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '239').value");
9123 // ... and enumerate the property.
9124 ExpectTrue("propertyIsEnumerable.call(other, '239')");
9125 allowed_access_type[v8::ACCESS_HAS] = false;
9126
9127 // Access a property with JS accessor.
9128 CompileRun("other.js_accessor_p = 2");
9129
9130 ExpectUndefined("other.js_accessor_p");
9131 ExpectUndefined(
9132 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p')");
9133
9134 // Enable ACCESS_HAS.
9135 allowed_access_type[v8::ACCESS_HAS] = true;
9136 ExpectUndefined("other.js_accessor_p");
9137 ExpectUndefined(
9138 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get");
9139 ExpectUndefined(
9140 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set");
9141 ExpectUndefined(
9142 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
9143 allowed_access_type[v8::ACCESS_HAS] = false;
9144
9145 // Enable both ACCESS_HAS and ACCESS_GET.
9146 allowed_access_type[v8::ACCESS_HAS] = true;
9147 allowed_access_type[v8::ACCESS_GET] = true;
9148
9149 ExpectString("other.js_accessor_p", "getter");
9150 ExpectObject(
9151 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get", getter);
9152 ExpectUndefined(
9153 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set");
9154 ExpectUndefined(
9155 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
9156
9157 allowed_access_type[v8::ACCESS_GET] = false;
9158 allowed_access_type[v8::ACCESS_HAS] = false;
9159
9160 // Enable both ACCESS_HAS and ACCESS_SET.
9161 allowed_access_type[v8::ACCESS_HAS] = true;
9162 allowed_access_type[v8::ACCESS_SET] = true;
9163
9164 ExpectUndefined("other.js_accessor_p");
9165 ExpectUndefined(
9166 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get");
9167 ExpectObject(
9168 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set", setter);
9169 ExpectUndefined(
9170 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
9171
9172 allowed_access_type[v8::ACCESS_SET] = false;
9173 allowed_access_type[v8::ACCESS_HAS] = false;
9174
9175 // Enable both ACCESS_HAS, ACCESS_GET and ACCESS_SET.
9176 allowed_access_type[v8::ACCESS_HAS] = true;
9177 allowed_access_type[v8::ACCESS_GET] = true;
9178 allowed_access_type[v8::ACCESS_SET] = true;
9179
9180 ExpectString("other.js_accessor_p", "getter");
9181 ExpectObject(
9182 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get", getter);
9183 ExpectObject(
9184 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set", setter);
9185 ExpectUndefined(
9186 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
9187
9188 allowed_access_type[v8::ACCESS_SET] = false;
9189 allowed_access_type[v8::ACCESS_GET] = false;
9190 allowed_access_type[v8::ACCESS_HAS] = false;
9191
9192 // Access an element with JS accessor.
9193 CompileRun("other[42] = 2");
9194
9195 ExpectUndefined("other[42]");
9196 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42')");
9197
9198 // Enable ACCESS_HAS.
9199 allowed_access_type[v8::ACCESS_HAS] = true;
9200 ExpectUndefined("other[42]");
9201 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').get");
9202 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').set");
9203 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
9204 allowed_access_type[v8::ACCESS_HAS] = false;
9205
9206 // Enable both ACCESS_HAS and ACCESS_GET.
9207 allowed_access_type[v8::ACCESS_HAS] = true;
9208 allowed_access_type[v8::ACCESS_GET] = true;
9209
9210 ExpectString("other[42]", "el_getter");
9211 ExpectObject("Object.getOwnPropertyDescriptor(other, '42').get", el_getter);
9212 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').set");
9213 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
9214
9215 allowed_access_type[v8::ACCESS_GET] = false;
9216 allowed_access_type[v8::ACCESS_HAS] = false;
9217
9218 // Enable both ACCESS_HAS and ACCESS_SET.
9219 allowed_access_type[v8::ACCESS_HAS] = true;
9220 allowed_access_type[v8::ACCESS_SET] = true;
9221
9222 ExpectUndefined("other[42]");
9223 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').get");
9224 ExpectObject("Object.getOwnPropertyDescriptor(other, '42').set", el_setter);
9225 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
9226
9227 allowed_access_type[v8::ACCESS_SET] = false;
9228 allowed_access_type[v8::ACCESS_HAS] = false;
9229
9230 // Enable both ACCESS_HAS, ACCESS_GET and ACCESS_SET.
9231 allowed_access_type[v8::ACCESS_HAS] = true;
9232 allowed_access_type[v8::ACCESS_GET] = true;
9233 allowed_access_type[v8::ACCESS_SET] = true;
9234
9235 ExpectString("other[42]", "el_getter");
9236 ExpectObject("Object.getOwnPropertyDescriptor(other, '42').get", el_getter);
9237 ExpectObject("Object.getOwnPropertyDescriptor(other, '42').set", el_setter);
9238 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
9239
9240 allowed_access_type[v8::ACCESS_SET] = false;
9241 allowed_access_type[v8::ACCESS_GET] = false;
9242 allowed_access_type[v8::ACCESS_HAS] = false;
9243
9244 v8::Handle<Value> value;
ager@chromium.org870a0b62008-11-04 11:43:05 +00009245
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009246 // Access accessible property
antonm@chromium.orgdca01352011-01-31 17:15:05 +00009247 value = CompileRun("other.accessible_prop = 3");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009248 CHECK(value->IsNumber());
9249 CHECK_EQ(3, value->Int32Value());
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00009250 CHECK_EQ(3, g_echo_value_1);
9251
9252 // Access accessible js property
9253 value = CompileRun("other.accessible_js_prop = 3");
9254 CHECK(value->IsNumber());
9255 CHECK_EQ(3, value->Int32Value());
9256 CHECK_EQ(3, g_echo_value_2);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009257
antonm@chromium.orgdca01352011-01-31 17:15:05 +00009258 value = CompileRun("other.accessible_prop");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009259 CHECK(value->IsNumber());
9260 CHECK_EQ(3, value->Int32Value());
9261
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00009262 value = CompileRun("other.accessible_js_prop");
9263 CHECK(value->IsNumber());
9264 CHECK_EQ(3, value->Int32Value());
9265
antonm@chromium.orgdca01352011-01-31 17:15:05 +00009266 value = CompileRun(
9267 "Object.getOwnPropertyDescriptor(other, 'accessible_prop').value");
9268 CHECK(value->IsNumber());
9269 CHECK_EQ(3, value->Int32Value());
9270
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00009271 value = CompileRun(
9272 "Object.getOwnPropertyDescriptor(other, 'accessible_js_prop').get()");
9273 CHECK(value->IsNumber());
9274 CHECK_EQ(3, value->Int32Value());
9275
antonm@chromium.orgdca01352011-01-31 17:15:05 +00009276 value = CompileRun("propertyIsEnumerable.call(other, 'accessible_prop')");
ager@chromium.org870a0b62008-11-04 11:43:05 +00009277 CHECK(value->IsTrue());
9278
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00009279 value = CompileRun("propertyIsEnumerable.call(other, 'accessible_js_prop')");
9280 CHECK(value->IsTrue());
9281
ager@chromium.org870a0b62008-11-04 11:43:05 +00009282 // Enumeration doesn't enumerate accessors from inaccessible objects in
9283 // the prototype chain even if the accessors are in themselves accessible.
antonm@chromium.orgdca01352011-01-31 17:15:05 +00009284 value =
ager@chromium.org870a0b62008-11-04 11:43:05 +00009285 CompileRun("(function(){var obj = {'__proto__':other};"
9286 "for (var p in obj)"
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00009287 " if (p == 'accessible_prop' ||"
9288 " p == 'accessible_js_prop' ||"
9289 " p == 'blocked_js_prop' ||"
9290 " p == 'blocked_js_prop') {"
ager@chromium.org870a0b62008-11-04 11:43:05 +00009291 " return false;"
9292 " }"
9293 "return true;})()");
antonm@chromium.orgdca01352011-01-31 17:15:05 +00009294 CHECK(value->IsTrue());
ager@chromium.org870a0b62008-11-04 11:43:05 +00009295
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009296 context1->Exit();
9297 context0->Exit();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009298}
9299
9300
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00009301TEST(AccessControlES5) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00009302 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009303 v8::HandleScope handle_scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00009304 v8::Handle<v8::ObjectTemplate> global_template =
9305 v8::ObjectTemplate::New(isolate);
ricow@chromium.org65001782011-02-15 13:36:41 +00009306
9307 global_template->SetAccessCheckCallbacks(NamedAccessBlocker,
9308 IndexedAccessBlocker);
9309
ricow@chromium.orgf5a18a22011-03-15 10:00:20 +00009310 // Add accessible accessor.
9311 global_template->SetAccessor(
9312 v8_str("accessible_prop"),
9313 EchoGetter, EchoSetter,
9314 v8::Handle<Value>(),
9315 v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
9316
9317
ricow@chromium.org65001782011-02-15 13:36:41 +00009318 // Add an accessor that is not accessible by cross-domain JS code.
9319 global_template->SetAccessor(v8_str("blocked_prop"),
9320 UnreachableGetter, UnreachableSetter,
9321 v8::Handle<Value>(),
9322 v8::DEFAULT);
9323
9324 // Create an environment
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009325 v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
ricow@chromium.org65001782011-02-15 13:36:41 +00009326 context0->Enter();
9327
9328 v8::Handle<v8::Object> global0 = context0->Global();
9329
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009330 v8::Local<Context> context1 = Context::New(isolate);
ricow@chromium.org65001782011-02-15 13:36:41 +00009331 context1->Enter();
9332 v8::Handle<v8::Object> global1 = context1->Global();
9333 global1->Set(v8_str("other"), global0);
9334
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00009335 // Regression test for issue 1154.
ricow@chromium.org65001782011-02-15 13:36:41 +00009336 ExpectTrue("Object.keys(other).indexOf('blocked_prop') == -1");
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00009337
9338 ExpectUndefined("other.blocked_prop");
9339
9340 // Regression test for issue 1027.
9341 CompileRun("Object.defineProperty(\n"
9342 " other, 'blocked_prop', {configurable: false})");
9343 ExpectUndefined("other.blocked_prop");
9344 ExpectUndefined(
9345 "Object.getOwnPropertyDescriptor(other, 'blocked_prop')");
9346
9347 // Regression test for issue 1171.
9348 ExpectTrue("Object.isExtensible(other)");
9349 CompileRun("Object.preventExtensions(other)");
9350 ExpectTrue("Object.isExtensible(other)");
9351
9352 // Object.seal and Object.freeze.
9353 CompileRun("Object.freeze(other)");
9354 ExpectTrue("Object.isExtensible(other)");
9355
9356 CompileRun("Object.seal(other)");
9357 ExpectTrue("Object.isExtensible(other)");
ricow@chromium.orgf5a18a22011-03-15 10:00:20 +00009358
9359 // Regression test for issue 1250.
9360 // Make sure that we can set the accessible accessors value using normal
9361 // assignment.
9362 CompileRun("other.accessible_prop = 42");
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00009363 CHECK_EQ(42, g_echo_value_1);
ricow@chromium.orgf5a18a22011-03-15 10:00:20 +00009364
9365 v8::Handle<Value> value;
9366 // We follow Safari in ignoring assignments to host object accessors.
9367 CompileRun("Object.defineProperty(other, 'accessible_prop', {value: -1})");
9368 value = CompileRun("other.accessible_prop == 42");
9369 CHECK(value->IsTrue());
ricow@chromium.org65001782011-02-15 13:36:41 +00009370}
9371
9372
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00009373static bool GetOwnPropertyNamesNamedBlocker(Local<v8::Object> global,
9374 Local<Value> name,
9375 v8::AccessType type,
9376 Local<Value> data) {
9377 return false;
9378}
9379
9380
9381static bool GetOwnPropertyNamesIndexedBlocker(Local<v8::Object> global,
9382 uint32_t key,
9383 v8::AccessType type,
9384 Local<Value> data) {
9385 return false;
9386}
9387
9388
9389THREADED_TEST(AccessControlGetOwnPropertyNames) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00009390 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009391 v8::HandleScope handle_scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00009392 v8::Handle<v8::ObjectTemplate> obj_template =
9393 v8::ObjectTemplate::New(isolate);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00009394
ulan@chromium.org0f13e742014-01-03 15:51:11 +00009395 obj_template->Set(v8_str("x"), v8::Integer::New(isolate, 42));
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00009396 obj_template->SetAccessCheckCallbacks(GetOwnPropertyNamesNamedBlocker,
9397 GetOwnPropertyNamesIndexedBlocker);
9398
9399 // Create an environment
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009400 v8::Local<Context> context0 = Context::New(isolate, NULL, obj_template);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00009401 context0->Enter();
9402
9403 v8::Handle<v8::Object> global0 = context0->Global();
9404
machenbach@chromium.org528ce022013-09-23 14:09:36 +00009405 v8::HandleScope scope1(CcTest::isolate());
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00009406
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009407 v8::Local<Context> context1 = Context::New(isolate);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00009408 context1->Enter();
9409
9410 v8::Handle<v8::Object> global1 = context1->Global();
9411 global1->Set(v8_str("other"), global0);
9412 global1->Set(v8_str("object"), obj_template->NewInstance());
9413
9414 v8::Handle<Value> value;
9415
9416 // Attempt to get the property names of the other global object and
9417 // of an object that requires access checks. Accessing the other
9418 // global object should be blocked by access checks on the global
9419 // proxy object. Accessing the object that requires access checks
9420 // is blocked by the access checks on the object itself.
9421 value = CompileRun("Object.getOwnPropertyNames(other).length == 0");
9422 CHECK(value->IsTrue());
9423
9424 value = CompileRun("Object.getOwnPropertyNames(object).length == 0");
9425 CHECK(value->IsTrue());
9426
9427 context1->Exit();
9428 context0->Exit();
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00009429}
9430
9431
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009432static void IndexedPropertyEnumerator(
9433 const v8::PropertyCallbackInfo<v8::Array>& info) {
machenbach@chromium.org9f18d912013-11-28 13:42:41 +00009434 v8::Handle<v8::Array> result = v8::Array::New(info.GetIsolate(), 2);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00009435 result->Set(0, v8::Integer::New(info.GetIsolate(), 7));
9436 result->Set(1, v8::Object::New(info.GetIsolate()));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009437 info.GetReturnValue().Set(result);
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +00009438}
9439
9440
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009441static void NamedPropertyEnumerator(
9442 const v8::PropertyCallbackInfo<v8::Array>& info) {
machenbach@chromium.org9f18d912013-11-28 13:42:41 +00009443 v8::Handle<v8::Array> result = v8::Array::New(info.GetIsolate(), 2);
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00009444 result->Set(0, v8_str("x"));
ulan@chromium.org0f13e742014-01-03 15:51:11 +00009445 result->Set(1, v8::Object::New(info.GetIsolate()));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009446 info.GetReturnValue().Set(result);
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00009447}
9448
9449
9450THREADED_TEST(GetOwnPropertyNamesWithInterceptor) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00009451 v8::Isolate* isolate = CcTest::isolate();
9452 v8::HandleScope handle_scope(isolate);
9453 v8::Handle<v8::ObjectTemplate> obj_template =
9454 v8::ObjectTemplate::New(isolate);
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00009455
ulan@chromium.org0f13e742014-01-03 15:51:11 +00009456 obj_template->Set(v8_str("7"), v8::Integer::New(CcTest::isolate(), 7));
9457 obj_template->Set(v8_str("x"), v8::Integer::New(CcTest::isolate(), 42));
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +00009458 obj_template->SetIndexedPropertyHandler(NULL, NULL, NULL, NULL,
9459 IndexedPropertyEnumerator);
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00009460 obj_template->SetNamedPropertyHandler(NULL, NULL, NULL, NULL,
9461 NamedPropertyEnumerator);
9462
9463 LocalContext context;
9464 v8::Handle<v8::Object> global = context->Global();
9465 global->Set(v8_str("object"), obj_template->NewInstance());
9466
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +00009467 v8::Handle<v8::Value> result =
9468 CompileRun("Object.getOwnPropertyNames(object)");
9469 CHECK(result->IsArray());
9470 v8::Handle<v8::Array> result_array = v8::Handle<v8::Array>::Cast(result);
9471 CHECK_EQ(3, result_array->Length());
9472 CHECK(result_array->Get(0)->IsString());
9473 CHECK(result_array->Get(1)->IsString());
9474 CHECK(result_array->Get(2)->IsString());
9475 CHECK_EQ(v8_str("7"), result_array->Get(0));
9476 CHECK_EQ(v8_str("[object Object]"), result_array->Get(1));
9477 CHECK_EQ(v8_str("x"), result_array->Get(2));
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00009478}
9479
9480
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009481static void ConstTenGetter(Local<String> name,
9482 const v8::PropertyCallbackInfo<v8::Value>& info) {
9483 info.GetReturnValue().Set(v8_num(10));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009484}
9485
9486
9487THREADED_TEST(CrossDomainAccessors) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00009488 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009489 v8::HandleScope handle_scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009490
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00009491 v8::Handle<v8::FunctionTemplate> func_template =
9492 v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009493
9494 v8::Handle<v8::ObjectTemplate> global_template =
9495 func_template->InstanceTemplate();
9496
9497 v8::Handle<v8::ObjectTemplate> proto_template =
9498 func_template->PrototypeTemplate();
9499
9500 // Add an accessor to proto that's accessible by cross-domain JS code.
9501 proto_template->SetAccessor(v8_str("accessible"),
9502 ConstTenGetter, 0,
9503 v8::Handle<Value>(),
9504 v8::ALL_CAN_READ);
9505
9506 // Add an accessor that is not accessible by cross-domain JS code.
9507 global_template->SetAccessor(v8_str("unreachable"),
9508 UnreachableGetter, 0,
9509 v8::Handle<Value>(),
9510 v8::DEFAULT);
9511
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009512 v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009513 context0->Enter();
9514
9515 Local<v8::Object> global = context0->Global();
9516 // Add a normal property that shadows 'accessible'
9517 global->Set(v8_str("accessible"), v8_num(11));
9518
9519 // Enter a new context.
machenbach@chromium.org528ce022013-09-23 14:09:36 +00009520 v8::HandleScope scope1(CcTest::isolate());
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009521 v8::Local<Context> context1 = Context::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009522 context1->Enter();
9523
9524 v8::Handle<v8::Object> global1 = context1->Global();
9525 global1->Set(v8_str("other"), global);
9526
9527 // Should return 10, instead of 11
9528 v8::Handle<Value> value = v8_compile("other.accessible")->Run();
9529 CHECK(value->IsNumber());
9530 CHECK_EQ(10, value->Int32Value());
9531
9532 value = v8_compile("other.unreachable")->Run();
9533 CHECK(value->IsUndefined());
9534
9535 context1->Exit();
9536 context0->Exit();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009537}
9538
9539
9540static int named_access_count = 0;
9541static int indexed_access_count = 0;
9542
9543static bool NamedAccessCounter(Local<v8::Object> global,
9544 Local<Value> name,
9545 v8::AccessType type,
9546 Local<Value> data) {
9547 named_access_count++;
9548 return true;
9549}
9550
9551
9552static bool IndexedAccessCounter(Local<v8::Object> global,
9553 uint32_t key,
9554 v8::AccessType type,
9555 Local<Value> data) {
9556 indexed_access_count++;
9557 return true;
9558}
9559
9560
9561// This one is too easily disturbed by other tests.
9562TEST(AccessControlIC) {
9563 named_access_count = 0;
9564 indexed_access_count = 0;
9565
machenbach@chromium.org528ce022013-09-23 14:09:36 +00009566 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009567 v8::HandleScope handle_scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009568
9569 // Create an environment.
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009570 v8::Local<Context> context0 = Context::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009571 context0->Enter();
9572
9573 // Create an object that requires access-check functions to be
9574 // called for cross-domain access.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00009575 v8::Handle<v8::ObjectTemplate> object_template =
9576 v8::ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009577 object_template->SetAccessCheckCallbacks(NamedAccessCounter,
9578 IndexedAccessCounter);
9579 Local<v8::Object> object = object_template->NewInstance();
9580
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009581 v8::HandleScope scope1(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009582
9583 // Create another environment.
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009584 v8::Local<Context> context1 = Context::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009585 context1->Enter();
9586
9587 // Make easy access to the object from the other environment.
9588 v8::Handle<v8::Object> global1 = context1->Global();
9589 global1->Set(v8_str("obj"), object);
9590
9591 v8::Handle<Value> value;
9592
9593 // Check that the named access-control function is called every time.
ager@chromium.org8bb60582008-12-11 12:02:20 +00009594 CompileRun("function testProp(obj) {"
9595 " for (var i = 0; i < 10; i++) obj.prop = 1;"
9596 " for (var j = 0; j < 10; j++) obj.prop;"
9597 " return obj.prop"
9598 "}");
9599 value = CompileRun("testProp(obj)");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009600 CHECK(value->IsNumber());
9601 CHECK_EQ(1, value->Int32Value());
9602 CHECK_EQ(21, named_access_count);
9603
9604 // Check that the named access-control function is called every time.
ager@chromium.org8bb60582008-12-11 12:02:20 +00009605 CompileRun("var p = 'prop';"
9606 "function testKeyed(obj) {"
9607 " for (var i = 0; i < 10; i++) obj[p] = 1;"
9608 " for (var j = 0; j < 10; j++) obj[p];"
9609 " return obj[p];"
9610 "}");
9611 // Use obj which requires access checks. No inline caching is used
9612 // in that case.
9613 value = CompileRun("testKeyed(obj)");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009614 CHECK(value->IsNumber());
9615 CHECK_EQ(1, value->Int32Value());
9616 CHECK_EQ(42, named_access_count);
ager@chromium.org8bb60582008-12-11 12:02:20 +00009617 // Force the inline caches into generic state and try again.
9618 CompileRun("testKeyed({ a: 0 })");
9619 CompileRun("testKeyed({ b: 0 })");
9620 value = CompileRun("testKeyed(obj)");
9621 CHECK(value->IsNumber());
9622 CHECK_EQ(1, value->Int32Value());
9623 CHECK_EQ(63, named_access_count);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009624
9625 // Check that the indexed access-control function is called every time.
ager@chromium.org8bb60582008-12-11 12:02:20 +00009626 CompileRun("function testIndexed(obj) {"
9627 " for (var i = 0; i < 10; i++) obj[0] = 1;"
9628 " for (var j = 0; j < 10; j++) obj[0];"
9629 " return obj[0]"
9630 "}");
9631 value = CompileRun("testIndexed(obj)");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009632 CHECK(value->IsNumber());
9633 CHECK_EQ(1, value->Int32Value());
9634 CHECK_EQ(21, indexed_access_count);
ager@chromium.org8bb60582008-12-11 12:02:20 +00009635 // Force the inline caches into generic state.
9636 CompileRun("testIndexed(new Array(1))");
9637 // Test that the indexed access check is called.
9638 value = CompileRun("testIndexed(obj)");
9639 CHECK(value->IsNumber());
9640 CHECK_EQ(1, value->Int32Value());
9641 CHECK_EQ(42, indexed_access_count);
9642
9643 // Check that the named access check is called when invoking
9644 // functions on an object that requires access checks.
9645 CompileRun("obj.f = function() {}");
9646 CompileRun("function testCallNormal(obj) {"
9647 " for (var i = 0; i < 10; i++) obj.f();"
9648 "}");
9649 CompileRun("testCallNormal(obj)");
9650 CHECK_EQ(74, named_access_count);
9651
9652 // Force obj into slow case.
9653 value = CompileRun("delete obj.prop");
9654 CHECK(value->BooleanValue());
9655 // Force inline caches into dictionary probing mode.
9656 CompileRun("var o = { x: 0 }; delete o.x; testProp(o);");
9657 // Test that the named access check is called.
9658 value = CompileRun("testProp(obj);");
9659 CHECK(value->IsNumber());
9660 CHECK_EQ(1, value->Int32Value());
9661 CHECK_EQ(96, named_access_count);
9662
9663 // Force the call inline cache into dictionary probing mode.
9664 CompileRun("o.f = function() {}; testCallNormal(o)");
9665 // Test that the named access check is still called for each
9666 // invocation of the function.
9667 value = CompileRun("testCallNormal(obj)");
9668 CHECK_EQ(106, named_access_count);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009669
9670 context1->Exit();
9671 context0->Exit();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009672}
9673
9674
9675static bool NamedAccessFlatten(Local<v8::Object> global,
9676 Local<Value> name,
9677 v8::AccessType type,
9678 Local<Value> data) {
9679 char buf[100];
9680 int len;
9681
9682 CHECK(name->IsString());
9683
9684 memset(buf, 0x1, sizeof(buf));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009685 len = name.As<String>()->WriteOneByte(reinterpret_cast<uint8_t*>(buf));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009686 CHECK_EQ(4, len);
9687
9688 uint16_t buf2[100];
9689
9690 memset(buf, 0x1, sizeof(buf));
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00009691 len = name.As<String>()->Write(buf2);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009692 CHECK_EQ(4, len);
9693
9694 return true;
9695}
9696
9697
9698static bool IndexedAccessFlatten(Local<v8::Object> global,
9699 uint32_t key,
9700 v8::AccessType type,
9701 Local<Value> data) {
9702 return true;
9703}
9704
9705
9706// Regression test. In access checks, operations that may cause
9707// garbage collection are not allowed. It used to be the case that
9708// using the Write operation on a string could cause a garbage
9709// collection due to flattening of the string. This is no longer the
9710// case.
9711THREADED_TEST(AccessControlFlatten) {
9712 named_access_count = 0;
9713 indexed_access_count = 0;
9714
machenbach@chromium.org528ce022013-09-23 14:09:36 +00009715 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009716 v8::HandleScope handle_scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009717
9718 // Create an environment.
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009719 v8::Local<Context> context0 = Context::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009720 context0->Enter();
9721
9722 // Create an object that requires access-check functions to be
9723 // called for cross-domain access.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00009724 v8::Handle<v8::ObjectTemplate> object_template =
9725 v8::ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009726 object_template->SetAccessCheckCallbacks(NamedAccessFlatten,
9727 IndexedAccessFlatten);
9728 Local<v8::Object> object = object_template->NewInstance();
9729
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009730 v8::HandleScope scope1(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009731
9732 // Create another environment.
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009733 v8::Local<Context> context1 = Context::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009734 context1->Enter();
9735
9736 // Make easy access to the object from the other environment.
9737 v8::Handle<v8::Object> global1 = context1->Global();
9738 global1->Set(v8_str("obj"), object);
9739
9740 v8::Handle<Value> value;
9741
9742 value = v8_compile("var p = 'as' + 'df';")->Run();
9743 value = v8_compile("obj[p];")->Run();
9744
9745 context1->Exit();
9746 context0->Exit();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009747}
9748
9749
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009750static void AccessControlNamedGetter(
9751 Local<String>,
9752 const v8::PropertyCallbackInfo<v8::Value>& info) {
9753 info.GetReturnValue().Set(42);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009754}
9755
9756
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009757static void AccessControlNamedSetter(
9758 Local<String>,
9759 Local<Value> value,
9760 const v8::PropertyCallbackInfo<v8::Value>& info) {
9761 info.GetReturnValue().Set(value);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009762}
9763
9764
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009765static void AccessControlIndexedGetter(
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009766 uint32_t index,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009767 const v8::PropertyCallbackInfo<v8::Value>& info) {
9768 info.GetReturnValue().Set(v8_num(42));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009769}
9770
9771
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009772static void AccessControlIndexedSetter(
9773 uint32_t,
9774 Local<Value> value,
9775 const v8::PropertyCallbackInfo<v8::Value>& info) {
9776 info.GetReturnValue().Set(value);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009777}
9778
9779
9780THREADED_TEST(AccessControlInterceptorIC) {
9781 named_access_count = 0;
9782 indexed_access_count = 0;
9783
machenbach@chromium.org528ce022013-09-23 14:09:36 +00009784 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009785 v8::HandleScope handle_scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009786
9787 // Create an environment.
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009788 v8::Local<Context> context0 = Context::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009789 context0->Enter();
9790
9791 // Create an object that requires access-check functions to be
9792 // called for cross-domain access. The object also has interceptors
9793 // interceptor.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00009794 v8::Handle<v8::ObjectTemplate> object_template =
9795 v8::ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009796 object_template->SetAccessCheckCallbacks(NamedAccessCounter,
9797 IndexedAccessCounter);
9798 object_template->SetNamedPropertyHandler(AccessControlNamedGetter,
9799 AccessControlNamedSetter);
9800 object_template->SetIndexedPropertyHandler(AccessControlIndexedGetter,
9801 AccessControlIndexedSetter);
9802 Local<v8::Object> object = object_template->NewInstance();
9803
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009804 v8::HandleScope scope1(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009805
9806 // Create another environment.
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009807 v8::Local<Context> context1 = Context::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009808 context1->Enter();
9809
9810 // Make easy access to the object from the other environment.
9811 v8::Handle<v8::Object> global1 = context1->Global();
9812 global1->Set(v8_str("obj"), object);
9813
9814 v8::Handle<Value> value;
9815
9816 // Check that the named access-control function is called every time
9817 // eventhough there is an interceptor on the object.
9818 value = v8_compile("for (var i = 0; i < 10; i++) obj.x = 1;")->Run();
9819 value = v8_compile("for (var i = 0; i < 10; i++) obj.x;"
9820 "obj.x")->Run();
9821 CHECK(value->IsNumber());
9822 CHECK_EQ(42, value->Int32Value());
9823 CHECK_EQ(21, named_access_count);
9824
9825 value = v8_compile("var p = 'x';")->Run();
9826 value = v8_compile("for (var i = 0; i < 10; i++) obj[p] = 1;")->Run();
9827 value = v8_compile("for (var i = 0; i < 10; i++) obj[p];"
9828 "obj[p]")->Run();
9829 CHECK(value->IsNumber());
9830 CHECK_EQ(42, value->Int32Value());
9831 CHECK_EQ(42, named_access_count);
9832
9833 // Check that the indexed access-control function is called every
9834 // time eventhough there is an interceptor on the object.
9835 value = v8_compile("for (var i = 0; i < 10; i++) obj[0] = 1;")->Run();
9836 value = v8_compile("for (var i = 0; i < 10; i++) obj[0];"
9837 "obj[0]")->Run();
9838 CHECK(value->IsNumber());
9839 CHECK_EQ(42, value->Int32Value());
9840 CHECK_EQ(21, indexed_access_count);
9841
9842 context1->Exit();
9843 context0->Exit();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009844}
9845
9846
9847THREADED_TEST(Version) {
9848 v8::V8::GetVersion();
9849}
9850
9851
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009852static void InstanceFunctionCallback(
9853 const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009854 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009855 args.GetReturnValue().Set(v8_num(12));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009856}
9857
9858
9859THREADED_TEST(InstanceProperties) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009860 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00009861 v8::Isolate* isolate = context->GetIsolate();
9862 v8::HandleScope handle_scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009863
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00009864 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009865 Local<ObjectTemplate> instance = t->InstanceTemplate();
9866
9867 instance->Set(v8_str("x"), v8_num(42));
9868 instance->Set(v8_str("f"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00009869 v8::FunctionTemplate::New(isolate, InstanceFunctionCallback));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009870
9871 Local<Value> o = t->GetFunction()->NewInstance();
9872
9873 context->Global()->Set(v8_str("i"), o);
9874 Local<Value> value = Script::Compile(v8_str("i.x"))->Run();
9875 CHECK_EQ(42, value->Int32Value());
9876
9877 value = Script::Compile(v8_str("i.f()"))->Run();
9878 CHECK_EQ(12, value->Int32Value());
9879}
9880
9881
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009882static void GlobalObjectInstancePropertiesGet(
9883 Local<String> key,
9884 const v8::PropertyCallbackInfo<v8::Value>&) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009885 ApiTestFuzzer::Fuzz();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009886}
9887
9888
9889THREADED_TEST(GlobalObjectInstanceProperties) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00009890 v8::Isolate* isolate = CcTest::isolate();
9891 v8::HandleScope handle_scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009892
9893 Local<Value> global_object;
9894
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00009895 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009896 t->InstanceTemplate()->SetNamedPropertyHandler(
9897 GlobalObjectInstancePropertiesGet);
9898 Local<ObjectTemplate> instance_template = t->InstanceTemplate();
9899 instance_template->Set(v8_str("x"), v8_num(42));
9900 instance_template->Set(v8_str("f"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00009901 v8::FunctionTemplate::New(isolate,
9902 InstanceFunctionCallback));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009903
kasperl@chromium.orga5551262010-12-07 12:49:48 +00009904 // The script to check how Crankshaft compiles missing global function
9905 // invocations. function g is not defined and should throw on call.
9906 const char* script =
9907 "function wrapper(call) {"
9908 " var x = 0, y = 1;"
9909 " for (var i = 0; i < 1000; i++) {"
9910 " x += i * 100;"
9911 " y += i * 100;"
9912 " }"
9913 " if (call) g();"
9914 "}"
9915 "for (var i = 0; i < 17; i++) wrapper(false);"
9916 "var thrown = 0;"
9917 "try { wrapper(true); } catch (e) { thrown = 1; };"
9918 "thrown";
9919
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009920 {
9921 LocalContext env(NULL, instance_template);
9922 // Hold on to the global object so it can be used again in another
9923 // environment initialization.
9924 global_object = env->Global();
9925
9926 Local<Value> value = Script::Compile(v8_str("x"))->Run();
9927 CHECK_EQ(42, value->Int32Value());
9928 value = Script::Compile(v8_str("f()"))->Run();
9929 CHECK_EQ(12, value->Int32Value());
kasperl@chromium.orga5551262010-12-07 12:49:48 +00009930 value = Script::Compile(v8_str(script))->Run();
9931 CHECK_EQ(1, value->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009932 }
9933
9934 {
9935 // Create new environment reusing the global object.
9936 LocalContext env(NULL, instance_template, global_object);
9937 Local<Value> value = Script::Compile(v8_str("x"))->Run();
9938 CHECK_EQ(42, value->Int32Value());
9939 value = Script::Compile(v8_str("f()"))->Run();
9940 CHECK_EQ(12, value->Int32Value());
kasperl@chromium.orga5551262010-12-07 12:49:48 +00009941 value = Script::Compile(v8_str(script))->Run();
9942 CHECK_EQ(1, value->Int32Value());
9943 }
9944}
9945
9946
9947THREADED_TEST(CallKnownGlobalReceiver) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00009948 v8::Isolate* isolate = CcTest::isolate();
9949 v8::HandleScope handle_scope(isolate);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00009950
9951 Local<Value> global_object;
9952
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00009953 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00009954 Local<ObjectTemplate> instance_template = t->InstanceTemplate();
9955
9956 // The script to check that we leave global object not
9957 // global object proxy on stack when we deoptimize from inside
9958 // arguments evaluation.
9959 // To provoke error we need to both force deoptimization
9960 // from arguments evaluation and to force CallIC to take
9961 // CallIC_Miss code path that can't cope with global proxy.
9962 const char* script =
9963 "function bar(x, y) { try { } finally { } }"
9964 "function baz(x) { try { } finally { } }"
9965 "function bom(x) { try { } finally { } }"
9966 "function foo(x) { bar([x], bom(2)); }"
9967 "for (var i = 0; i < 10000; i++) foo(1);"
9968 "foo";
9969
9970 Local<Value> foo;
9971 {
9972 LocalContext env(NULL, instance_template);
9973 // Hold on to the global object so it can be used again in another
9974 // environment initialization.
9975 global_object = env->Global();
9976 foo = Script::Compile(v8_str(script))->Run();
9977 }
9978
9979 {
9980 // Create new environment reusing the global object.
9981 LocalContext env(NULL, instance_template, global_object);
9982 env->Global()->Set(v8_str("foo"), foo);
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00009983 Script::Compile(v8_str("foo()"))->Run();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009984 }
9985}
9986
9987
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009988static void ShadowFunctionCallback(
9989 const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009990 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009991 args.GetReturnValue().Set(v8_num(42));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009992}
9993
9994
9995static int shadow_y;
9996static int shadow_y_setter_call_count;
9997static int shadow_y_getter_call_count;
9998
9999
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010000static void ShadowYSetter(Local<String>,
10001 Local<Value>,
10002 const v8::PropertyCallbackInfo<void>&) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010003 shadow_y_setter_call_count++;
10004 shadow_y = 42;
10005}
10006
10007
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010008static void ShadowYGetter(Local<String> name,
10009 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010010 ApiTestFuzzer::Fuzz();
10011 shadow_y_getter_call_count++;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010012 info.GetReturnValue().Set(v8_num(shadow_y));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010013}
10014
10015
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010016static void ShadowIndexedGet(uint32_t index,
10017 const v8::PropertyCallbackInfo<v8::Value>&) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010018}
10019
10020
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010021static void ShadowNamedGet(Local<String> key,
10022 const v8::PropertyCallbackInfo<v8::Value>&) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010023}
10024
10025
10026THREADED_TEST(ShadowObject) {
10027 shadow_y = shadow_y_setter_call_count = shadow_y_getter_call_count = 0;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010028 v8::Isolate* isolate = CcTest::isolate();
10029 v8::HandleScope handle_scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010030
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000010031 Local<ObjectTemplate> global_template = v8::ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010032 LocalContext context(NULL, global_template);
10033
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010034 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010035 t->InstanceTemplate()->SetNamedPropertyHandler(ShadowNamedGet);
10036 t->InstanceTemplate()->SetIndexedPropertyHandler(ShadowIndexedGet);
10037 Local<ObjectTemplate> proto = t->PrototypeTemplate();
10038 Local<ObjectTemplate> instance = t->InstanceTemplate();
10039
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010040 proto->Set(v8_str("f"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010041 v8::FunctionTemplate::New(isolate,
10042 ShadowFunctionCallback,
10043 Local<Value>()));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010044 proto->Set(v8_str("x"), v8_num(12));
10045
10046 instance->SetAccessor(v8_str("y"), ShadowYGetter, ShadowYSetter);
10047
10048 Local<Value> o = t->GetFunction()->NewInstance();
10049 context->Global()->Set(v8_str("__proto__"), o);
10050
10051 Local<Value> value =
ricow@chromium.orgd2be9012011-06-01 06:00:58 +000010052 Script::Compile(v8_str("this.propertyIsEnumerable(0)"))->Run();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010053 CHECK(value->IsBoolean());
10054 CHECK(!value->BooleanValue());
10055
10056 value = Script::Compile(v8_str("x"))->Run();
10057 CHECK_EQ(12, value->Int32Value());
10058
10059 value = Script::Compile(v8_str("f()"))->Run();
10060 CHECK_EQ(42, value->Int32Value());
10061
mmassi@chromium.org7028c052012-06-13 11:51:58 +000010062 Script::Compile(v8_str("y = 43"))->Run();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010063 CHECK_EQ(1, shadow_y_setter_call_count);
10064 value = Script::Compile(v8_str("y"))->Run();
10065 CHECK_EQ(1, shadow_y_getter_call_count);
10066 CHECK_EQ(42, value->Int32Value());
10067}
10068
10069
10070THREADED_TEST(HiddenPrototype) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010071 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010072 v8::Isolate* isolate = context->GetIsolate();
10073 v8::HandleScope handle_scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010074
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010075 Local<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010076 t0->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010077 Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010078 t1->SetHiddenPrototype(true);
10079 t1->InstanceTemplate()->Set(v8_str("y"), v8_num(1));
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010080 Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010081 t2->SetHiddenPrototype(true);
10082 t2->InstanceTemplate()->Set(v8_str("z"), v8_num(2));
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010083 Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010084 t3->InstanceTemplate()->Set(v8_str("u"), v8_num(3));
10085
10086 Local<v8::Object> o0 = t0->GetFunction()->NewInstance();
10087 Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
10088 Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
10089 Local<v8::Object> o3 = t3->GetFunction()->NewInstance();
10090
10091 // Setting the prototype on an object skips hidden prototypes.
10092 CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
10093 o0->Set(v8_str("__proto__"), o1);
10094 CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
10095 CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
10096 o0->Set(v8_str("__proto__"), o2);
10097 CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
10098 CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
10099 CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
10100 o0->Set(v8_str("__proto__"), o3);
10101 CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
10102 CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
10103 CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
10104 CHECK_EQ(3, o0->Get(v8_str("u"))->Int32Value());
10105
10106 // Getting the prototype of o0 should get the first visible one
10107 // which is o3. Therefore, z should not be defined on the prototype
10108 // object.
10109 Local<Value> proto = o0->Get(v8_str("__proto__"));
10110 CHECK(proto->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000010111 CHECK(proto.As<v8::Object>()->Get(v8_str("z"))->IsUndefined());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010112}
10113
10114
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000010115THREADED_TEST(HiddenPrototypeSet) {
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000010116 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010117 v8::Isolate* isolate = context->GetIsolate();
10118 v8::HandleScope handle_scope(isolate);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000010119
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010120 Local<v8::FunctionTemplate> ot = v8::FunctionTemplate::New(isolate);
10121 Local<v8::FunctionTemplate> ht = v8::FunctionTemplate::New(isolate);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000010122 ht->SetHiddenPrototype(true);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010123 Local<v8::FunctionTemplate> pt = v8::FunctionTemplate::New(isolate);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000010124 ht->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
10125
10126 Local<v8::Object> o = ot->GetFunction()->NewInstance();
10127 Local<v8::Object> h = ht->GetFunction()->NewInstance();
10128 Local<v8::Object> p = pt->GetFunction()->NewInstance();
10129 o->Set(v8_str("__proto__"), h);
10130 h->Set(v8_str("__proto__"), p);
10131
10132 // Setting a property that exists on the hidden prototype goes there.
10133 o->Set(v8_str("x"), v8_num(7));
10134 CHECK_EQ(7, o->Get(v8_str("x"))->Int32Value());
10135 CHECK_EQ(7, h->Get(v8_str("x"))->Int32Value());
10136 CHECK(p->Get(v8_str("x"))->IsUndefined());
10137
10138 // Setting a new property should not be forwarded to the hidden prototype.
10139 o->Set(v8_str("y"), v8_num(6));
10140 CHECK_EQ(6, o->Get(v8_str("y"))->Int32Value());
10141 CHECK(h->Get(v8_str("y"))->IsUndefined());
10142 CHECK(p->Get(v8_str("y"))->IsUndefined());
10143
10144 // Setting a property that only exists on a prototype of the hidden prototype
10145 // is treated normally again.
10146 p->Set(v8_str("z"), v8_num(8));
10147 CHECK_EQ(8, o->Get(v8_str("z"))->Int32Value());
10148 CHECK_EQ(8, h->Get(v8_str("z"))->Int32Value());
10149 CHECK_EQ(8, p->Get(v8_str("z"))->Int32Value());
10150 o->Set(v8_str("z"), v8_num(9));
10151 CHECK_EQ(9, o->Get(v8_str("z"))->Int32Value());
10152 CHECK_EQ(8, h->Get(v8_str("z"))->Int32Value());
10153 CHECK_EQ(8, p->Get(v8_str("z"))->Int32Value());
10154}
10155
10156
10157// Regression test for issue 2457.
10158THREADED_TEST(HiddenPrototypeIdentityHash) {
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000010159 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000010160 v8::HandleScope handle_scope(context->GetIsolate());
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000010161
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010162 Handle<FunctionTemplate> t = FunctionTemplate::New(context->GetIsolate());
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000010163 t->SetHiddenPrototype(true);
10164 t->InstanceTemplate()->Set(v8_str("foo"), v8_num(75));
10165 Handle<Object> p = t->GetFunction()->NewInstance();
ulan@chromium.org0f13e742014-01-03 15:51:11 +000010166 Handle<Object> o = Object::New(context->GetIsolate());
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000010167 o->SetPrototype(p);
10168
10169 int hash = o->GetIdentityHash();
10170 USE(hash);
10171 o->Set(v8_str("foo"), v8_num(42));
10172 ASSERT_EQ(hash, o->GetIdentityHash());
10173}
10174
10175
ager@chromium.org5c838252010-02-19 08:53:10 +000010176THREADED_TEST(SetPrototype) {
ager@chromium.org5c838252010-02-19 08:53:10 +000010177 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010178 v8::Isolate* isolate = context->GetIsolate();
10179 v8::HandleScope handle_scope(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +000010180
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010181 Local<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +000010182 t0->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010183 Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +000010184 t1->SetHiddenPrototype(true);
10185 t1->InstanceTemplate()->Set(v8_str("y"), v8_num(1));
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010186 Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +000010187 t2->SetHiddenPrototype(true);
10188 t2->InstanceTemplate()->Set(v8_str("z"), v8_num(2));
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010189 Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +000010190 t3->InstanceTemplate()->Set(v8_str("u"), v8_num(3));
10191
10192 Local<v8::Object> o0 = t0->GetFunction()->NewInstance();
10193 Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
10194 Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
10195 Local<v8::Object> o3 = t3->GetFunction()->NewInstance();
10196
10197 // Setting the prototype on an object does not skip hidden prototypes.
10198 CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
10199 CHECK(o0->SetPrototype(o1));
10200 CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
10201 CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
10202 CHECK(o1->SetPrototype(o2));
10203 CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
10204 CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
10205 CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
10206 CHECK(o2->SetPrototype(o3));
10207 CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
10208 CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
10209 CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
10210 CHECK_EQ(3, o0->Get(v8_str("u"))->Int32Value());
10211
10212 // Getting the prototype of o0 should get the first visible one
10213 // which is o3. Therefore, z should not be defined on the prototype
10214 // object.
10215 Local<Value> proto = o0->Get(v8_str("__proto__"));
10216 CHECK(proto->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000010217 CHECK_EQ(proto.As<v8::Object>(), o3);
ager@chromium.org5c838252010-02-19 08:53:10 +000010218
10219 // However, Object::GetPrototype ignores hidden prototype.
10220 Local<Value> proto0 = o0->GetPrototype();
10221 CHECK(proto0->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000010222 CHECK_EQ(proto0.As<v8::Object>(), o1);
ager@chromium.org5c838252010-02-19 08:53:10 +000010223
10224 Local<Value> proto1 = o1->GetPrototype();
10225 CHECK(proto1->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000010226 CHECK_EQ(proto1.As<v8::Object>(), o2);
ager@chromium.org5c838252010-02-19 08:53:10 +000010227
10228 Local<Value> proto2 = o2->GetPrototype();
10229 CHECK(proto2->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000010230 CHECK_EQ(proto2.As<v8::Object>(), o3);
ager@chromium.org5c838252010-02-19 08:53:10 +000010231}
10232
10233
ricow@chromium.org27bf2882011-11-17 08:34:43 +000010234// Getting property names of an object with a prototype chain that
10235// triggers dictionary elements in GetLocalPropertyNames() shouldn't
10236// crash the runtime.
10237THREADED_TEST(Regress91517) {
10238 i::FLAG_allow_natives_syntax = true;
ricow@chromium.org27bf2882011-11-17 08:34:43 +000010239 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010240 v8::Isolate* isolate = context->GetIsolate();
10241 v8::HandleScope handle_scope(isolate);
ricow@chromium.org27bf2882011-11-17 08:34:43 +000010242
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010243 Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
ricow@chromium.org27bf2882011-11-17 08:34:43 +000010244 t1->SetHiddenPrototype(true);
10245 t1->InstanceTemplate()->Set(v8_str("foo"), v8_num(1));
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010246 Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
ricow@chromium.org27bf2882011-11-17 08:34:43 +000010247 t2->SetHiddenPrototype(true);
10248 t2->InstanceTemplate()->Set(v8_str("fuz1"), v8_num(2));
ulan@chromium.org0f13e742014-01-03 15:51:11 +000010249 t2->InstanceTemplate()->Set(v8_str("objects"), v8::Object::New(isolate));
ricow@chromium.org27bf2882011-11-17 08:34:43 +000010250 t2->InstanceTemplate()->Set(v8_str("fuz2"), v8_num(2));
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010251 Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
ricow@chromium.org27bf2882011-11-17 08:34:43 +000010252 t3->SetHiddenPrototype(true);
10253 t3->InstanceTemplate()->Set(v8_str("boo"), v8_num(3));
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010254 Local<v8::FunctionTemplate> t4 = v8::FunctionTemplate::New(isolate);
ricow@chromium.org27bf2882011-11-17 08:34:43 +000010255 t4->InstanceTemplate()->Set(v8_str("baz"), v8_num(4));
10256
10257 // Force dictionary-based properties.
10258 i::ScopedVector<char> name_buf(1024);
10259 for (int i = 1; i <= 1000; i++) {
10260 i::OS::SNPrintF(name_buf, "sdf%d", i);
10261 t2->InstanceTemplate()->Set(v8_str(name_buf.start()), v8_num(2));
10262 }
10263
10264 Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
10265 Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
10266 Local<v8::Object> o3 = t3->GetFunction()->NewInstance();
10267 Local<v8::Object> o4 = t4->GetFunction()->NewInstance();
10268
10269 // Create prototype chain of hidden prototypes.
10270 CHECK(o4->SetPrototype(o3));
10271 CHECK(o3->SetPrototype(o2));
10272 CHECK(o2->SetPrototype(o1));
10273
10274 // Call the runtime version of GetLocalPropertyNames() on the natively
10275 // created object through JavaScript.
10276 context->Global()->Set(v8_str("obj"), o4);
machenbach@chromium.org03453962014-01-10 14:16:31 +000010277 // PROPERTY_ATTRIBUTES_NONE = 0
10278 CompileRun("var names = %GetLocalPropertyNames(obj, 0);");
ricow@chromium.org27bf2882011-11-17 08:34:43 +000010279
10280 ExpectInt32("names.length", 1006);
10281 ExpectTrue("names.indexOf(\"baz\") >= 0");
10282 ExpectTrue("names.indexOf(\"boo\") >= 0");
10283 ExpectTrue("names.indexOf(\"foo\") >= 0");
10284 ExpectTrue("names.indexOf(\"fuz1\") >= 0");
10285 ExpectTrue("names.indexOf(\"fuz2\") >= 0");
10286 ExpectFalse("names[1005] == undefined");
10287}
10288
10289
ulan@chromium.org0f13e742014-01-03 15:51:11 +000010290// Getting property names of an object with a hidden and inherited
10291// prototype should not duplicate the accessor properties inherited.
10292THREADED_TEST(Regress269562) {
10293 i::FLAG_allow_natives_syntax = true;
10294 LocalContext context;
10295 v8::HandleScope handle_scope(context->GetIsolate());
10296
10297 Local<v8::FunctionTemplate> t1 =
10298 v8::FunctionTemplate::New(context->GetIsolate());
10299 t1->SetHiddenPrototype(true);
10300
10301 Local<v8::ObjectTemplate> i1 = t1->InstanceTemplate();
10302 i1->SetAccessor(v8_str("foo"),
10303 SimpleAccessorGetter, SimpleAccessorSetter);
10304 i1->SetAccessor(v8_str("bar"),
10305 SimpleAccessorGetter, SimpleAccessorSetter);
10306 i1->SetAccessor(v8_str("baz"),
10307 SimpleAccessorGetter, SimpleAccessorSetter);
10308 i1->Set(v8_str("n1"), v8_num(1));
10309 i1->Set(v8_str("n2"), v8_num(2));
10310
10311 Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
10312 Local<v8::FunctionTemplate> t2 =
10313 v8::FunctionTemplate::New(context->GetIsolate());
10314 t2->SetHiddenPrototype(true);
10315
10316 // Inherit from t1 and mark prototype as hidden.
10317 t2->Inherit(t1);
10318 t2->InstanceTemplate()->Set(v8_str("mine"), v8_num(4));
10319
10320 Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
10321 CHECK(o2->SetPrototype(o1));
10322
10323 v8::Local<v8::Symbol> sym = v8::Symbol::New(context->GetIsolate(), "s1");
10324 o1->Set(sym, v8_num(3));
10325 o1->SetHiddenValue(v8_str("h1"),
10326 v8::Integer::New(context->GetIsolate(), 2013));
10327
10328 // Call the runtime version of GetLocalPropertyNames() on
10329 // the natively created object through JavaScript.
10330 context->Global()->Set(v8_str("obj"), o2);
10331 context->Global()->Set(v8_str("sym"), sym);
machenbach@chromium.org03453962014-01-10 14:16:31 +000010332 // PROPERTY_ATTRIBUTES_NONE = 0
10333 CompileRun("var names = %GetLocalPropertyNames(obj, 0);");
ulan@chromium.org0f13e742014-01-03 15:51:11 +000010334
10335 ExpectInt32("names.length", 7);
10336 ExpectTrue("names.indexOf(\"foo\") >= 0");
10337 ExpectTrue("names.indexOf(\"bar\") >= 0");
10338 ExpectTrue("names.indexOf(\"baz\") >= 0");
10339 ExpectTrue("names.indexOf(\"n1\") >= 0");
10340 ExpectTrue("names.indexOf(\"n2\") >= 0");
10341 ExpectTrue("names.indexOf(sym) >= 0");
10342 ExpectTrue("names.indexOf(\"mine\") >= 0");
10343}
10344
10345
ricow@chromium.org2c99e282011-07-28 09:15:17 +000010346THREADED_TEST(FunctionReadOnlyPrototype) {
ager@chromium.org04921a82011-06-27 13:21:41 +000010347 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010348 v8::Isolate* isolate = context->GetIsolate();
10349 v8::HandleScope handle_scope(isolate);
ager@chromium.org04921a82011-06-27 13:21:41 +000010350
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010351 Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000010352 t1->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(isolate, 42));
ricow@chromium.org2c99e282011-07-28 09:15:17 +000010353 t1->ReadOnlyPrototype();
ager@chromium.org04921a82011-06-27 13:21:41 +000010354 context->Global()->Set(v8_str("func1"), t1->GetFunction());
ricow@chromium.org2c99e282011-07-28 09:15:17 +000010355 // Configured value of ReadOnly flag.
ager@chromium.org04921a82011-06-27 13:21:41 +000010356 CHECK(CompileRun(
10357 "(function() {"
10358 " descriptor = Object.getOwnPropertyDescriptor(func1, 'prototype');"
ricow@chromium.org2c99e282011-07-28 09:15:17 +000010359 " return (descriptor['writable'] == false);"
ager@chromium.org04921a82011-06-27 13:21:41 +000010360 "})()")->BooleanValue());
ricow@chromium.org2c99e282011-07-28 09:15:17 +000010361 CHECK_EQ(42, CompileRun("func1.prototype.x")->Int32Value());
10362 CHECK_EQ(42,
10363 CompileRun("func1.prototype = {}; func1.prototype.x")->Int32Value());
ager@chromium.org04921a82011-06-27 13:21:41 +000010364
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010365 Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000010366 t2->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(isolate, 42));
ager@chromium.org04921a82011-06-27 13:21:41 +000010367 context->Global()->Set(v8_str("func2"), t2->GetFunction());
ricow@chromium.org2c99e282011-07-28 09:15:17 +000010368 // Default value of ReadOnly flag.
ager@chromium.org04921a82011-06-27 13:21:41 +000010369 CHECK(CompileRun(
10370 "(function() {"
10371 " descriptor = Object.getOwnPropertyDescriptor(func2, 'prototype');"
ricow@chromium.org2c99e282011-07-28 09:15:17 +000010372 " return (descriptor['writable'] == true);"
ager@chromium.org04921a82011-06-27 13:21:41 +000010373 "})()")->BooleanValue());
ricow@chromium.org2c99e282011-07-28 09:15:17 +000010374 CHECK_EQ(42, CompileRun("func2.prototype.x")->Int32Value());
ager@chromium.org04921a82011-06-27 13:21:41 +000010375}
10376
10377
ager@chromium.org5c838252010-02-19 08:53:10 +000010378THREADED_TEST(SetPrototypeThrows) {
ager@chromium.org5c838252010-02-19 08:53:10 +000010379 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010380 v8::Isolate* isolate = context->GetIsolate();
10381 v8::HandleScope handle_scope(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +000010382
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010383 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +000010384
10385 Local<v8::Object> o0 = t->GetFunction()->NewInstance();
10386 Local<v8::Object> o1 = t->GetFunction()->NewInstance();
10387
10388 CHECK(o0->SetPrototype(o1));
10389 // If setting the prototype leads to the cycle, SetPrototype should
10390 // return false and keep VM in sane state.
10391 v8::TryCatch try_catch;
10392 CHECK(!o1->SetPrototype(o0));
10393 CHECK(!try_catch.HasCaught());
machenbach@chromium.org528ce022013-09-23 14:09:36 +000010394 ASSERT(!CcTest::i_isolate()->has_pending_exception());
ager@chromium.org5c838252010-02-19 08:53:10 +000010395
10396 CHECK_EQ(42, CompileRun("function f() { return 42; }; f()")->Int32Value());
10397}
10398
10399
verwaest@chromium.org662436e2013-08-28 08:41:27 +000010400THREADED_TEST(FunctionRemovePrototype) {
10401 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010402 v8::Isolate* isolate = context->GetIsolate();
10403 v8::HandleScope handle_scope(isolate);
verwaest@chromium.org662436e2013-08-28 08:41:27 +000010404
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010405 Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
verwaest@chromium.org662436e2013-08-28 08:41:27 +000010406 t1->RemovePrototype();
10407 Local<v8::Function> fun = t1->GetFunction();
10408 context->Global()->Set(v8_str("fun"), fun);
10409 CHECK(!CompileRun("'prototype' in fun")->BooleanValue());
10410
10411 v8::TryCatch try_catch;
10412 CompileRun("new fun()");
10413 CHECK(try_catch.HasCaught());
10414
10415 try_catch.Reset();
10416 fun->NewInstance();
10417 CHECK(try_catch.HasCaught());
10418}
10419
10420
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010421THREADED_TEST(GetterSetterExceptions) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010422 LocalContext context;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000010423 v8::Isolate* isolate = context->GetIsolate();
10424 v8::HandleScope handle_scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010425 CompileRun(
10426 "function Foo() { };"
10427 "function Throw() { throw 5; };"
10428 "var x = { };"
10429 "x.__defineSetter__('set', Throw);"
10430 "x.__defineGetter__('get', Throw);");
10431 Local<v8::Object> x =
10432 Local<v8::Object>::Cast(context->Global()->Get(v8_str("x")));
10433 v8::TryCatch try_catch;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000010434 x->Set(v8_str("set"), v8::Integer::New(isolate, 8));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010435 x->Get(v8_str("get"));
ulan@chromium.org0f13e742014-01-03 15:51:11 +000010436 x->Set(v8_str("set"), v8::Integer::New(isolate, 8));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010437 x->Get(v8_str("get"));
ulan@chromium.org0f13e742014-01-03 15:51:11 +000010438 x->Set(v8_str("set"), v8::Integer::New(isolate, 8));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010439 x->Get(v8_str("get"));
ulan@chromium.org0f13e742014-01-03 15:51:11 +000010440 x->Set(v8_str("set"), v8::Integer::New(isolate, 8));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010441 x->Get(v8_str("get"));
10442}
10443
10444
10445THREADED_TEST(Constructor) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010446 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010447 v8::Isolate* isolate = context->GetIsolate();
10448 v8::HandleScope handle_scope(isolate);
10449 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010450 templ->SetClassName(v8_str("Fun"));
10451 Local<Function> cons = templ->GetFunction();
10452 context->Global()->Set(v8_str("Fun"), cons);
10453 Local<v8::Object> inst = cons->NewInstance();
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000010454 i::Handle<i::JSObject> obj(v8::Utils::OpenHandle(*inst));
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000010455 CHECK(obj->IsJSObject());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010456 Local<Value> value = CompileRun("(new Fun()).constructor === Fun");
10457 CHECK(value->BooleanValue());
10458}
10459
lrn@chromium.org1c092762011-05-09 09:42:16 +000010460
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010461static void ConstructorCallback(
10462 const v8::FunctionCallbackInfo<v8::Value>& args) {
lrn@chromium.org1c092762011-05-09 09:42:16 +000010463 ApiTestFuzzer::Fuzz();
10464 Local<Object> This;
10465
10466 if (args.IsConstructCall()) {
10467 Local<Object> Holder = args.Holder();
ulan@chromium.org0f13e742014-01-03 15:51:11 +000010468 This = Object::New(args.GetIsolate());
lrn@chromium.org1c092762011-05-09 09:42:16 +000010469 Local<Value> proto = Holder->GetPrototype();
10470 if (proto->IsObject()) {
10471 This->SetPrototype(proto);
10472 }
10473 } else {
10474 This = args.This();
10475 }
10476
10477 This->Set(v8_str("a"), args[0]);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010478 args.GetReturnValue().Set(This);
lrn@chromium.org1c092762011-05-09 09:42:16 +000010479}
10480
10481
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010482static void FakeConstructorCallback(
10483 const v8::FunctionCallbackInfo<v8::Value>& args) {
lrn@chromium.org1c092762011-05-09 09:42:16 +000010484 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010485 args.GetReturnValue().Set(args[0]);
lrn@chromium.org1c092762011-05-09 09:42:16 +000010486}
10487
10488
10489THREADED_TEST(ConstructorForObject) {
lrn@chromium.org1c092762011-05-09 09:42:16 +000010490 LocalContext context;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000010491 v8::Isolate* isolate = context->GetIsolate();
10492 v8::HandleScope handle_scope(isolate);
lrn@chromium.org1c092762011-05-09 09:42:16 +000010493
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000010494 { Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
lrn@chromium.org1c092762011-05-09 09:42:16 +000010495 instance_template->SetCallAsFunctionHandler(ConstructorCallback);
10496 Local<Object> instance = instance_template->NewInstance();
10497 context->Global()->Set(v8_str("obj"), instance);
10498 v8::TryCatch try_catch;
10499 Local<Value> value;
10500 CHECK(!try_catch.HasCaught());
10501
10502 // Call the Object's constructor with a 32-bit signed integer.
10503 value = CompileRun("(function() { var o = new obj(28); return o.a; })()");
10504 CHECK(!try_catch.HasCaught());
10505 CHECK(value->IsInt32());
10506 CHECK_EQ(28, value->Int32Value());
10507
10508 Local<Value> args1[] = { v8_num(28) };
10509 Local<Value> value_obj1 = instance->CallAsConstructor(1, args1);
10510 CHECK(value_obj1->IsObject());
10511 Local<Object> object1 = Local<Object>::Cast(value_obj1);
10512 value = object1->Get(v8_str("a"));
10513 CHECK(value->IsInt32());
10514 CHECK(!try_catch.HasCaught());
10515 CHECK_EQ(28, value->Int32Value());
10516
10517 // Call the Object's constructor with a String.
10518 value = CompileRun(
10519 "(function() { var o = new obj('tipli'); return o.a; })()");
10520 CHECK(!try_catch.HasCaught());
10521 CHECK(value->IsString());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000010522 String::Utf8Value string_value1(value->ToString());
lrn@chromium.org1c092762011-05-09 09:42:16 +000010523 CHECK_EQ("tipli", *string_value1);
10524
10525 Local<Value> args2[] = { v8_str("tipli") };
10526 Local<Value> value_obj2 = instance->CallAsConstructor(1, args2);
10527 CHECK(value_obj2->IsObject());
10528 Local<Object> object2 = Local<Object>::Cast(value_obj2);
10529 value = object2->Get(v8_str("a"));
10530 CHECK(!try_catch.HasCaught());
10531 CHECK(value->IsString());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000010532 String::Utf8Value string_value2(value->ToString());
lrn@chromium.org1c092762011-05-09 09:42:16 +000010533 CHECK_EQ("tipli", *string_value2);
10534
10535 // Call the Object's constructor with a Boolean.
10536 value = CompileRun("(function() { var o = new obj(true); return o.a; })()");
10537 CHECK(!try_catch.HasCaught());
10538 CHECK(value->IsBoolean());
10539 CHECK_EQ(true, value->BooleanValue());
10540
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000010541 Handle<Value> args3[] = { v8::True(isolate) };
lrn@chromium.org1c092762011-05-09 09:42:16 +000010542 Local<Value> value_obj3 = instance->CallAsConstructor(1, args3);
10543 CHECK(value_obj3->IsObject());
10544 Local<Object> object3 = Local<Object>::Cast(value_obj3);
10545 value = object3->Get(v8_str("a"));
10546 CHECK(!try_catch.HasCaught());
10547 CHECK(value->IsBoolean());
10548 CHECK_EQ(true, value->BooleanValue());
10549
10550 // Call the Object's constructor with undefined.
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000010551 Handle<Value> args4[] = { v8::Undefined(isolate) };
lrn@chromium.org1c092762011-05-09 09:42:16 +000010552 Local<Value> value_obj4 = instance->CallAsConstructor(1, args4);
10553 CHECK(value_obj4->IsObject());
10554 Local<Object> object4 = Local<Object>::Cast(value_obj4);
10555 value = object4->Get(v8_str("a"));
10556 CHECK(!try_catch.HasCaught());
10557 CHECK(value->IsUndefined());
10558
10559 // Call the Object's constructor with null.
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000010560 Handle<Value> args5[] = { v8::Null(isolate) };
lrn@chromium.org1c092762011-05-09 09:42:16 +000010561 Local<Value> value_obj5 = instance->CallAsConstructor(1, args5);
10562 CHECK(value_obj5->IsObject());
10563 Local<Object> object5 = Local<Object>::Cast(value_obj5);
10564 value = object5->Get(v8_str("a"));
10565 CHECK(!try_catch.HasCaught());
10566 CHECK(value->IsNull());
10567 }
10568
10569 // Check exception handling when there is no constructor set for the Object.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000010570 { Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
lrn@chromium.org1c092762011-05-09 09:42:16 +000010571 Local<Object> instance = instance_template->NewInstance();
10572 context->Global()->Set(v8_str("obj2"), instance);
10573 v8::TryCatch try_catch;
10574 Local<Value> value;
10575 CHECK(!try_catch.HasCaught());
10576
10577 value = CompileRun("new obj2(28)");
10578 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000010579 String::Utf8Value exception_value1(try_catch.Exception());
lrn@chromium.org1c092762011-05-09 09:42:16 +000010580 CHECK_EQ("TypeError: object is not a function", *exception_value1);
10581 try_catch.Reset();
10582
10583 Local<Value> args[] = { v8_num(29) };
10584 value = instance->CallAsConstructor(1, args);
10585 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000010586 String::Utf8Value exception_value2(try_catch.Exception());
lrn@chromium.org1c092762011-05-09 09:42:16 +000010587 CHECK_EQ("TypeError: #<Object> is not a function", *exception_value2);
10588 try_catch.Reset();
10589 }
10590
10591 // Check the case when constructor throws exception.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000010592 { Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
lrn@chromium.org1c092762011-05-09 09:42:16 +000010593 instance_template->SetCallAsFunctionHandler(ThrowValue);
10594 Local<Object> instance = instance_template->NewInstance();
10595 context->Global()->Set(v8_str("obj3"), instance);
10596 v8::TryCatch try_catch;
10597 Local<Value> value;
10598 CHECK(!try_catch.HasCaught());
10599
10600 value = CompileRun("new obj3(22)");
10601 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000010602 String::Utf8Value exception_value1(try_catch.Exception());
lrn@chromium.org1c092762011-05-09 09:42:16 +000010603 CHECK_EQ("22", *exception_value1);
10604 try_catch.Reset();
10605
10606 Local<Value> args[] = { v8_num(23) };
10607 value = instance->CallAsConstructor(1, args);
10608 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000010609 String::Utf8Value exception_value2(try_catch.Exception());
lrn@chromium.org1c092762011-05-09 09:42:16 +000010610 CHECK_EQ("23", *exception_value2);
10611 try_catch.Reset();
10612 }
10613
10614 // Check whether constructor returns with an object or non-object.
10615 { Local<FunctionTemplate> function_template =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010616 FunctionTemplate::New(isolate, FakeConstructorCallback);
lrn@chromium.org1c092762011-05-09 09:42:16 +000010617 Local<Function> function = function_template->GetFunction();
10618 Local<Object> instance1 = function;
10619 context->Global()->Set(v8_str("obj4"), instance1);
10620 v8::TryCatch try_catch;
10621 Local<Value> value;
10622 CHECK(!try_catch.HasCaught());
10623
10624 CHECK(instance1->IsObject());
10625 CHECK(instance1->IsFunction());
10626
10627 value = CompileRun("new obj4(28)");
10628 CHECK(!try_catch.HasCaught());
10629 CHECK(value->IsObject());
10630
10631 Local<Value> args1[] = { v8_num(28) };
10632 value = instance1->CallAsConstructor(1, args1);
10633 CHECK(!try_catch.HasCaught());
10634 CHECK(value->IsObject());
10635
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000010636 Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
lrn@chromium.org1c092762011-05-09 09:42:16 +000010637 instance_template->SetCallAsFunctionHandler(FakeConstructorCallback);
10638 Local<Object> instance2 = instance_template->NewInstance();
10639 context->Global()->Set(v8_str("obj5"), instance2);
10640 CHECK(!try_catch.HasCaught());
10641
10642 CHECK(instance2->IsObject());
10643 CHECK(!instance2->IsFunction());
10644
10645 value = CompileRun("new obj5(28)");
10646 CHECK(!try_catch.HasCaught());
10647 CHECK(!value->IsObject());
10648
10649 Local<Value> args2[] = { v8_num(28) };
10650 value = instance2->CallAsConstructor(1, args2);
10651 CHECK(!try_catch.HasCaught());
10652 CHECK(!value->IsObject());
10653 }
10654}
10655
10656
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010657THREADED_TEST(FunctionDescriptorException) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010658 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010659 v8::Isolate* isolate = context->GetIsolate();
10660 v8::HandleScope handle_scope(isolate);
10661 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010662 templ->SetClassName(v8_str("Fun"));
10663 Local<Function> cons = templ->GetFunction();
10664 context->Global()->Set(v8_str("Fun"), cons);
10665 Local<Value> value = CompileRun(
10666 "function test() {"
10667 " try {"
10668 " (new Fun()).blah()"
10669 " } catch (e) {"
10670 " var str = String(e);"
10671 " if (str.indexOf('TypeError') == -1) return 1;"
10672 " if (str.indexOf('[object Fun]') != -1) return 2;"
whesse@chromium.org7a392b32011-01-31 11:30:36 +000010673 " if (str.indexOf('#<Fun>') == -1) return 3;"
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010674 " return 0;"
10675 " }"
10676 " return 4;"
10677 "}"
10678 "test();");
10679 CHECK_EQ(0, value->Int32Value());
10680}
10681
10682
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010683THREADED_TEST(EvalAliasedDynamic) {
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010684 LocalContext current;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000010685 v8::HandleScope scope(current->GetIsolate());
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010686
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010687 // Tests where aliased eval can only be resolved dynamically.
10688 Local<Script> script =
10689 Script::Compile(v8_str("function f(x) { "
10690 " var foo = 2;"
10691 " with (x) { return eval('foo'); }"
10692 "}"
10693 "foo = 0;"
10694 "result1 = f(new Object());"
ager@chromium.orge2902be2009-06-08 12:21:35 +000010695 "result2 = f(this);"
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010696 "var x = new Object();"
10697 "x.eval = function(x) { return 1; };"
10698 "result3 = f(x);"));
10699 script->Run();
10700 CHECK_EQ(2, current->Global()->Get(v8_str("result1"))->Int32Value());
10701 CHECK_EQ(0, current->Global()->Get(v8_str("result2"))->Int32Value());
10702 CHECK_EQ(1, current->Global()->Get(v8_str("result3"))->Int32Value());
10703
10704 v8::TryCatch try_catch;
10705 script =
10706 Script::Compile(v8_str("function f(x) { "
10707 " var bar = 2;"
10708 " with (x) { return eval('bar'); }"
10709 "}"
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000010710 "result4 = f(this)"));
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010711 script->Run();
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000010712 CHECK(!try_catch.HasCaught());
10713 CHECK_EQ(2, current->Global()->Get(v8_str("result4"))->Int32Value());
10714
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010715 try_catch.Reset();
10716}
10717
10718
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010719THREADED_TEST(CrossEval) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000010720 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010721 LocalContext other;
10722 LocalContext current;
10723
10724 Local<String> token = v8_str("<security token>");
10725 other->SetSecurityToken(token);
10726 current->SetSecurityToken(token);
10727
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000010728 // Set up reference from current to other.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010729 current->Global()->Set(v8_str("other"), other->Global());
10730
10731 // Check that new variables are introduced in other context.
10732 Local<Script> script =
10733 Script::Compile(v8_str("other.eval('var foo = 1234')"));
10734 script->Run();
10735 Local<Value> foo = other->Global()->Get(v8_str("foo"));
10736 CHECK_EQ(1234, foo->Int32Value());
10737 CHECK(!current->Global()->Has(v8_str("foo")));
10738
10739 // Check that writing to non-existing properties introduces them in
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010740 // the other context.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010741 script =
10742 Script::Compile(v8_str("other.eval('na = 1234')"));
10743 script->Run();
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010744 CHECK_EQ(1234, other->Global()->Get(v8_str("na"))->Int32Value());
10745 CHECK(!current->Global()->Has(v8_str("na")));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010746
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010747 // Check that global variables in current context are not visible in other
10748 // context.
10749 v8::TryCatch try_catch;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010750 script =
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010751 Script::Compile(v8_str("var bar = 42; other.eval('bar');"));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010752 Local<Value> result = script->Run();
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010753 CHECK(try_catch.HasCaught());
10754 try_catch.Reset();
10755
10756 // Check that local variables in current context are not visible in other
10757 // context.
10758 script =
10759 Script::Compile(v8_str("(function() { "
10760 " var baz = 87;"
10761 " return other.eval('baz');"
10762 "})();"));
10763 result = script->Run();
10764 CHECK(try_catch.HasCaught());
10765 try_catch.Reset();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010766
10767 // Check that global variables in the other environment are visible
10768 // when evaluting code.
10769 other->Global()->Set(v8_str("bis"), v8_num(1234));
10770 script = Script::Compile(v8_str("other.eval('bis')"));
10771 CHECK_EQ(1234, script->Run()->Int32Value());
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010772 CHECK(!try_catch.HasCaught());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010773
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010774 // Check that the 'this' pointer points to the global object evaluating
10775 // code.
10776 other->Global()->Set(v8_str("t"), other->Global());
10777 script = Script::Compile(v8_str("other.eval('this == t')"));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010778 result = script->Run();
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010779 CHECK(result->IsTrue());
10780 CHECK(!try_catch.HasCaught());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010781
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010782 // Check that variables introduced in with-statement are not visible in
10783 // other context.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010784 script =
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010785 Script::Compile(v8_str("with({x:2}){other.eval('x')}"));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010786 result = script->Run();
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010787 CHECK(try_catch.HasCaught());
10788 try_catch.Reset();
ager@chromium.org3bf7b912008-11-17 09:09:45 +000010789
10790 // Check that you cannot use 'eval.call' with another object than the
10791 // current global object.
ager@chromium.org3bf7b912008-11-17 09:09:45 +000010792 script =
10793 Script::Compile(v8_str("other.y = 1; eval.call(other, 'y')"));
10794 result = script->Run();
10795 CHECK(try_catch.HasCaught());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010796}
10797
10798
ager@chromium.orge2902be2009-06-08 12:21:35 +000010799// Test that calling eval in a context which has been detached from
10800// its global throws an exception. This behavior is consistent with
10801// other JavaScript implementations.
10802THREADED_TEST(EvalInDetachedGlobal) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000010803 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000010804 v8::HandleScope scope(isolate);
ager@chromium.orge2902be2009-06-08 12:21:35 +000010805
ulan@chromium.org57ff8812013-05-10 08:16:55 +000010806 v8::Local<Context> context0 = Context::New(isolate);
10807 v8::Local<Context> context1 = Context::New(isolate);
ager@chromium.orge2902be2009-06-08 12:21:35 +000010808
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000010809 // Set up function in context0 that uses eval from context0.
ager@chromium.orge2902be2009-06-08 12:21:35 +000010810 context0->Enter();
10811 v8::Handle<v8::Value> fun =
10812 CompileRun("var x = 42;"
10813 "(function() {"
10814 " var e = eval;"
10815 " return function(s) { return e(s); }"
10816 "})()");
10817 context0->Exit();
10818
10819 // Put the function into context1 and call it before and after
10820 // detaching the global. Before detaching, the call succeeds and
10821 // after detaching and exception is thrown.
10822 context1->Enter();
10823 context1->Global()->Set(v8_str("fun"), fun);
10824 v8::Handle<v8::Value> x_value = CompileRun("fun('x')");
10825 CHECK_EQ(42, x_value->Int32Value());
10826 context0->DetachGlobal();
10827 v8::TryCatch catcher;
10828 x_value = CompileRun("fun('x')");
10829 CHECK(x_value.IsEmpty());
10830 CHECK(catcher.HasCaught());
10831 context1->Exit();
ager@chromium.orge2902be2009-06-08 12:21:35 +000010832}
10833
10834
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010835THREADED_TEST(CrossLazyLoad) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000010836 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010837 LocalContext other;
10838 LocalContext current;
10839
10840 Local<String> token = v8_str("<security token>");
10841 other->SetSecurityToken(token);
10842 current->SetSecurityToken(token);
10843
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000010844 // Set up reference from current to other.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010845 current->Global()->Set(v8_str("other"), other->Global());
10846
10847 // Trigger lazy loading in other context.
10848 Local<Script> script =
10849 Script::Compile(v8_str("other.eval('new Date(42)')"));
10850 Local<Value> value = script->Run();
10851 CHECK_EQ(42.0, value->NumberValue());
10852}
10853
10854
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010855static void call_as_function(const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010856 ApiTestFuzzer::Fuzz();
sgjesse@chromium.org05521fc2009-05-21 07:37:44 +000010857 if (args.IsConstructCall()) {
10858 if (args[0]->IsInt32()) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010859 args.GetReturnValue().Set(v8_num(-args[0]->Int32Value()));
10860 return;
sgjesse@chromium.org05521fc2009-05-21 07:37:44 +000010861 }
10862 }
10863
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010864 args.GetReturnValue().Set(args[0]);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010865}
10866
10867
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +000010868static void ReturnThis(const v8::FunctionCallbackInfo<v8::Value>& args) {
10869 args.GetReturnValue().Set(args.This());
10870}
10871
10872
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010873// Test that a call handler can be set for objects which will allow
10874// non-function objects created through the API to be called as
10875// functions.
10876THREADED_TEST(CallAsFunction) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010877 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010878 v8::Isolate* isolate = context->GetIsolate();
10879 v8::HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010880
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010881 { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
lrn@chromium.org1c092762011-05-09 09:42:16 +000010882 Local<ObjectTemplate> instance_template = t->InstanceTemplate();
10883 instance_template->SetCallAsFunctionHandler(call_as_function);
10884 Local<v8::Object> instance = t->GetFunction()->NewInstance();
10885 context->Global()->Set(v8_str("obj"), instance);
10886 v8::TryCatch try_catch;
10887 Local<Value> value;
10888 CHECK(!try_catch.HasCaught());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010889
lrn@chromium.org1c092762011-05-09 09:42:16 +000010890 value = CompileRun("obj(42)");
10891 CHECK(!try_catch.HasCaught());
10892 CHECK_EQ(42, value->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010893
lrn@chromium.org1c092762011-05-09 09:42:16 +000010894 value = CompileRun("(function(o){return o(49)})(obj)");
10895 CHECK(!try_catch.HasCaught());
10896 CHECK_EQ(49, value->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010897
lrn@chromium.org1c092762011-05-09 09:42:16 +000010898 // test special case of call as function
10899 value = CompileRun("[obj]['0'](45)");
10900 CHECK(!try_catch.HasCaught());
10901 CHECK_EQ(45, value->Int32Value());
ager@chromium.org9258b6b2008-09-11 09:11:10 +000010902
lrn@chromium.org1c092762011-05-09 09:42:16 +000010903 value = CompileRun("obj.call = Function.prototype.call;"
10904 "obj.call(null, 87)");
10905 CHECK(!try_catch.HasCaught());
10906 CHECK_EQ(87, value->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010907
lrn@chromium.org1c092762011-05-09 09:42:16 +000010908 // Regression tests for bug #1116356: Calling call through call/apply
10909 // must work for non-function receivers.
10910 const char* apply_99 = "Function.prototype.call.apply(obj, [this, 99])";
10911 value = CompileRun(apply_99);
10912 CHECK(!try_catch.HasCaught());
10913 CHECK_EQ(99, value->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010914
lrn@chromium.org1c092762011-05-09 09:42:16 +000010915 const char* call_17 = "Function.prototype.call.call(obj, this, 17)";
10916 value = CompileRun(call_17);
10917 CHECK(!try_catch.HasCaught());
10918 CHECK_EQ(17, value->Int32Value());
ager@chromium.org9085a012009-05-11 19:22:57 +000010919
lrn@chromium.org1c092762011-05-09 09:42:16 +000010920 // Check that the call-as-function handler can be called through
10921 // new.
10922 value = CompileRun("new obj(43)");
10923 CHECK(!try_catch.HasCaught());
10924 CHECK_EQ(-43, value->Int32Value());
10925
10926 // Check that the call-as-function handler can be called through
10927 // the API.
10928 v8::Handle<Value> args[] = { v8_num(28) };
10929 value = instance->CallAsFunction(instance, 1, args);
10930 CHECK(!try_catch.HasCaught());
10931 CHECK_EQ(28, value->Int32Value());
10932 }
10933
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010934 { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000010935 Local<ObjectTemplate> instance_template(t->InstanceTemplate());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000010936 USE(instance_template);
lrn@chromium.org1c092762011-05-09 09:42:16 +000010937 Local<v8::Object> instance = t->GetFunction()->NewInstance();
10938 context->Global()->Set(v8_str("obj2"), instance);
10939 v8::TryCatch try_catch;
10940 Local<Value> value;
10941 CHECK(!try_catch.HasCaught());
10942
10943 // Call an object without call-as-function handler through the JS
10944 value = CompileRun("obj2(28)");
10945 CHECK(value.IsEmpty());
10946 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000010947 String::Utf8Value exception_value1(try_catch.Exception());
lrn@chromium.org1c092762011-05-09 09:42:16 +000010948 CHECK_EQ("TypeError: Property 'obj2' of object #<Object> is not a function",
10949 *exception_value1);
10950 try_catch.Reset();
10951
10952 // Call an object without call-as-function handler through the API
10953 value = CompileRun("obj2(28)");
10954 v8::Handle<Value> args[] = { v8_num(28) };
10955 value = instance->CallAsFunction(instance, 1, args);
10956 CHECK(value.IsEmpty());
10957 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000010958 String::Utf8Value exception_value2(try_catch.Exception());
lrn@chromium.org1c092762011-05-09 09:42:16 +000010959 CHECK_EQ("TypeError: [object Object] is not a function", *exception_value2);
10960 try_catch.Reset();
10961 }
10962
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010963 { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
lrn@chromium.org1c092762011-05-09 09:42:16 +000010964 Local<ObjectTemplate> instance_template = t->InstanceTemplate();
10965 instance_template->SetCallAsFunctionHandler(ThrowValue);
10966 Local<v8::Object> instance = t->GetFunction()->NewInstance();
10967 context->Global()->Set(v8_str("obj3"), instance);
10968 v8::TryCatch try_catch;
10969 Local<Value> value;
10970 CHECK(!try_catch.HasCaught());
10971
10972 // Catch the exception which is thrown by call-as-function handler
10973 value = CompileRun("obj3(22)");
10974 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000010975 String::Utf8Value exception_value1(try_catch.Exception());
lrn@chromium.org1c092762011-05-09 09:42:16 +000010976 CHECK_EQ("22", *exception_value1);
10977 try_catch.Reset();
10978
10979 v8::Handle<Value> args[] = { v8_num(23) };
10980 value = instance->CallAsFunction(instance, 1, args);
10981 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000010982 String::Utf8Value exception_value2(try_catch.Exception());
lrn@chromium.org1c092762011-05-09 09:42:16 +000010983 CHECK_EQ("23", *exception_value2);
10984 try_catch.Reset();
10985 }
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +000010986
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010987 { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +000010988 Local<ObjectTemplate> instance_template = t->InstanceTemplate();
10989 instance_template->SetCallAsFunctionHandler(ReturnThis);
10990 Local<v8::Object> instance = t->GetFunction()->NewInstance();
10991
10992 Local<v8::Value> a1 =
10993 instance->CallAsFunction(v8::Undefined(isolate), 0, NULL);
10994 CHECK(a1->StrictEquals(instance));
10995 Local<v8::Value> a2 =
10996 instance->CallAsFunction(v8::Null(isolate), 0, NULL);
10997 CHECK(a2->StrictEquals(instance));
10998 Local<v8::Value> a3 =
10999 instance->CallAsFunction(v8_num(42), 0, NULL);
11000 CHECK(a3->StrictEquals(instance));
11001 Local<v8::Value> a4 =
11002 instance->CallAsFunction(v8_str("hello"), 0, NULL);
11003 CHECK(a4->StrictEquals(instance));
11004 Local<v8::Value> a5 =
11005 instance->CallAsFunction(v8::True(isolate), 0, NULL);
11006 CHECK(a5->StrictEquals(instance));
11007 }
11008
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000011009 { CompileRun(
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +000011010 "function ReturnThisSloppy() {"
11011 " return this;"
11012 "}"
11013 "function ReturnThisStrict() {"
11014 " 'use strict';"
11015 " return this;"
11016 "}");
11017 Local<Function> ReturnThisSloppy =
11018 Local<Function>::Cast(
11019 context->Global()->Get(v8_str("ReturnThisSloppy")));
11020 Local<Function> ReturnThisStrict =
11021 Local<Function>::Cast(
11022 context->Global()->Get(v8_str("ReturnThisStrict")));
11023
11024 Local<v8::Value> a1 =
11025 ReturnThisSloppy->CallAsFunction(v8::Undefined(isolate), 0, NULL);
11026 CHECK(a1->StrictEquals(context->Global()));
11027 Local<v8::Value> a2 =
11028 ReturnThisSloppy->CallAsFunction(v8::Null(isolate), 0, NULL);
11029 CHECK(a2->StrictEquals(context->Global()));
11030 Local<v8::Value> a3 =
11031 ReturnThisSloppy->CallAsFunction(v8_num(42), 0, NULL);
11032 CHECK(a3->IsNumberObject());
11033 CHECK_EQ(42.0, a3.As<v8::NumberObject>()->ValueOf());
11034 Local<v8::Value> a4 =
11035 ReturnThisSloppy->CallAsFunction(v8_str("hello"), 0, NULL);
11036 CHECK(a4->IsStringObject());
11037 CHECK(a4.As<v8::StringObject>()->ValueOf()->StrictEquals(v8_str("hello")));
11038 Local<v8::Value> a5 =
11039 ReturnThisSloppy->CallAsFunction(v8::True(isolate), 0, NULL);
11040 CHECK(a5->IsBooleanObject());
11041 CHECK(a5.As<v8::BooleanObject>()->ValueOf());
11042
11043 Local<v8::Value> a6 =
11044 ReturnThisStrict->CallAsFunction(v8::Undefined(isolate), 0, NULL);
11045 CHECK(a6->IsUndefined());
11046 Local<v8::Value> a7 =
11047 ReturnThisStrict->CallAsFunction(v8::Null(isolate), 0, NULL);
11048 CHECK(a7->IsNull());
11049 Local<v8::Value> a8 =
11050 ReturnThisStrict->CallAsFunction(v8_num(42), 0, NULL);
11051 CHECK(a8->StrictEquals(v8_num(42)));
11052 Local<v8::Value> a9 =
11053 ReturnThisStrict->CallAsFunction(v8_str("hello"), 0, NULL);
11054 CHECK(a9->StrictEquals(v8_str("hello")));
11055 Local<v8::Value> a10 =
11056 ReturnThisStrict->CallAsFunction(v8::True(isolate), 0, NULL);
11057 CHECK(a10->StrictEquals(v8::True(isolate)));
11058 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011059}
11060
11061
karlklose@chromium.org83a47282011-05-11 11:54:09 +000011062// Check whether a non-function object is callable.
11063THREADED_TEST(CallableObject) {
karlklose@chromium.org83a47282011-05-11 11:54:09 +000011064 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000011065 v8::Isolate* isolate = context->GetIsolate();
11066 v8::HandleScope scope(isolate);
karlklose@chromium.org83a47282011-05-11 11:54:09 +000011067
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011068 { Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
karlklose@chromium.org83a47282011-05-11 11:54:09 +000011069 instance_template->SetCallAsFunctionHandler(call_as_function);
11070 Local<Object> instance = instance_template->NewInstance();
11071 v8::TryCatch try_catch;
11072
11073 CHECK(instance->IsCallable());
11074 CHECK(!try_catch.HasCaught());
11075 }
11076
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011077 { Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
karlklose@chromium.org83a47282011-05-11 11:54:09 +000011078 Local<Object> instance = instance_template->NewInstance();
11079 v8::TryCatch try_catch;
11080
11081 CHECK(!instance->IsCallable());
11082 CHECK(!try_catch.HasCaught());
11083 }
11084
11085 { Local<FunctionTemplate> function_template =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000011086 FunctionTemplate::New(isolate, call_as_function);
karlklose@chromium.org83a47282011-05-11 11:54:09 +000011087 Local<Function> function = function_template->GetFunction();
11088 Local<Object> instance = function;
11089 v8::TryCatch try_catch;
11090
11091 CHECK(instance->IsCallable());
11092 CHECK(!try_catch.HasCaught());
11093 }
11094
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000011095 { Local<FunctionTemplate> function_template = FunctionTemplate::New(isolate);
karlklose@chromium.org83a47282011-05-11 11:54:09 +000011096 Local<Function> function = function_template->GetFunction();
11097 Local<Object> instance = function;
11098 v8::TryCatch try_catch;
11099
11100 CHECK(instance->IsCallable());
11101 CHECK(!try_catch.HasCaught());
11102 }
11103}
11104
11105
machenbach@chromium.org4610c282014-01-09 10:39:51 +000011106static int Recurse(v8::Isolate* isolate, int depth, int iterations) {
11107 v8::HandleScope scope(isolate);
11108 if (depth == 0) return v8::HandleScope::NumberOfHandles(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011109 for (int i = 0; i < iterations; i++) {
machenbach@chromium.org4610c282014-01-09 10:39:51 +000011110 Local<v8::Number> n(v8::Integer::New(isolate, 42));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011111 }
machenbach@chromium.org4610c282014-01-09 10:39:51 +000011112 return Recurse(isolate, depth - 1, iterations);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011113}
11114
11115
11116THREADED_TEST(HandleIteration) {
11117 static const int kIterations = 500;
11118 static const int kNesting = 200;
machenbach@chromium.org4610c282014-01-09 10:39:51 +000011119 LocalContext context;
11120 v8::Isolate* isolate = context->GetIsolate();
11121 v8::HandleScope scope0(isolate);
11122 CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011123 {
machenbach@chromium.org4610c282014-01-09 10:39:51 +000011124 v8::HandleScope scope1(isolate);
11125 CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011126 for (int i = 0; i < kIterations; i++) {
ulan@chromium.org0f13e742014-01-03 15:51:11 +000011127 Local<v8::Number> n(v8::Integer::New(CcTest::isolate(), 42));
machenbach@chromium.org4610c282014-01-09 10:39:51 +000011128 CHECK_EQ(i + 1, v8::HandleScope::NumberOfHandles(isolate));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011129 }
11130
machenbach@chromium.org4610c282014-01-09 10:39:51 +000011131 CHECK_EQ(kIterations, v8::HandleScope::NumberOfHandles(isolate));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011132 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000011133 v8::HandleScope scope2(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011134 for (int j = 0; j < kIterations; j++) {
ulan@chromium.org0f13e742014-01-03 15:51:11 +000011135 Local<v8::Number> n(v8::Integer::New(CcTest::isolate(), 42));
machenbach@chromium.org4610c282014-01-09 10:39:51 +000011136 CHECK_EQ(j + 1 + kIterations,
11137 v8::HandleScope::NumberOfHandles(isolate));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011138 }
11139 }
machenbach@chromium.org4610c282014-01-09 10:39:51 +000011140 CHECK_EQ(kIterations, v8::HandleScope::NumberOfHandles(isolate));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011141 }
machenbach@chromium.org4610c282014-01-09 10:39:51 +000011142 CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
11143 CHECK_EQ(kNesting * kIterations, Recurse(isolate, kNesting, kIterations));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011144}
11145
11146
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011147static void InterceptorHasOwnPropertyGetter(
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011148 Local<String> name,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011149 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011150 ApiTestFuzzer::Fuzz();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011151}
11152
11153
11154THREADED_TEST(InterceptorHasOwnProperty) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011155 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000011156 v8::Isolate* isolate = context->GetIsolate();
11157 v8::HandleScope scope(isolate);
11158 Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011159 Local<v8::ObjectTemplate> instance_templ = fun_templ->InstanceTemplate();
11160 instance_templ->SetNamedPropertyHandler(InterceptorHasOwnPropertyGetter);
11161 Local<Function> function = fun_templ->GetFunction();
11162 context->Global()->Set(v8_str("constructor"), function);
11163 v8::Handle<Value> value = CompileRun(
11164 "var o = new constructor();"
11165 "o.hasOwnProperty('ostehaps');");
11166 CHECK_EQ(false, value->BooleanValue());
11167 value = CompileRun(
11168 "o.ostehaps = 42;"
11169 "o.hasOwnProperty('ostehaps');");
11170 CHECK_EQ(true, value->BooleanValue());
11171 value = CompileRun(
11172 "var p = new constructor();"
11173 "p.hasOwnProperty('ostehaps');");
11174 CHECK_EQ(false, value->BooleanValue());
11175}
11176
11177
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011178static void InterceptorHasOwnPropertyGetterGC(
ager@chromium.org9085a012009-05-11 19:22:57 +000011179 Local<String> name,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011180 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.org9085a012009-05-11 19:22:57 +000011181 ApiTestFuzzer::Fuzz();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000011182 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org9085a012009-05-11 19:22:57 +000011183}
11184
11185
11186THREADED_TEST(InterceptorHasOwnPropertyCausingGC) {
ager@chromium.org9085a012009-05-11 19:22:57 +000011187 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000011188 v8::Isolate* isolate = context->GetIsolate();
11189 v8::HandleScope scope(isolate);
11190 Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(isolate);
ager@chromium.org9085a012009-05-11 19:22:57 +000011191 Local<v8::ObjectTemplate> instance_templ = fun_templ->InstanceTemplate();
11192 instance_templ->SetNamedPropertyHandler(InterceptorHasOwnPropertyGetterGC);
11193 Local<Function> function = fun_templ->GetFunction();
11194 context->Global()->Set(v8_str("constructor"), function);
11195 // Let's first make some stuff so we can be sure to get a good GC.
11196 CompileRun(
11197 "function makestr(size) {"
11198 " switch (size) {"
11199 " case 1: return 'f';"
11200 " case 2: return 'fo';"
11201 " case 3: return 'foo';"
11202 " }"
11203 " return makestr(size >> 1) + makestr((size + 1) >> 1);"
11204 "}"
11205 "var x = makestr(12345);"
11206 "x = makestr(31415);"
11207 "x = makestr(23456);");
11208 v8::Handle<Value> value = CompileRun(
11209 "var o = new constructor();"
11210 "o.__proto__ = new String(x);"
11211 "o.hasOwnProperty('ostehaps');");
11212 CHECK_EQ(false, value->BooleanValue());
11213}
11214
11215
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011216typedef void (*NamedPropertyGetter)(
11217 Local<String> property,
11218 const v8::PropertyCallbackInfo<v8::Value>& info);
ager@chromium.orge2902be2009-06-08 12:21:35 +000011219
11220
11221static void CheckInterceptorLoadIC(NamedPropertyGetter getter,
11222 const char* source,
11223 int expected) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011224 v8::Isolate* isolate = CcTest::isolate();
11225 v8::HandleScope scope(isolate);
11226 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
vegorov@chromium.org21b5e952010-11-23 10:24:40 +000011227 templ->SetNamedPropertyHandler(getter, 0, 0, 0, 0, v8_str("data"));
ager@chromium.orge2902be2009-06-08 12:21:35 +000011228 LocalContext context;
11229 context->Global()->Set(v8_str("o"), templ->NewInstance());
11230 v8::Handle<Value> value = CompileRun(source);
11231 CHECK_EQ(expected, value->Int32Value());
11232}
11233
11234
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011235static void InterceptorLoadICGetter(
11236 Local<String> name,
11237 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011238 ApiTestFuzzer::Fuzz();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000011239 v8::Isolate* isolate = CcTest::isolate();
jkummerow@chromium.org28faa982012-04-13 09:58:30 +000011240 CHECK_EQ(isolate, info.GetIsolate());
vegorov@chromium.org21b5e952010-11-23 10:24:40 +000011241 CHECK_EQ(v8_str("data"), info.Data());
11242 CHECK_EQ(v8_str("x"), name);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000011243 info.GetReturnValue().Set(v8::Integer::New(isolate, 42));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011244}
11245
11246
11247// This test should hit the load IC for the interceptor case.
11248THREADED_TEST(InterceptorLoadIC) {
ager@chromium.orge2902be2009-06-08 12:21:35 +000011249 CheckInterceptorLoadIC(InterceptorLoadICGetter,
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011250 "var result = 0;"
11251 "for (var i = 0; i < 1000; i++) {"
11252 " result = o.x;"
ager@chromium.orge2902be2009-06-08 12:21:35 +000011253 "}",
11254 42);
11255}
11256
11257
11258// Below go several tests which verify that JITing for various
11259// configurations of interceptor and explicit fields works fine
11260// (those cases are special cased to get better performance).
11261
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011262static void InterceptorLoadXICGetter(
11263 Local<String> name,
11264 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.orge2902be2009-06-08 12:21:35 +000011265 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011266 info.GetReturnValue().Set(
11267 v8_str("x")->Equals(name) ?
ulan@chromium.org0f13e742014-01-03 15:51:11 +000011268 v8::Handle<v8::Value>(v8::Integer::New(info.GetIsolate(), 42)) :
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011269 v8::Handle<v8::Value>());
ager@chromium.orge2902be2009-06-08 12:21:35 +000011270}
11271
11272
11273THREADED_TEST(InterceptorLoadICWithFieldOnHolder) {
11274 CheckInterceptorLoadIC(InterceptorLoadXICGetter,
11275 "var result = 0;"
11276 "o.y = 239;"
11277 "for (var i = 0; i < 1000; i++) {"
11278 " result = o.y;"
11279 "}",
11280 239);
11281}
11282
11283
11284THREADED_TEST(InterceptorLoadICWithSubstitutedProto) {
11285 CheckInterceptorLoadIC(InterceptorLoadXICGetter,
11286 "var result = 0;"
11287 "o.__proto__ = { 'y': 239 };"
11288 "for (var i = 0; i < 1000; i++) {"
11289 " result = o.y + o.x;"
11290 "}",
11291 239 + 42);
11292}
11293
11294
11295THREADED_TEST(InterceptorLoadICWithPropertyOnProto) {
11296 CheckInterceptorLoadIC(InterceptorLoadXICGetter,
11297 "var result = 0;"
11298 "o.__proto__.y = 239;"
11299 "for (var i = 0; i < 1000; i++) {"
11300 " result = o.y + o.x;"
11301 "}",
11302 239 + 42);
11303}
11304
11305
11306THREADED_TEST(InterceptorLoadICUndefined) {
11307 CheckInterceptorLoadIC(InterceptorLoadXICGetter,
11308 "var result = 0;"
11309 "for (var i = 0; i < 1000; i++) {"
11310 " result = (o.y == undefined) ? 239 : 42;"
11311 "}",
11312 239);
11313}
11314
11315
11316THREADED_TEST(InterceptorLoadICWithOverride) {
11317 CheckInterceptorLoadIC(InterceptorLoadXICGetter,
11318 "fst = new Object(); fst.__proto__ = o;"
11319 "snd = new Object(); snd.__proto__ = fst;"
11320 "var result1 = 0;"
11321 "for (var i = 0; i < 1000; i++) {"
11322 " result1 = snd.x;"
11323 "}"
11324 "fst.x = 239;"
11325 "var result = 0;"
11326 "for (var i = 0; i < 1000; i++) {"
11327 " result = snd.x;"
11328 "}"
11329 "result + result1",
11330 239 + 42);
11331}
11332
11333
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011334// Test the case when we stored field into
11335// a stub, but interceptor produced value on its own.
11336THREADED_TEST(InterceptorLoadICFieldNotNeeded) {
11337 CheckInterceptorLoadIC(InterceptorLoadXICGetter,
11338 "proto = new Object();"
11339 "o.__proto__ = proto;"
11340 "proto.x = 239;"
11341 "for (var i = 0; i < 1000; i++) {"
11342 " o.x;"
11343 // Now it should be ICed and keep a reference to x defined on proto
11344 "}"
11345 "var result = 0;"
11346 "for (var i = 0; i < 1000; i++) {"
11347 " result += o.x;"
11348 "}"
11349 "result;",
11350 42 * 1000);
11351}
11352
11353
11354// Test the case when we stored field into
11355// a stub, but it got invalidated later on.
11356THREADED_TEST(InterceptorLoadICInvalidatedField) {
11357 CheckInterceptorLoadIC(InterceptorLoadXICGetter,
11358 "proto1 = new Object();"
11359 "proto2 = new Object();"
11360 "o.__proto__ = proto1;"
11361 "proto1.__proto__ = proto2;"
11362 "proto2.y = 239;"
11363 "for (var i = 0; i < 1000; i++) {"
11364 " o.y;"
11365 // Now it should be ICed and keep a reference to y defined on proto2
11366 "}"
11367 "proto1.y = 42;"
11368 "var result = 0;"
11369 "for (var i = 0; i < 1000; i++) {"
11370 " result += o.y;"
11371 "}"
11372 "result;",
11373 42 * 1000);
11374}
11375
11376
ager@chromium.orgb26c50a2010-03-26 09:27:16 +000011377static int interceptor_load_not_handled_calls = 0;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011378static void InterceptorLoadNotHandled(
11379 Local<String> name,
11380 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.orgb26c50a2010-03-26 09:27:16 +000011381 ++interceptor_load_not_handled_calls;
ager@chromium.orgb26c50a2010-03-26 09:27:16 +000011382}
11383
11384
11385// Test how post-interceptor lookups are done in the non-cacheable
11386// case: the interceptor should not be invoked during this lookup.
11387THREADED_TEST(InterceptorLoadICPostInterceptor) {
11388 interceptor_load_not_handled_calls = 0;
11389 CheckInterceptorLoadIC(InterceptorLoadNotHandled,
11390 "receiver = new Object();"
11391 "receiver.__proto__ = o;"
11392 "proto = new Object();"
11393 "/* Make proto a slow-case object. */"
11394 "for (var i = 0; i < 1000; i++) {"
11395 " proto[\"xxxxxxxx\" + i] = [];"
11396 "}"
11397 "proto.x = 17;"
11398 "o.__proto__ = proto;"
11399 "var result = 0;"
11400 "for (var i = 0; i < 1000; i++) {"
11401 " result += receiver.x;"
11402 "}"
11403 "result;",
11404 17 * 1000);
11405 CHECK_EQ(1000, interceptor_load_not_handled_calls);
11406}
11407
11408
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011409// Test the case when we stored field into
11410// a stub, but it got invalidated later on due to override on
11411// global object which is between interceptor and fields' holders.
11412THREADED_TEST(InterceptorLoadICInvalidatedFieldViaGlobal) {
11413 CheckInterceptorLoadIC(InterceptorLoadXICGetter,
11414 "o.__proto__ = this;" // set a global to be a proto of o.
11415 "this.__proto__.y = 239;"
11416 "for (var i = 0; i < 10; i++) {"
11417 " if (o.y != 239) throw 'oops: ' + o.y;"
11418 // Now it should be ICed and keep a reference to y defined on field_holder.
11419 "}"
11420 "this.y = 42;" // Assign on a global.
11421 "var result = 0;"
11422 "for (var i = 0; i < 10; i++) {"
11423 " result += o.y;"
11424 "}"
11425 "result;",
11426 42 * 10);
11427}
11428
11429
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011430static void SetOnThis(Local<String> name,
11431 Local<Value> value,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011432 const v8::PropertyCallbackInfo<void>& info) {
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011433 info.This()->ForceSet(name, value);
11434}
11435
11436
11437THREADED_TEST(InterceptorLoadICWithCallbackOnHolder) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011438 v8::Isolate* isolate = CcTest::isolate();
11439 v8::HandleScope scope(isolate);
11440 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011441 templ->SetNamedPropertyHandler(InterceptorLoadXICGetter);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011442 templ->SetAccessor(v8_str("y"), Return239Callback);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011443 LocalContext context;
11444 context->Global()->Set(v8_str("o"), templ->NewInstance());
ricow@chromium.org30ce4112010-05-31 10:38:25 +000011445
11446 // Check the case when receiver and interceptor's holder
11447 // are the same objects.
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011448 v8::Handle<Value> value = CompileRun(
11449 "var result = 0;"
11450 "for (var i = 0; i < 7; i++) {"
11451 " result = o.y;"
11452 "}");
11453 CHECK_EQ(239, value->Int32Value());
ricow@chromium.org30ce4112010-05-31 10:38:25 +000011454
11455 // Check the case when interceptor's holder is in proto chain
11456 // of receiver.
11457 value = CompileRun(
11458 "r = { __proto__: o };"
11459 "var result = 0;"
11460 "for (var i = 0; i < 7; i++) {"
11461 " result = r.y;"
11462 "}");
11463 CHECK_EQ(239, value->Int32Value());
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011464}
11465
11466
11467THREADED_TEST(InterceptorLoadICWithCallbackOnProto) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011468 v8::Isolate* isolate = CcTest::isolate();
11469 v8::HandleScope scope(isolate);
11470 v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011471 templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011472 v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New(isolate);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011473 templ_p->SetAccessor(v8_str("y"), Return239Callback);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011474
11475 LocalContext context;
11476 context->Global()->Set(v8_str("o"), templ_o->NewInstance());
11477 context->Global()->Set(v8_str("p"), templ_p->NewInstance());
11478
ricow@chromium.org30ce4112010-05-31 10:38:25 +000011479 // Check the case when receiver and interceptor's holder
11480 // are the same objects.
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011481 v8::Handle<Value> value = CompileRun(
11482 "o.__proto__ = p;"
11483 "var result = 0;"
11484 "for (var i = 0; i < 7; i++) {"
11485 " result = o.x + o.y;"
11486 "}");
11487 CHECK_EQ(239 + 42, value->Int32Value());
ricow@chromium.org30ce4112010-05-31 10:38:25 +000011488
11489 // Check the case when interceptor's holder is in proto chain
11490 // of receiver.
11491 value = CompileRun(
11492 "r = { __proto__: o };"
11493 "var result = 0;"
11494 "for (var i = 0; i < 7; i++) {"
11495 " result = r.x + r.y;"
11496 "}");
11497 CHECK_EQ(239 + 42, value->Int32Value());
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011498}
11499
11500
11501THREADED_TEST(InterceptorLoadICForCallbackWithOverride) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011502 v8::Isolate* isolate = CcTest::isolate();
11503 v8::HandleScope scope(isolate);
11504 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011505 templ->SetNamedPropertyHandler(InterceptorLoadXICGetter);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011506 templ->SetAccessor(v8_str("y"), Return239Callback);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011507
11508 LocalContext context;
11509 context->Global()->Set(v8_str("o"), templ->NewInstance());
11510
11511 v8::Handle<Value> value = CompileRun(
11512 "fst = new Object(); fst.__proto__ = o;"
11513 "snd = new Object(); snd.__proto__ = fst;"
11514 "var result1 = 0;"
11515 "for (var i = 0; i < 7; i++) {"
11516 " result1 = snd.x;"
11517 "}"
11518 "fst.x = 239;"
11519 "var result = 0;"
11520 "for (var i = 0; i < 7; i++) {"
11521 " result = snd.x;"
11522 "}"
11523 "result + result1");
11524 CHECK_EQ(239 + 42, value->Int32Value());
11525}
11526
11527
11528// Test the case when we stored callback into
11529// a stub, but interceptor produced value on its own.
11530THREADED_TEST(InterceptorLoadICCallbackNotNeeded) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011531 v8::Isolate* isolate = CcTest::isolate();
11532 v8::HandleScope scope(isolate);
11533 v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011534 templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011535 v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New(isolate);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011536 templ_p->SetAccessor(v8_str("y"), Return239Callback);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011537
11538 LocalContext context;
11539 context->Global()->Set(v8_str("o"), templ_o->NewInstance());
11540 context->Global()->Set(v8_str("p"), templ_p->NewInstance());
11541
11542 v8::Handle<Value> value = CompileRun(
11543 "o.__proto__ = p;"
11544 "for (var i = 0; i < 7; i++) {"
11545 " o.x;"
11546 // Now it should be ICed and keep a reference to x defined on p
11547 "}"
11548 "var result = 0;"
11549 "for (var i = 0; i < 7; i++) {"
11550 " result += o.x;"
11551 "}"
11552 "result");
11553 CHECK_EQ(42 * 7, value->Int32Value());
11554}
11555
11556
11557// Test the case when we stored callback into
11558// a stub, but it got invalidated later on.
11559THREADED_TEST(InterceptorLoadICInvalidatedCallback) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011560 v8::Isolate* isolate = CcTest::isolate();
11561 v8::HandleScope scope(isolate);
11562 v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011563 templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011564 v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New(isolate);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011565 templ_p->SetAccessor(v8_str("y"), Return239Callback, SetOnThis);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011566
11567 LocalContext context;
11568 context->Global()->Set(v8_str("o"), templ_o->NewInstance());
11569 context->Global()->Set(v8_str("p"), templ_p->NewInstance());
11570
11571 v8::Handle<Value> value = CompileRun(
11572 "inbetween = new Object();"
11573 "o.__proto__ = inbetween;"
11574 "inbetween.__proto__ = p;"
11575 "for (var i = 0; i < 10; i++) {"
11576 " o.y;"
11577 // Now it should be ICed and keep a reference to y defined on p
11578 "}"
11579 "inbetween.y = 42;"
11580 "var result = 0;"
11581 "for (var i = 0; i < 10; i++) {"
11582 " result += o.y;"
11583 "}"
11584 "result");
11585 CHECK_EQ(42 * 10, value->Int32Value());
11586}
11587
11588
11589// Test the case when we stored callback into
11590// a stub, but it got invalidated later on due to override on
11591// global object which is between interceptor and callbacks' holders.
11592THREADED_TEST(InterceptorLoadICInvalidatedCallbackViaGlobal) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011593 v8::Isolate* isolate = CcTest::isolate();
11594 v8::HandleScope scope(isolate);
11595 v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011596 templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011597 v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New(isolate);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011598 templ_p->SetAccessor(v8_str("y"), Return239Callback, SetOnThis);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011599
11600 LocalContext context;
11601 context->Global()->Set(v8_str("o"), templ_o->NewInstance());
11602 context->Global()->Set(v8_str("p"), templ_p->NewInstance());
11603
11604 v8::Handle<Value> value = CompileRun(
11605 "o.__proto__ = this;"
11606 "this.__proto__ = p;"
11607 "for (var i = 0; i < 10; i++) {"
11608 " if (o.y != 239) throw 'oops: ' + o.y;"
11609 // Now it should be ICed and keep a reference to y defined on p
11610 "}"
11611 "this.y = 42;"
11612 "var result = 0;"
11613 "for (var i = 0; i < 10; i++) {"
11614 " result += o.y;"
11615 "}"
11616 "result");
11617 CHECK_EQ(42 * 10, value->Int32Value());
11618}
11619
11620
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011621static void InterceptorLoadICGetter0(
11622 Local<String> name,
11623 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.orge2902be2009-06-08 12:21:35 +000011624 ApiTestFuzzer::Fuzz();
11625 CHECK(v8_str("x")->Equals(name));
ulan@chromium.org0f13e742014-01-03 15:51:11 +000011626 info.GetReturnValue().Set(v8::Integer::New(info.GetIsolate(), 0));
ager@chromium.orge2902be2009-06-08 12:21:35 +000011627}
11628
11629
11630THREADED_TEST(InterceptorReturningZero) {
11631 CheckInterceptorLoadIC(InterceptorLoadICGetter0,
11632 "o.x == undefined ? 1 : 0",
11633 0);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011634}
11635
11636
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011637static void InterceptorStoreICSetter(
11638 Local<String> key,
11639 Local<Value> value,
11640 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011641 CHECK(v8_str("x")->Equals(key));
11642 CHECK_EQ(42, value->Int32Value());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011643 info.GetReturnValue().Set(value);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011644}
11645
11646
11647// This test should hit the store IC for the interceptor case.
11648THREADED_TEST(InterceptorStoreIC) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011649 v8::Isolate* isolate = CcTest::isolate();
11650 v8::HandleScope scope(isolate);
11651 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011652 templ->SetNamedPropertyHandler(InterceptorLoadICGetter,
vegorov@chromium.org21b5e952010-11-23 10:24:40 +000011653 InterceptorStoreICSetter,
11654 0, 0, 0, v8_str("data"));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011655 LocalContext context;
11656 context->Global()->Set(v8_str("o"), templ->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000011657 CompileRun(
11658 "for (var i = 0; i < 1000; i++) {"
11659 " o.x = 42;"
11660 "}");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011661}
11662
11663
ager@chromium.orgeadaf222009-06-16 09:43:10 +000011664THREADED_TEST(InterceptorStoreICWithNoSetter) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011665 v8::Isolate* isolate = CcTest::isolate();
11666 v8::HandleScope scope(isolate);
11667 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.orgeadaf222009-06-16 09:43:10 +000011668 templ->SetNamedPropertyHandler(InterceptorLoadXICGetter);
11669 LocalContext context;
11670 context->Global()->Set(v8_str("o"), templ->NewInstance());
11671 v8::Handle<Value> value = CompileRun(
11672 "for (var i = 0; i < 1000; i++) {"
11673 " o.y = 239;"
11674 "}"
11675 "42 + o.y");
11676 CHECK_EQ(239 + 42, value->Int32Value());
11677}
11678
11679
11680
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011681
11682v8::Handle<Value> call_ic_function;
11683v8::Handle<Value> call_ic_function2;
11684v8::Handle<Value> call_ic_function3;
11685
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011686static void InterceptorCallICGetter(
11687 Local<String> name,
11688 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011689 ApiTestFuzzer::Fuzz();
11690 CHECK(v8_str("x")->Equals(name));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011691 info.GetReturnValue().Set(call_ic_function);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011692}
11693
11694
11695// This test should hit the call IC for the interceptor case.
11696THREADED_TEST(InterceptorCallIC) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011697 v8::Isolate* isolate = CcTest::isolate();
11698 v8::HandleScope scope(isolate);
11699 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011700 templ->SetNamedPropertyHandler(InterceptorCallICGetter);
11701 LocalContext context;
11702 context->Global()->Set(v8_str("o"), templ->NewInstance());
11703 call_ic_function =
11704 v8_compile("function f(x) { return x + 1; }; f")->Run();
11705 v8::Handle<Value> value = CompileRun(
11706 "var result = 0;"
11707 "for (var i = 0; i < 1000; i++) {"
11708 " result = o.x(41);"
11709 "}");
11710 CHECK_EQ(42, value->Int32Value());
11711}
11712
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011713
11714// This test checks that if interceptor doesn't provide
11715// a value, we can fetch regular value.
11716THREADED_TEST(InterceptorCallICSeesOthers) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011717 v8::Isolate* isolate = CcTest::isolate();
11718 v8::HandleScope scope(isolate);
11719 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011720 templ->SetNamedPropertyHandler(NoBlockGetterX);
11721 LocalContext context;
11722 context->Global()->Set(v8_str("o"), templ->NewInstance());
11723 v8::Handle<Value> value = CompileRun(
11724 "o.x = function f(x) { return x + 1; };"
11725 "var result = 0;"
11726 "for (var i = 0; i < 7; i++) {"
11727 " result = o.x(41);"
11728 "}");
11729 CHECK_EQ(42, value->Int32Value());
11730}
11731
11732
11733static v8::Handle<Value> call_ic_function4;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011734static void InterceptorCallICGetter4(
11735 Local<String> name,
11736 const v8::PropertyCallbackInfo<v8::Value>& info) {
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011737 ApiTestFuzzer::Fuzz();
11738 CHECK(v8_str("x")->Equals(name));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011739 info.GetReturnValue().Set(call_ic_function4);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011740}
11741
11742
11743// This test checks that if interceptor provides a function,
11744// even if we cached shadowed variant, interceptor's function
11745// is invoked
11746THREADED_TEST(InterceptorCallICCacheableNotNeeded) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011747 v8::Isolate* isolate = CcTest::isolate();
11748 v8::HandleScope scope(isolate);
11749 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011750 templ->SetNamedPropertyHandler(InterceptorCallICGetter4);
11751 LocalContext context;
11752 context->Global()->Set(v8_str("o"), templ->NewInstance());
11753 call_ic_function4 =
11754 v8_compile("function f(x) { return x - 1; }; f")->Run();
11755 v8::Handle<Value> value = CompileRun(
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +000011756 "Object.getPrototypeOf(o).x = function(x) { return x + 1; };"
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011757 "var result = 0;"
11758 "for (var i = 0; i < 1000; i++) {"
11759 " result = o.x(42);"
11760 "}");
11761 CHECK_EQ(41, value->Int32Value());
11762}
11763
11764
11765// Test the case when we stored cacheable lookup into
11766// a stub, but it got invalidated later on
11767THREADED_TEST(InterceptorCallICInvalidatedCacheable) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011768 v8::Isolate* isolate = CcTest::isolate();
11769 v8::HandleScope scope(isolate);
11770 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011771 templ->SetNamedPropertyHandler(NoBlockGetterX);
11772 LocalContext context;
11773 context->Global()->Set(v8_str("o"), templ->NewInstance());
11774 v8::Handle<Value> value = CompileRun(
11775 "proto1 = new Object();"
11776 "proto2 = new Object();"
11777 "o.__proto__ = proto1;"
11778 "proto1.__proto__ = proto2;"
11779 "proto2.y = function(x) { return x + 1; };"
11780 // Invoke it many times to compile a stub
11781 "for (var i = 0; i < 7; i++) {"
11782 " o.y(42);"
11783 "}"
11784 "proto1.y = function(x) { return x - 1; };"
11785 "var result = 0;"
11786 "for (var i = 0; i < 7; i++) {"
11787 " result += o.y(42);"
11788 "}");
11789 CHECK_EQ(41 * 7, value->Int32Value());
11790}
11791
11792
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011793// This test checks that if interceptor doesn't provide a function,
11794// cached constant function is used
11795THREADED_TEST(InterceptorCallICConstantFunctionUsed) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011796 v8::Isolate* isolate = CcTest::isolate();
11797 v8::HandleScope scope(isolate);
11798 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011799 templ->SetNamedPropertyHandler(NoBlockGetterX);
11800 LocalContext context;
11801 context->Global()->Set(v8_str("o"), templ->NewInstance());
11802 v8::Handle<Value> value = CompileRun(
11803 "function inc(x) { return x + 1; };"
11804 "inc(1);"
11805 "o.x = inc;"
11806 "var result = 0;"
11807 "for (var i = 0; i < 1000; i++) {"
11808 " result = o.x(42);"
11809 "}");
11810 CHECK_EQ(43, value->Int32Value());
11811}
11812
11813
ulan@chromium.org2efb9002012-01-19 15:36:35 +000011814static v8::Handle<Value> call_ic_function5;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011815static void InterceptorCallICGetter5(
11816 Local<String> name,
11817 const v8::PropertyCallbackInfo<v8::Value>& info) {
ulan@chromium.org2efb9002012-01-19 15:36:35 +000011818 ApiTestFuzzer::Fuzz();
11819 if (v8_str("x")->Equals(name))
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011820 info.GetReturnValue().Set(call_ic_function5);
ulan@chromium.org2efb9002012-01-19 15:36:35 +000011821}
11822
11823
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011824// This test checks that if interceptor provides a function,
11825// even if we cached constant function, interceptor's function
11826// is invoked
11827THREADED_TEST(InterceptorCallICConstantFunctionNotNeeded) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011828 v8::Isolate* isolate = CcTest::isolate();
11829 v8::HandleScope scope(isolate);
11830 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011831 templ->SetNamedPropertyHandler(InterceptorCallICGetter5);
11832 LocalContext context;
11833 context->Global()->Set(v8_str("o"), templ->NewInstance());
11834 call_ic_function5 =
11835 v8_compile("function f(x) { return x - 1; }; f")->Run();
11836 v8::Handle<Value> value = CompileRun(
11837 "function inc(x) { return x + 1; };"
11838 "inc(1);"
11839 "o.x = inc;"
11840 "var result = 0;"
11841 "for (var i = 0; i < 1000; i++) {"
11842 " result = o.x(42);"
11843 "}");
11844 CHECK_EQ(41, value->Int32Value());
11845}
11846
11847
ulan@chromium.org2efb9002012-01-19 15:36:35 +000011848static v8::Handle<Value> call_ic_function6;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011849static void InterceptorCallICGetter6(
11850 Local<String> name,
11851 const v8::PropertyCallbackInfo<v8::Value>& info) {
ulan@chromium.org2efb9002012-01-19 15:36:35 +000011852 ApiTestFuzzer::Fuzz();
11853 if (v8_str("x")->Equals(name))
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011854 info.GetReturnValue().Set(call_ic_function6);
ulan@chromium.org2efb9002012-01-19 15:36:35 +000011855}
11856
11857
11858// Same test as above, except the code is wrapped in a function
11859// to test the optimized compiler.
11860THREADED_TEST(InterceptorCallICConstantFunctionNotNeededWrapped) {
11861 i::FLAG_allow_natives_syntax = true;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011862 v8::Isolate* isolate = CcTest::isolate();
11863 v8::HandleScope scope(isolate);
11864 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
ulan@chromium.org2efb9002012-01-19 15:36:35 +000011865 templ->SetNamedPropertyHandler(InterceptorCallICGetter6);
11866 LocalContext context;
11867 context->Global()->Set(v8_str("o"), templ->NewInstance());
11868 call_ic_function6 =
11869 v8_compile("function f(x) { return x - 1; }; f")->Run();
11870 v8::Handle<Value> value = CompileRun(
11871 "function inc(x) { return x + 1; };"
11872 "inc(1);"
11873 "o.x = inc;"
11874 "function test() {"
11875 " var result = 0;"
11876 " for (var i = 0; i < 1000; i++) {"
11877 " result = o.x(42);"
11878 " }"
11879 " return result;"
11880 "};"
11881 "test();"
11882 "test();"
11883 "test();"
11884 "%OptimizeFunctionOnNextCall(test);"
11885 "test()");
11886 CHECK_EQ(41, value->Int32Value());
11887}
11888
11889
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011890// Test the case when we stored constant function into
11891// a stub, but it got invalidated later on
11892THREADED_TEST(InterceptorCallICInvalidatedConstantFunction) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011893 v8::Isolate* isolate = CcTest::isolate();
11894 v8::HandleScope scope(isolate);
11895 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011896 templ->SetNamedPropertyHandler(NoBlockGetterX);
11897 LocalContext context;
11898 context->Global()->Set(v8_str("o"), templ->NewInstance());
11899 v8::Handle<Value> value = CompileRun(
11900 "function inc(x) { return x + 1; };"
11901 "inc(1);"
11902 "proto1 = new Object();"
11903 "proto2 = new Object();"
11904 "o.__proto__ = proto1;"
11905 "proto1.__proto__ = proto2;"
11906 "proto2.y = inc;"
11907 // Invoke it many times to compile a stub
11908 "for (var i = 0; i < 7; i++) {"
11909 " o.y(42);"
11910 "}"
11911 "proto1.y = function(x) { return x - 1; };"
11912 "var result = 0;"
11913 "for (var i = 0; i < 7; i++) {"
11914 " result += o.y(42);"
11915 "}");
11916 CHECK_EQ(41 * 7, value->Int32Value());
11917}
11918
11919
11920// Test the case when we stored constant function into
11921// a stub, but it got invalidated later on due to override on
11922// global object which is between interceptor and constant function' holders.
11923THREADED_TEST(InterceptorCallICInvalidatedConstantFunctionViaGlobal) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011924 v8::Isolate* isolate = CcTest::isolate();
11925 v8::HandleScope scope(isolate);
11926 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011927 templ->SetNamedPropertyHandler(NoBlockGetterX);
11928 LocalContext context;
11929 context->Global()->Set(v8_str("o"), templ->NewInstance());
11930 v8::Handle<Value> value = CompileRun(
11931 "function inc(x) { return x + 1; };"
11932 "inc(1);"
11933 "o.__proto__ = this;"
11934 "this.__proto__.y = inc;"
11935 // Invoke it many times to compile a stub
11936 "for (var i = 0; i < 7; i++) {"
11937 " if (o.y(42) != 43) throw 'oops: ' + o.y(42);"
11938 "}"
11939 "this.y = function(x) { return x - 1; };"
11940 "var result = 0;"
11941 "for (var i = 0; i < 7; i++) {"
11942 " result += o.y(42);"
11943 "}");
11944 CHECK_EQ(41 * 7, value->Int32Value());
11945}
11946
11947
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000011948// Test the case when actual function to call sits on global object.
11949THREADED_TEST(InterceptorCallICCachedFromGlobal) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011950 v8::Isolate* isolate = CcTest::isolate();
11951 v8::HandleScope scope(isolate);
11952 v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000011953 templ_o->SetNamedPropertyHandler(NoBlockGetterX);
11954
11955 LocalContext context;
11956 context->Global()->Set(v8_str("o"), templ_o->NewInstance());
11957
11958 v8::Handle<Value> value = CompileRun(
11959 "try {"
11960 " o.__proto__ = this;"
11961 " for (var i = 0; i < 10; i++) {"
11962 " var v = o.parseFloat('239');"
11963 " if (v != 239) throw v;"
11964 // Now it should be ICed and keep a reference to parseFloat.
11965 " }"
11966 " var result = 0;"
11967 " for (var i = 0; i < 10; i++) {"
11968 " result += o.parseFloat('239');"
11969 " }"
11970 " result"
11971 "} catch(e) {"
11972 " e"
11973 "};");
11974 CHECK_EQ(239 * 10, value->Int32Value());
11975}
11976
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011977static void InterceptorCallICFastApi(
11978 Local<String> name,
11979 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.org5c838252010-02-19 08:53:10 +000011980 ApiTestFuzzer::Fuzz();
dslomov@chromium.orgb752d402013-06-18 11:54:54 +000011981 CheckReturnValue(info, FUNCTION_ADDR(InterceptorCallICFastApi));
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000011982 int* call_count =
11983 reinterpret_cast<int*>(v8::External::Cast(*info.Data())->Value());
ager@chromium.org5c838252010-02-19 08:53:10 +000011984 ++(*call_count);
11985 if ((*call_count) % 20 == 0) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000011986 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org5c838252010-02-19 08:53:10 +000011987 }
ager@chromium.org5c838252010-02-19 08:53:10 +000011988}
11989
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011990static void FastApiCallback_TrivialSignature(
11991 const v8::FunctionCallbackInfo<v8::Value>& args) {
ager@chromium.org5c838252010-02-19 08:53:10 +000011992 ApiTestFuzzer::Fuzz();
dslomov@chromium.orgb752d402013-06-18 11:54:54 +000011993 CheckReturnValue(args, FUNCTION_ADDR(FastApiCallback_TrivialSignature));
machenbach@chromium.org528ce022013-09-23 14:09:36 +000011994 v8::Isolate* isolate = CcTest::isolate();
jkummerow@chromium.org28faa982012-04-13 09:58:30 +000011995 CHECK_EQ(isolate, args.GetIsolate());
ager@chromium.org5c838252010-02-19 08:53:10 +000011996 CHECK_EQ(args.This(), args.Holder());
11997 CHECK(args.Data()->Equals(v8_str("method_data")));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011998 args.GetReturnValue().Set(args[0]->Int32Value() + 1);
ager@chromium.org5c838252010-02-19 08:53:10 +000011999}
12000
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012001static void FastApiCallback_SimpleSignature(
12002 const v8::FunctionCallbackInfo<v8::Value>& args) {
ager@chromium.org5c838252010-02-19 08:53:10 +000012003 ApiTestFuzzer::Fuzz();
dslomov@chromium.orgb752d402013-06-18 11:54:54 +000012004 CheckReturnValue(args, FUNCTION_ADDR(FastApiCallback_SimpleSignature));
machenbach@chromium.org528ce022013-09-23 14:09:36 +000012005 v8::Isolate* isolate = CcTest::isolate();
jkummerow@chromium.org28faa982012-04-13 09:58:30 +000012006 CHECK_EQ(isolate, args.GetIsolate());
ager@chromium.org5c838252010-02-19 08:53:10 +000012007 CHECK_EQ(args.This()->GetPrototype(), args.Holder());
12008 CHECK(args.Data()->Equals(v8_str("method_data")));
12009 // Note, we're using HasRealNamedProperty instead of Has to avoid
12010 // invoking the interceptor again.
12011 CHECK(args.Holder()->HasRealNamedProperty(v8_str("foo")));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012012 args.GetReturnValue().Set(args[0]->Int32Value() + 1);
ager@chromium.org5c838252010-02-19 08:53:10 +000012013}
12014
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012015
ager@chromium.org5c838252010-02-19 08:53:10 +000012016// Helper to maximize the odds of object moving.
12017static void GenerateSomeGarbage() {
12018 CompileRun(
12019 "var garbage;"
12020 "for (var i = 0; i < 1000; i++) {"
12021 " garbage = [1/i, \"garbage\" + i, garbage, {foo: garbage}];"
12022 "}"
12023 "garbage = undefined;");
12024}
12025
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000012026
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012027void DirectApiCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +000012028 static int count = 0;
12029 if (count++ % 3 == 0) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000012030 CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
yangguo@chromium.orgd2899aa2012-06-21 11:16:20 +000012031 // This should move the stub
ricow@chromium.org83aa5492011-02-07 12:42:56 +000012032 GenerateSomeGarbage(); // This should ensure the old stub memory is flushed
12033 }
ricow@chromium.org83aa5492011-02-07 12:42:56 +000012034}
12035
12036
12037THREADED_TEST(CallICFastApi_DirectCall_GCMoveStub) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +000012038 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012039 v8::Isolate* isolate = context->GetIsolate();
12040 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012041 v8::Handle<v8::ObjectTemplate> nativeobject_templ =
12042 v8::ObjectTemplate::New(isolate);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012043 nativeobject_templ->Set(isolate, "callback",
12044 v8::FunctionTemplate::New(isolate,
12045 DirectApiCallback));
ricow@chromium.org83aa5492011-02-07 12:42:56 +000012046 v8::Local<v8::Object> nativeobject_obj = nativeobject_templ->NewInstance();
12047 context->Global()->Set(v8_str("nativeobject"), nativeobject_obj);
12048 // call the api function multiple times to ensure direct call stub creation.
12049 CompileRun(
12050 "function f() {"
12051 " for (var i = 1; i <= 30; i++) {"
12052 " nativeobject.callback();"
12053 " }"
12054 "}"
12055 "f();");
12056}
12057
12058
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012059void ThrowingDirectApiCallback(
12060 const v8::FunctionCallbackInfo<v8::Value>& args) {
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000012061 args.GetIsolate()->ThrowException(v8_str("g"));
ricow@chromium.org83aa5492011-02-07 12:42:56 +000012062}
12063
12064
12065THREADED_TEST(CallICFastApi_DirectCall_Throw) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +000012066 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012067 v8::Isolate* isolate = context->GetIsolate();
12068 v8::HandleScope scope(isolate);
12069 v8::Handle<v8::ObjectTemplate> nativeobject_templ =
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012070 v8::ObjectTemplate::New(isolate);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012071 nativeobject_templ->Set(isolate, "callback",
12072 v8::FunctionTemplate::New(isolate,
12073 ThrowingDirectApiCallback));
ricow@chromium.org83aa5492011-02-07 12:42:56 +000012074 v8::Local<v8::Object> nativeobject_obj = nativeobject_templ->NewInstance();
12075 context->Global()->Set(v8_str("nativeobject"), nativeobject_obj);
12076 // call the api function multiple times to ensure direct call stub creation.
12077 v8::Handle<Value> result = CompileRun(
12078 "var result = '';"
12079 "function f() {"
12080 " for (var i = 1; i <= 5; i++) {"
12081 " try { nativeobject.callback(); } catch (e) { result += e; }"
12082 " }"
12083 "}"
12084 "f(); result;");
12085 CHECK_EQ(v8_str("ggggg"), result);
12086}
12087
12088
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +000012089static Handle<Value> DoDirectGetter() {
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000012090 if (++p_getter_count % 3 == 0) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000012091 CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000012092 GenerateSomeGarbage();
12093 }
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +000012094 return v8_str("Direct Getter Result");
12095}
12096
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +000012097static void DirectGetterCallback(
12098 Local<String> name,
12099 const v8::PropertyCallbackInfo<v8::Value>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +000012100 CheckReturnValue(info, FUNCTION_ADDR(DirectGetterCallback));
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +000012101 info.GetReturnValue().Set(DoDirectGetter());
12102}
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000012103
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +000012104
12105template<typename Accessor>
12106static void LoadICFastApi_DirectCall_GCMoveStub(Accessor accessor) {
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000012107 LocalContext context;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012108 v8::Isolate* isolate = context->GetIsolate();
12109 v8::HandleScope scope(isolate);
12110 v8::Handle<v8::ObjectTemplate> obj = v8::ObjectTemplate::New(isolate);
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +000012111 obj->SetAccessor(v8_str("p1"), accessor);
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000012112 context->Global()->Set(v8_str("o1"), obj->NewInstance());
12113 p_getter_count = 0;
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +000012114 v8::Handle<v8::Value> result = CompileRun(
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000012115 "function f() {"
12116 " for (var i = 0; i < 30; i++) o1.p1;"
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +000012117 " return o1.p1"
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000012118 "}"
12119 "f();");
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +000012120 CHECK_EQ(v8_str("Direct Getter Result"), result);
12121 CHECK_EQ(31, p_getter_count);
12122}
12123
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012124
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012125THREADED_PROFILED_TEST(LoadICFastApi_DirectCall_GCMoveStub) {
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +000012126 LoadICFastApi_DirectCall_GCMoveStub(DirectGetterCallback);
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000012127}
12128
12129
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012130void ThrowingDirectGetterCallback(
12131 Local<String> name,
12132 const v8::PropertyCallbackInfo<v8::Value>& info) {
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000012133 info.GetIsolate()->ThrowException(v8_str("g"));
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000012134}
12135
12136
12137THREADED_TEST(LoadICFastApi_DirectCall_Throw) {
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000012138 LocalContext context;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012139 v8::Isolate* isolate = context->GetIsolate();
12140 v8::HandleScope scope(isolate);
12141 v8::Handle<v8::ObjectTemplate> obj = v8::ObjectTemplate::New(isolate);
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000012142 obj->SetAccessor(v8_str("p1"), ThrowingDirectGetterCallback);
12143 context->Global()->Set(v8_str("o1"), obj->NewInstance());
12144 v8::Handle<Value> result = CompileRun(
12145 "var result = '';"
12146 "for (var i = 0; i < 5; i++) {"
12147 " try { o1.p1; } catch (e) { result += e; }"
12148 "}"
12149 "result;");
12150 CHECK_EQ(v8_str("ggggg"), result);
12151}
12152
12153
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012154THREADED_PROFILED_TEST(InterceptorCallICFastApi_TrivialSignature) {
ager@chromium.org5c838252010-02-19 08:53:10 +000012155 int interceptor_call_count = 0;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012156 v8::Isolate* isolate = CcTest::isolate();
12157 v8::HandleScope scope(isolate);
12158 v8::Handle<v8::FunctionTemplate> fun_templ =
12159 v8::FunctionTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +000012160 v8::Handle<v8::FunctionTemplate> method_templ =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012161 v8::FunctionTemplate::New(isolate,
12162 FastApiCallback_TrivialSignature,
ager@chromium.org5c838252010-02-19 08:53:10 +000012163 v8_str("method_data"),
12164 v8::Handle<v8::Signature>());
12165 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12166 proto_templ->Set(v8_str("method"), method_templ);
12167 v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
machenbach@chromium.org0cc09502013-11-13 12:20:55 +000012168 templ->SetNamedPropertyHandler(
12169 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012170 v8::External::New(isolate, &interceptor_call_count));
ager@chromium.org5c838252010-02-19 08:53:10 +000012171 LocalContext context;
12172 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12173 GenerateSomeGarbage();
12174 context->Global()->Set(v8_str("o"), fun->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012175 CompileRun(
ager@chromium.org5c838252010-02-19 08:53:10 +000012176 "var result = 0;"
12177 "for (var i = 0; i < 100; i++) {"
12178 " result = o.method(41);"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012179 "}");
ager@chromium.org5c838252010-02-19 08:53:10 +000012180 CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
12181 CHECK_EQ(100, interceptor_call_count);
12182}
12183
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012184
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012185THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature) {
ager@chromium.org5c838252010-02-19 08:53:10 +000012186 int interceptor_call_count = 0;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012187 v8::Isolate* isolate = CcTest::isolate();
12188 v8::HandleScope scope(isolate);
12189 v8::Handle<v8::FunctionTemplate> fun_templ =
12190 v8::FunctionTemplate::New(isolate);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000012191 v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012192 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12193 v8::Signature::New(isolate, fun_templ));
ager@chromium.org5c838252010-02-19 08:53:10 +000012194 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12195 proto_templ->Set(v8_str("method"), method_templ);
mmassi@chromium.org49a44672012-12-04 13:52:03 +000012196 fun_templ->SetHiddenPrototype(true);
ager@chromium.org5c838252010-02-19 08:53:10 +000012197 v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
machenbach@chromium.org0cc09502013-11-13 12:20:55 +000012198 templ->SetNamedPropertyHandler(
12199 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012200 v8::External::New(isolate, &interceptor_call_count));
ager@chromium.org5c838252010-02-19 08:53:10 +000012201 LocalContext context;
12202 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12203 GenerateSomeGarbage();
12204 context->Global()->Set(v8_str("o"), fun->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012205 CompileRun(
ager@chromium.org5c838252010-02-19 08:53:10 +000012206 "o.foo = 17;"
12207 "var receiver = {};"
12208 "receiver.__proto__ = o;"
12209 "var result = 0;"
12210 "for (var i = 0; i < 100; i++) {"
12211 " result = receiver.method(41);"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012212 "}");
ager@chromium.org5c838252010-02-19 08:53:10 +000012213 CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
12214 CHECK_EQ(100, interceptor_call_count);
12215}
12216
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012217
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012218THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss1) {
ager@chromium.org5c838252010-02-19 08:53:10 +000012219 int interceptor_call_count = 0;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012220 v8::Isolate* isolate = CcTest::isolate();
12221 v8::HandleScope scope(isolate);
12222 v8::Handle<v8::FunctionTemplate> fun_templ =
12223 v8::FunctionTemplate::New(isolate);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000012224 v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012225 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12226 v8::Signature::New(isolate, fun_templ));
ager@chromium.org5c838252010-02-19 08:53:10 +000012227 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12228 proto_templ->Set(v8_str("method"), method_templ);
mmassi@chromium.org49a44672012-12-04 13:52:03 +000012229 fun_templ->SetHiddenPrototype(true);
ager@chromium.org5c838252010-02-19 08:53:10 +000012230 v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
machenbach@chromium.org0cc09502013-11-13 12:20:55 +000012231 templ->SetNamedPropertyHandler(
12232 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012233 v8::External::New(isolate, &interceptor_call_count));
ager@chromium.org5c838252010-02-19 08:53:10 +000012234 LocalContext context;
12235 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12236 GenerateSomeGarbage();
12237 context->Global()->Set(v8_str("o"), fun->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012238 CompileRun(
ager@chromium.org5c838252010-02-19 08:53:10 +000012239 "o.foo = 17;"
12240 "var receiver = {};"
12241 "receiver.__proto__ = o;"
12242 "var result = 0;"
12243 "var saved_result = 0;"
12244 "for (var i = 0; i < 100; i++) {"
12245 " result = receiver.method(41);"
12246 " if (i == 50) {"
12247 " saved_result = result;"
12248 " receiver = {method: function(x) { return x - 1 }};"
12249 " }"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012250 "}");
ager@chromium.org5c838252010-02-19 08:53:10 +000012251 CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
12252 CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
12253 CHECK_GE(interceptor_call_count, 50);
12254}
12255
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012256
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012257THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss2) {
ager@chromium.org5c838252010-02-19 08:53:10 +000012258 int interceptor_call_count = 0;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012259 v8::Isolate* isolate = CcTest::isolate();
12260 v8::HandleScope scope(isolate);
12261 v8::Handle<v8::FunctionTemplate> fun_templ =
12262 v8::FunctionTemplate::New(isolate);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000012263 v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012264 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12265 v8::Signature::New(isolate, fun_templ));
ager@chromium.org5c838252010-02-19 08:53:10 +000012266 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12267 proto_templ->Set(v8_str("method"), method_templ);
mmassi@chromium.org49a44672012-12-04 13:52:03 +000012268 fun_templ->SetHiddenPrototype(true);
ager@chromium.org5c838252010-02-19 08:53:10 +000012269 v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
machenbach@chromium.org0cc09502013-11-13 12:20:55 +000012270 templ->SetNamedPropertyHandler(
12271 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012272 v8::External::New(isolate, &interceptor_call_count));
ager@chromium.org5c838252010-02-19 08:53:10 +000012273 LocalContext context;
12274 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12275 GenerateSomeGarbage();
12276 context->Global()->Set(v8_str("o"), fun->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012277 CompileRun(
ager@chromium.org5c838252010-02-19 08:53:10 +000012278 "o.foo = 17;"
12279 "var receiver = {};"
12280 "receiver.__proto__ = o;"
12281 "var result = 0;"
12282 "var saved_result = 0;"
12283 "for (var i = 0; i < 100; i++) {"
12284 " result = receiver.method(41);"
12285 " if (i == 50) {"
12286 " saved_result = result;"
12287 " o.method = function(x) { return x - 1 };"
12288 " }"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012289 "}");
ager@chromium.org5c838252010-02-19 08:53:10 +000012290 CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
12291 CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
12292 CHECK_GE(interceptor_call_count, 50);
12293}
12294
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012295
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012296THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss3) {
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000012297 int interceptor_call_count = 0;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012298 v8::Isolate* isolate = CcTest::isolate();
12299 v8::HandleScope scope(isolate);
12300 v8::Handle<v8::FunctionTemplate> fun_templ =
12301 v8::FunctionTemplate::New(isolate);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000012302 v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012303 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12304 v8::Signature::New(isolate, fun_templ));
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000012305 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12306 proto_templ->Set(v8_str("method"), method_templ);
mmassi@chromium.org49a44672012-12-04 13:52:03 +000012307 fun_templ->SetHiddenPrototype(true);
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000012308 v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
machenbach@chromium.org0cc09502013-11-13 12:20:55 +000012309 templ->SetNamedPropertyHandler(
12310 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012311 v8::External::New(isolate, &interceptor_call_count));
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000012312 LocalContext context;
12313 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12314 GenerateSomeGarbage();
12315 context->Global()->Set(v8_str("o"), fun->NewInstance());
12316 v8::TryCatch try_catch;
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012317 CompileRun(
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000012318 "o.foo = 17;"
12319 "var receiver = {};"
12320 "receiver.__proto__ = o;"
12321 "var result = 0;"
12322 "var saved_result = 0;"
12323 "for (var i = 0; i < 100; i++) {"
12324 " result = receiver.method(41);"
12325 " if (i == 50) {"
12326 " saved_result = result;"
12327 " receiver = 333;"
12328 " }"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012329 "}");
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000012330 CHECK(try_catch.HasCaught());
12331 CHECK_EQ(v8_str("TypeError: Object 333 has no method 'method'"),
12332 try_catch.Exception()->ToString());
12333 CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
12334 CHECK_GE(interceptor_call_count, 50);
12335}
12336
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012337
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012338THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_TypeError) {
ager@chromium.org5c838252010-02-19 08:53:10 +000012339 int interceptor_call_count = 0;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012340 v8::Isolate* isolate = CcTest::isolate();
12341 v8::HandleScope scope(isolate);
12342 v8::Handle<v8::FunctionTemplate> fun_templ =
12343 v8::FunctionTemplate::New(isolate);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000012344 v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012345 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12346 v8::Signature::New(isolate, fun_templ));
ager@chromium.org5c838252010-02-19 08:53:10 +000012347 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12348 proto_templ->Set(v8_str("method"), method_templ);
mmassi@chromium.org49a44672012-12-04 13:52:03 +000012349 fun_templ->SetHiddenPrototype(true);
ager@chromium.org5c838252010-02-19 08:53:10 +000012350 v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
machenbach@chromium.org0cc09502013-11-13 12:20:55 +000012351 templ->SetNamedPropertyHandler(
12352 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012353 v8::External::New(isolate, &interceptor_call_count));
ager@chromium.org5c838252010-02-19 08:53:10 +000012354 LocalContext context;
12355 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12356 GenerateSomeGarbage();
12357 context->Global()->Set(v8_str("o"), fun->NewInstance());
12358 v8::TryCatch try_catch;
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012359 CompileRun(
ager@chromium.org5c838252010-02-19 08:53:10 +000012360 "o.foo = 17;"
12361 "var receiver = {};"
12362 "receiver.__proto__ = o;"
12363 "var result = 0;"
12364 "var saved_result = 0;"
12365 "for (var i = 0; i < 100; i++) {"
12366 " result = receiver.method(41);"
12367 " if (i == 50) {"
12368 " saved_result = result;"
12369 " receiver = {method: receiver.method};"
12370 " }"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012371 "}");
ager@chromium.org5c838252010-02-19 08:53:10 +000012372 CHECK(try_catch.HasCaught());
12373 CHECK_EQ(v8_str("TypeError: Illegal invocation"),
12374 try_catch.Exception()->ToString());
12375 CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
12376 CHECK_GE(interceptor_call_count, 50);
12377}
12378
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012379
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012380THREADED_PROFILED_TEST(CallICFastApi_TrivialSignature) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012381 v8::Isolate* isolate = CcTest::isolate();
12382 v8::HandleScope scope(isolate);
12383 v8::Handle<v8::FunctionTemplate> fun_templ =
12384 v8::FunctionTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +000012385 v8::Handle<v8::FunctionTemplate> method_templ =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012386 v8::FunctionTemplate::New(isolate,
12387 FastApiCallback_TrivialSignature,
ager@chromium.org5c838252010-02-19 08:53:10 +000012388 v8_str("method_data"),
12389 v8::Handle<v8::Signature>());
12390 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12391 proto_templ->Set(v8_str("method"), method_templ);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000012392 v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012393 USE(templ);
ager@chromium.org5c838252010-02-19 08:53:10 +000012394 LocalContext context;
12395 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12396 GenerateSomeGarbage();
12397 context->Global()->Set(v8_str("o"), fun->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012398 CompileRun(
ager@chromium.org5c838252010-02-19 08:53:10 +000012399 "var result = 0;"
12400 "for (var i = 0; i < 100; i++) {"
12401 " result = o.method(41);"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012402 "}");
ager@chromium.org5c838252010-02-19 08:53:10 +000012403
12404 CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
12405}
12406
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012407
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012408THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012409 v8::Isolate* isolate = CcTest::isolate();
12410 v8::HandleScope scope(isolate);
12411 v8::Handle<v8::FunctionTemplate> fun_templ =
12412 v8::FunctionTemplate::New(isolate);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000012413 v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012414 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12415 v8::Signature::New(isolate, fun_templ));
ager@chromium.org5c838252010-02-19 08:53:10 +000012416 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12417 proto_templ->Set(v8_str("method"), method_templ);
mmassi@chromium.org49a44672012-12-04 13:52:03 +000012418 fun_templ->SetHiddenPrototype(true);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000012419 v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012420 CHECK(!templ.IsEmpty());
ager@chromium.org5c838252010-02-19 08:53:10 +000012421 LocalContext context;
12422 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12423 GenerateSomeGarbage();
12424 context->Global()->Set(v8_str("o"), fun->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012425 CompileRun(
ager@chromium.org5c838252010-02-19 08:53:10 +000012426 "o.foo = 17;"
12427 "var receiver = {};"
12428 "receiver.__proto__ = o;"
12429 "var result = 0;"
12430 "for (var i = 0; i < 100; i++) {"
12431 " result = receiver.method(41);"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012432 "}");
ager@chromium.org5c838252010-02-19 08:53:10 +000012433
12434 CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
12435}
12436
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012437
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012438THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_Miss1) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012439 v8::Isolate* isolate = CcTest::isolate();
12440 v8::HandleScope scope(isolate);
12441 v8::Handle<v8::FunctionTemplate> fun_templ =
12442 v8::FunctionTemplate::New(isolate);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000012443 v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012444 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12445 v8::Signature::New(isolate, fun_templ));
ager@chromium.org5c838252010-02-19 08:53:10 +000012446 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12447 proto_templ->Set(v8_str("method"), method_templ);
mmassi@chromium.org49a44672012-12-04 13:52:03 +000012448 fun_templ->SetHiddenPrototype(true);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000012449 v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012450 CHECK(!templ.IsEmpty());
ager@chromium.org5c838252010-02-19 08:53:10 +000012451 LocalContext context;
12452 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12453 GenerateSomeGarbage();
12454 context->Global()->Set(v8_str("o"), fun->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012455 CompileRun(
ager@chromium.org5c838252010-02-19 08:53:10 +000012456 "o.foo = 17;"
12457 "var receiver = {};"
12458 "receiver.__proto__ = o;"
12459 "var result = 0;"
12460 "var saved_result = 0;"
12461 "for (var i = 0; i < 100; i++) {"
12462 " result = receiver.method(41);"
12463 " if (i == 50) {"
12464 " saved_result = result;"
12465 " receiver = {method: function(x) { return x - 1 }};"
12466 " }"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012467 "}");
ager@chromium.org5c838252010-02-19 08:53:10 +000012468 CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
12469 CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
12470}
12471
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012472
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012473THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_Miss2) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012474 v8::Isolate* isolate = CcTest::isolate();
12475 v8::HandleScope scope(isolate);
12476 v8::Handle<v8::FunctionTemplate> fun_templ =
12477 v8::FunctionTemplate::New(isolate);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000012478 v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012479 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12480 v8::Signature::New(isolate, fun_templ));
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000012481 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12482 proto_templ->Set(v8_str("method"), method_templ);
mmassi@chromium.org49a44672012-12-04 13:52:03 +000012483 fun_templ->SetHiddenPrototype(true);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000012484 v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012485 CHECK(!templ.IsEmpty());
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000012486 LocalContext context;
12487 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12488 GenerateSomeGarbage();
12489 context->Global()->Set(v8_str("o"), fun->NewInstance());
12490 v8::TryCatch try_catch;
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012491 CompileRun(
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000012492 "o.foo = 17;"
12493 "var receiver = {};"
12494 "receiver.__proto__ = o;"
12495 "var result = 0;"
12496 "var saved_result = 0;"
12497 "for (var i = 0; i < 100; i++) {"
12498 " result = receiver.method(41);"
12499 " if (i == 50) {"
12500 " saved_result = result;"
12501 " receiver = 333;"
12502 " }"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012503 "}");
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000012504 CHECK(try_catch.HasCaught());
12505 CHECK_EQ(v8_str("TypeError: Object 333 has no method 'method'"),
12506 try_catch.Exception()->ToString());
12507 CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
12508}
12509
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012510
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012511THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_TypeError) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012512 v8::Isolate* isolate = CcTest::isolate();
12513 v8::HandleScope scope(isolate);
12514 v8::Handle<v8::FunctionTemplate> fun_templ =
12515 v8::FunctionTemplate::New(isolate);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000012516 v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012517 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12518 v8::Signature::New(isolate, fun_templ));
mmassi@chromium.org49a44672012-12-04 13:52:03 +000012519 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12520 proto_templ->Set(v8_str("method"), method_templ);
12521 fun_templ->SetHiddenPrototype(true);
12522 v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
12523 CHECK(!templ.IsEmpty());
12524 LocalContext context;
12525 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12526 GenerateSomeGarbage();
12527 context->Global()->Set(v8_str("o"), fun->NewInstance());
12528 v8::TryCatch try_catch;
12529 CompileRun(
12530 "o.foo = 17;"
12531 "var receiver = {};"
12532 "receiver.__proto__ = o;"
12533 "var result = 0;"
12534 "var saved_result = 0;"
12535 "for (var i = 0; i < 100; i++) {"
12536 " result = receiver.method(41);"
12537 " if (i == 50) {"
12538 " saved_result = result;"
12539 " receiver = Object.create(receiver);"
12540 " }"
12541 "}");
12542 CHECK(try_catch.HasCaught());
12543 CHECK_EQ(v8_str("TypeError: Illegal invocation"),
12544 try_catch.Exception()->ToString());
12545 CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
12546}
12547
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000012548
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012549v8::Handle<Value> keyed_call_ic_function;
12550
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012551static void InterceptorKeyedCallICGetter(
12552 Local<String> name,
12553 const v8::PropertyCallbackInfo<v8::Value>& info) {
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012554 ApiTestFuzzer::Fuzz();
12555 if (v8_str("x")->Equals(name)) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012556 info.GetReturnValue().Set(keyed_call_ic_function);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012557 }
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012558}
12559
12560
12561// Test the case when we stored cacheable lookup into
12562// a stub, but the function name changed (to another cacheable function).
12563THREADED_TEST(InterceptorKeyedCallICKeyChange1) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012564 v8::Isolate* isolate = CcTest::isolate();
12565 v8::HandleScope scope(isolate);
12566 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012567 templ->SetNamedPropertyHandler(NoBlockGetterX);
12568 LocalContext context;
12569 context->Global()->Set(v8_str("o"), templ->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012570 CompileRun(
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012571 "proto = new Object();"
12572 "proto.y = function(x) { return x + 1; };"
12573 "proto.z = function(x) { return x - 1; };"
12574 "o.__proto__ = proto;"
12575 "var result = 0;"
12576 "var method = 'y';"
12577 "for (var i = 0; i < 10; i++) {"
12578 " if (i == 5) { method = 'z'; };"
12579 " result += o[method](41);"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012580 "}");
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012581 CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
12582}
12583
12584
12585// Test the case when we stored cacheable lookup into
12586// a stub, but the function name changed (and the new function is present
12587// both before and after the interceptor in the prototype chain).
12588THREADED_TEST(InterceptorKeyedCallICKeyChange2) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012589 v8::Isolate* isolate = CcTest::isolate();
12590 v8::HandleScope scope(isolate);
12591 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012592 templ->SetNamedPropertyHandler(InterceptorKeyedCallICGetter);
12593 LocalContext context;
12594 context->Global()->Set(v8_str("proto1"), templ->NewInstance());
12595 keyed_call_ic_function =
12596 v8_compile("function f(x) { return x - 1; }; f")->Run();
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012597 CompileRun(
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012598 "o = new Object();"
12599 "proto2 = new Object();"
12600 "o.y = function(x) { return x + 1; };"
12601 "proto2.y = function(x) { return x + 2; };"
12602 "o.__proto__ = proto1;"
12603 "proto1.__proto__ = proto2;"
12604 "var result = 0;"
12605 "var method = 'x';"
12606 "for (var i = 0; i < 10; i++) {"
12607 " if (i == 5) { method = 'y'; };"
12608 " result += o[method](41);"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012609 "}");
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012610 CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
12611}
12612
12613
12614// Same as InterceptorKeyedCallICKeyChange1 only the cacheable function sit
12615// on the global object.
12616THREADED_TEST(InterceptorKeyedCallICKeyChangeOnGlobal) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012617 v8::Isolate* isolate = CcTest::isolate();
12618 v8::HandleScope scope(isolate);
12619 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012620 templ->SetNamedPropertyHandler(NoBlockGetterX);
12621 LocalContext context;
12622 context->Global()->Set(v8_str("o"), templ->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012623 CompileRun(
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012624 "function inc(x) { return x + 1; };"
12625 "inc(1);"
12626 "function dec(x) { return x - 1; };"
12627 "dec(1);"
12628 "o.__proto__ = this;"
12629 "this.__proto__.x = inc;"
12630 "this.__proto__.y = dec;"
12631 "var result = 0;"
12632 "var method = 'x';"
12633 "for (var i = 0; i < 10; i++) {"
12634 " if (i == 5) { method = 'y'; };"
12635 " result += o[method](41);"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012636 "}");
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012637 CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
12638}
12639
12640
12641// Test the case when actual function to call sits on global object.
12642THREADED_TEST(InterceptorKeyedCallICFromGlobal) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012643 v8::Isolate* isolate = CcTest::isolate();
12644 v8::HandleScope scope(isolate);
12645 v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012646 templ_o->SetNamedPropertyHandler(NoBlockGetterX);
12647 LocalContext context;
12648 context->Global()->Set(v8_str("o"), templ_o->NewInstance());
12649
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012650 CompileRun(
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012651 "function len(x) { return x.length; };"
12652 "o.__proto__ = this;"
12653 "var m = 'parseFloat';"
12654 "var result = 0;"
12655 "for (var i = 0; i < 10; i++) {"
12656 " if (i == 5) {"
12657 " m = 'len';"
12658 " saved_result = result;"
12659 " };"
12660 " result = o[m]('239');"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012661 "}");
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012662 CHECK_EQ(3, context->Global()->Get(v8_str("result"))->Int32Value());
12663 CHECK_EQ(239, context->Global()->Get(v8_str("saved_result"))->Int32Value());
12664}
12665
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012666
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012667// Test the map transition before the interceptor.
12668THREADED_TEST(InterceptorKeyedCallICMapChangeBefore) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012669 v8::Isolate* isolate = CcTest::isolate();
12670 v8::HandleScope scope(isolate);
12671 v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012672 templ_o->SetNamedPropertyHandler(NoBlockGetterX);
12673 LocalContext context;
12674 context->Global()->Set(v8_str("proto"), templ_o->NewInstance());
12675
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012676 CompileRun(
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012677 "var o = new Object();"
12678 "o.__proto__ = proto;"
12679 "o.method = function(x) { return x + 1; };"
12680 "var m = 'method';"
12681 "var result = 0;"
12682 "for (var i = 0; i < 10; i++) {"
12683 " if (i == 5) { o.method = function(x) { return x - 1; }; };"
12684 " result += o[m](41);"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012685 "}");
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012686 CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
12687}
12688
12689
12690// Test the map transition after the interceptor.
12691THREADED_TEST(InterceptorKeyedCallICMapChangeAfter) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012692 v8::Isolate* isolate = CcTest::isolate();
12693 v8::HandleScope scope(isolate);
12694 v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012695 templ_o->SetNamedPropertyHandler(NoBlockGetterX);
12696 LocalContext context;
12697 context->Global()->Set(v8_str("o"), templ_o->NewInstance());
12698
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012699 CompileRun(
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012700 "var proto = new Object();"
12701 "o.__proto__ = proto;"
12702 "proto.method = function(x) { return x + 1; };"
12703 "var m = 'method';"
12704 "var result = 0;"
12705 "for (var i = 0; i < 10; i++) {"
12706 " if (i == 5) { proto.method = function(x) { return x - 1; }; };"
12707 " result += o[m](41);"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012708 "}");
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012709 CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
12710}
12711
12712
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012713static int interceptor_call_count = 0;
12714
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012715static void InterceptorICRefErrorGetter(
12716 Local<String> name,
12717 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012718 ApiTestFuzzer::Fuzz();
12719 if (v8_str("x")->Equals(name) && interceptor_call_count++ < 20) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012720 info.GetReturnValue().Set(call_ic_function2);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012721 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012722}
12723
12724
12725// This test should hit load and call ICs for the interceptor case.
12726// Once in a while, the interceptor will reply that a property was not
12727// found in which case we should get a reference error.
12728THREADED_TEST(InterceptorICReferenceErrors) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012729 v8::Isolate* isolate = CcTest::isolate();
12730 v8::HandleScope scope(isolate);
12731 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012732 templ->SetNamedPropertyHandler(InterceptorICRefErrorGetter);
12733 LocalContext context(0, templ, v8::Handle<Value>());
12734 call_ic_function2 = v8_compile("function h(x) { return x; }; h")->Run();
12735 v8::Handle<Value> value = CompileRun(
12736 "function f() {"
12737 " for (var i = 0; i < 1000; i++) {"
12738 " try { x; } catch(e) { return true; }"
12739 " }"
12740 " return false;"
12741 "};"
12742 "f();");
12743 CHECK_EQ(true, value->BooleanValue());
12744 interceptor_call_count = 0;
12745 value = CompileRun(
12746 "function g() {"
12747 " for (var i = 0; i < 1000; i++) {"
12748 " try { x(42); } catch(e) { return true; }"
12749 " }"
12750 " return false;"
12751 "};"
12752 "g();");
12753 CHECK_EQ(true, value->BooleanValue());
12754}
12755
12756
12757static int interceptor_ic_exception_get_count = 0;
12758
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012759static void InterceptorICExceptionGetter(
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012760 Local<String> name,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012761 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012762 ApiTestFuzzer::Fuzz();
12763 if (v8_str("x")->Equals(name) && ++interceptor_ic_exception_get_count < 20) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012764 info.GetReturnValue().Set(call_ic_function3);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012765 }
12766 if (interceptor_ic_exception_get_count == 20) {
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000012767 info.GetIsolate()->ThrowException(v8_num(42));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012768 return;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012769 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012770}
12771
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012772
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012773// Test interceptor load/call IC where the interceptor throws an
12774// exception once in a while.
12775THREADED_TEST(InterceptorICGetterExceptions) {
12776 interceptor_ic_exception_get_count = 0;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012777 v8::Isolate* isolate = CcTest::isolate();
12778 v8::HandleScope scope(isolate);
12779 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012780 templ->SetNamedPropertyHandler(InterceptorICExceptionGetter);
12781 LocalContext context(0, templ, v8::Handle<Value>());
12782 call_ic_function3 = v8_compile("function h(x) { return x; }; h")->Run();
12783 v8::Handle<Value> value = CompileRun(
12784 "function f() {"
12785 " for (var i = 0; i < 100; i++) {"
12786 " try { x; } catch(e) { return true; }"
12787 " }"
12788 " return false;"
12789 "};"
12790 "f();");
12791 CHECK_EQ(true, value->BooleanValue());
12792 interceptor_ic_exception_get_count = 0;
12793 value = CompileRun(
12794 "function f() {"
12795 " for (var i = 0; i < 100; i++) {"
12796 " try { x(42); } catch(e) { return true; }"
12797 " }"
12798 " return false;"
12799 "};"
12800 "f();");
12801 CHECK_EQ(true, value->BooleanValue());
12802}
12803
12804
12805static int interceptor_ic_exception_set_count = 0;
12806
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012807static void InterceptorICExceptionSetter(
12808 Local<String> key,
12809 Local<Value> value,
12810 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012811 ApiTestFuzzer::Fuzz();
12812 if (++interceptor_ic_exception_set_count > 20) {
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000012813 info.GetIsolate()->ThrowException(v8_num(42));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012814 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012815}
12816
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012817
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012818// Test interceptor store IC where the interceptor throws an exception
12819// once in a while.
12820THREADED_TEST(InterceptorICSetterExceptions) {
12821 interceptor_ic_exception_set_count = 0;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012822 v8::Isolate* isolate = CcTest::isolate();
12823 v8::HandleScope scope(isolate);
12824 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012825 templ->SetNamedPropertyHandler(0, InterceptorICExceptionSetter);
12826 LocalContext context(0, templ, v8::Handle<Value>());
12827 v8::Handle<Value> value = CompileRun(
12828 "function f() {"
12829 " for (var i = 0; i < 100; i++) {"
12830 " try { x = 42; } catch(e) { return true; }"
12831 " }"
12832 " return false;"
12833 "};"
12834 "f();");
12835 CHECK_EQ(true, value->BooleanValue());
12836}
12837
12838
12839// Test that we ignore null interceptors.
12840THREADED_TEST(NullNamedInterceptor) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012841 v8::Isolate* isolate = CcTest::isolate();
12842 v8::HandleScope scope(isolate);
12843 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012844 templ->SetNamedPropertyHandler(
12845 static_cast<v8::NamedPropertyGetterCallback>(0));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012846 LocalContext context;
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000012847 templ->Set(CcTest::isolate(), "x", v8_num(42));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012848 v8::Handle<v8::Object> obj = templ->NewInstance();
12849 context->Global()->Set(v8_str("obj"), obj);
12850 v8::Handle<Value> value = CompileRun("obj.x");
12851 CHECK(value->IsInt32());
12852 CHECK_EQ(42, value->Int32Value());
12853}
12854
12855
12856// Test that we ignore null interceptors.
12857THREADED_TEST(NullIndexedInterceptor) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012858 v8::Isolate* isolate = CcTest::isolate();
12859 v8::HandleScope scope(isolate);
12860 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012861 templ->SetIndexedPropertyHandler(
12862 static_cast<v8::IndexedPropertyGetterCallback>(0));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012863 LocalContext context;
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000012864 templ->Set(CcTest::isolate(), "42", v8_num(42));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012865 v8::Handle<v8::Object> obj = templ->NewInstance();
12866 context->Global()->Set(v8_str("obj"), obj);
12867 v8::Handle<Value> value = CompileRun("obj[42]");
12868 CHECK(value->IsInt32());
12869 CHECK_EQ(42, value->Int32Value());
12870}
12871
12872
ricow@chromium.org30ce4112010-05-31 10:38:25 +000012873THREADED_TEST(NamedPropertyHandlerGetterAttributes) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012874 v8::Isolate* isolate = CcTest::isolate();
12875 v8::HandleScope scope(isolate);
12876 v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
ricow@chromium.org30ce4112010-05-31 10:38:25 +000012877 templ->InstanceTemplate()->SetNamedPropertyHandler(InterceptorLoadXICGetter);
12878 LocalContext env;
12879 env->Global()->Set(v8_str("obj"),
12880 templ->GetFunction()->NewInstance());
12881 ExpectTrue("obj.x === 42");
12882 ExpectTrue("!obj.propertyIsEnumerable('x')");
12883}
12884
12885
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012886static void ThrowingGetter(Local<String> name,
12887 const v8::PropertyCallbackInfo<v8::Value>& info) {
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012888 ApiTestFuzzer::Fuzz();
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000012889 info.GetIsolate()->ThrowException(Handle<Value>());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012890 info.GetReturnValue().SetUndefined();
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012891}
12892
12893
12894THREADED_TEST(VariousGetPropertiesAndThrowingCallbacks) {
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012895 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000012896 HandleScope scope(context->GetIsolate());
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012897
ulan@chromium.org0f13e742014-01-03 15:51:11 +000012898 Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012899 Local<ObjectTemplate> instance_templ = templ->InstanceTemplate();
12900 instance_templ->SetAccessor(v8_str("f"), ThrowingGetter);
12901
12902 Local<Object> instance = templ->GetFunction()->NewInstance();
12903
ulan@chromium.org0f13e742014-01-03 15:51:11 +000012904 Local<Object> another = Object::New(context->GetIsolate());
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012905 another->SetPrototype(instance);
12906
12907 Local<Object> with_js_getter = CompileRun(
12908 "o = {};\n"
12909 "o.__defineGetter__('f', function() { throw undefined; });\n"
12910 "o\n").As<Object>();
12911 CHECK(!with_js_getter.IsEmpty());
12912
12913 TryCatch try_catch;
12914
12915 Local<Value> result = instance->GetRealNamedProperty(v8_str("f"));
12916 CHECK(try_catch.HasCaught());
12917 try_catch.Reset();
12918 CHECK(result.IsEmpty());
12919
12920 result = another->GetRealNamedProperty(v8_str("f"));
12921 CHECK(try_catch.HasCaught());
12922 try_catch.Reset();
12923 CHECK(result.IsEmpty());
12924
12925 result = another->GetRealNamedPropertyInPrototypeChain(v8_str("f"));
12926 CHECK(try_catch.HasCaught());
12927 try_catch.Reset();
12928 CHECK(result.IsEmpty());
12929
12930 result = another->Get(v8_str("f"));
12931 CHECK(try_catch.HasCaught());
12932 try_catch.Reset();
12933 CHECK(result.IsEmpty());
12934
12935 result = with_js_getter->GetRealNamedProperty(v8_str("f"));
12936 CHECK(try_catch.HasCaught());
12937 try_catch.Reset();
12938 CHECK(result.IsEmpty());
12939
12940 result = with_js_getter->Get(v8_str("f"));
12941 CHECK(try_catch.HasCaught());
12942 try_catch.Reset();
12943 CHECK(result.IsEmpty());
12944}
12945
12946
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012947static void ThrowingCallbackWithTryCatch(
12948 const v8::FunctionCallbackInfo<v8::Value>& args) {
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012949 TryCatch try_catch;
12950 // Verboseness is important: it triggers message delivery which can call into
12951 // external code.
12952 try_catch.SetVerbose(true);
12953 CompileRun("throw 'from JS';");
12954 CHECK(try_catch.HasCaught());
machenbach@chromium.org528ce022013-09-23 14:09:36 +000012955 CHECK(!CcTest::i_isolate()->has_pending_exception());
12956 CHECK(!CcTest::i_isolate()->has_scheduled_exception());
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012957}
12958
12959
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +000012960static int call_depth;
12961
12962
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012963static void WithTryCatch(Handle<Message> message, Handle<Value> data) {
12964 TryCatch try_catch;
12965}
12966
12967
12968static void ThrowFromJS(Handle<Message> message, Handle<Value> data) {
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +000012969 if (--call_depth) CompileRun("throw 'ThrowInJS';");
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012970}
12971
12972
12973static void ThrowViaApi(Handle<Message> message, Handle<Value> data) {
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000012974 if (--call_depth) CcTest::isolate()->ThrowException(v8_str("ThrowViaApi"));
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012975}
12976
12977
12978static void WebKitLike(Handle<Message> message, Handle<Value> data) {
12979 Handle<String> errorMessageString = message->Get();
12980 CHECK(!errorMessageString.IsEmpty());
12981 message->GetStackTrace();
12982 message->GetScriptResourceName();
12983}
12984
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012985
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012986THREADED_TEST(ExceptionsDoNotPropagatePastTryCatch) {
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012987 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012988 v8::Isolate* isolate = context->GetIsolate();
12989 HandleScope scope(isolate);
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012990
12991 Local<Function> func =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012992 FunctionTemplate::New(isolate,
12993 ThrowingCallbackWithTryCatch)->GetFunction();
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012994 context->Global()->Set(v8_str("func"), func);
12995
12996 MessageCallback callbacks[] =
12997 { NULL, WebKitLike, ThrowViaApi, ThrowFromJS, WithTryCatch };
12998 for (unsigned i = 0; i < sizeof(callbacks)/sizeof(callbacks[0]); i++) {
12999 MessageCallback callback = callbacks[i];
13000 if (callback != NULL) {
13001 V8::AddMessageListener(callback);
13002 }
ricow@chromium.orgdcebac02011-04-20 09:44:50 +000013003 // Some small number to control number of times message handler should
13004 // throw an exception.
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +000013005 call_depth = 5;
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000013006 ExpectFalse(
13007 "var thrown = false;\n"
13008 "try { func(); } catch(e) { thrown = true; }\n"
13009 "thrown\n");
13010 if (callback != NULL) {
13011 V8::RemoveMessageListeners(callback);
13012 }
13013 }
13014}
13015
13016
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013017static void ParentGetter(Local<String> name,
13018 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013019 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013020 info.GetReturnValue().Set(v8_num(1));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013021}
13022
13023
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013024static void ChildGetter(Local<String> name,
13025 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013026 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013027 info.GetReturnValue().Set(v8_num(42));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013028}
13029
13030
13031THREADED_TEST(Overriding) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +000013032 i::FLAG_es5_readonly = true;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013033 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000013034 v8::Isolate* isolate = context->GetIsolate();
13035 v8::HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013036
13037 // Parent template.
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000013038 Local<v8::FunctionTemplate> parent_templ = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013039 Local<ObjectTemplate> parent_instance_templ =
13040 parent_templ->InstanceTemplate();
13041 parent_instance_templ->SetAccessor(v8_str("f"), ParentGetter);
13042
13043 // Template that inherits from the parent template.
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000013044 Local<v8::FunctionTemplate> child_templ = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013045 Local<ObjectTemplate> child_instance_templ =
13046 child_templ->InstanceTemplate();
13047 child_templ->Inherit(parent_templ);
13048 // Override 'f'. The child version of 'f' should get called for child
13049 // instances.
13050 child_instance_templ->SetAccessor(v8_str("f"), ChildGetter);
13051 // Add 'g' twice. The 'g' added last should get called for instances.
13052 child_instance_templ->SetAccessor(v8_str("g"), ParentGetter);
13053 child_instance_templ->SetAccessor(v8_str("g"), ChildGetter);
13054
13055 // Add 'h' as an accessor to the proto template with ReadOnly attributes
13056 // so 'h' can be shadowed on the instance object.
13057 Local<ObjectTemplate> child_proto_templ = child_templ->PrototypeTemplate();
13058 child_proto_templ->SetAccessor(v8_str("h"), ParentGetter, 0,
13059 v8::Handle<Value>(), v8::DEFAULT, v8::ReadOnly);
13060
13061 // Add 'i' as an accessor to the instance template with ReadOnly attributes
13062 // but the attribute does not have effect because it is duplicated with
13063 // NULL setter.
13064 child_instance_templ->SetAccessor(v8_str("i"), ChildGetter, 0,
13065 v8::Handle<Value>(), v8::DEFAULT, v8::ReadOnly);
13066
13067
13068
13069 // Instantiate the child template.
13070 Local<v8::Object> instance = child_templ->GetFunction()->NewInstance();
13071
13072 // Check that the child function overrides the parent one.
13073 context->Global()->Set(v8_str("o"), instance);
13074 Local<Value> value = v8_compile("o.f")->Run();
13075 // Check that the 'g' that was added last is hit.
13076 CHECK_EQ(42, value->Int32Value());
13077 value = v8_compile("o.g")->Run();
13078 CHECK_EQ(42, value->Int32Value());
13079
mmassi@chromium.org7028c052012-06-13 11:51:58 +000013080 // Check that 'h' cannot be shadowed.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013081 value = v8_compile("o.h = 3; o.h")->Run();
mmassi@chromium.org7028c052012-06-13 11:51:58 +000013082 CHECK_EQ(1, value->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013083
mmassi@chromium.org7028c052012-06-13 11:51:58 +000013084 // Check that 'i' cannot be shadowed or changed.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013085 value = v8_compile("o.i = 3; o.i")->Run();
13086 CHECK_EQ(42, value->Int32Value());
13087}
13088
13089
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013090static void IsConstructHandler(
13091 const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013092 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013093 args.GetReturnValue().Set(args.IsConstructCall());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013094}
13095
13096
13097THREADED_TEST(IsConstructCall) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000013098 v8::Isolate* isolate = CcTest::isolate();
13099 v8::HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013100
13101 // Function template with call handler.
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000013102 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013103 templ->SetCallHandler(IsConstructHandler);
13104
13105 LocalContext context;
13106
13107 context->Global()->Set(v8_str("f"), templ->GetFunction());
13108 Local<Value> value = v8_compile("f()")->Run();
13109 CHECK(!value->BooleanValue());
13110 value = v8_compile("new f()")->Run();
13111 CHECK(value->BooleanValue());
13112}
13113
13114
13115THREADED_TEST(ObjectProtoToString) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000013116 v8::Isolate* isolate = CcTest::isolate();
13117 v8::HandleScope scope(isolate);
13118 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013119 templ->SetClassName(v8_str("MyClass"));
13120
13121 LocalContext context;
13122
13123 Local<String> customized_tostring = v8_str("customized toString");
13124
13125 // Replace Object.prototype.toString
13126 v8_compile("Object.prototype.toString = function() {"
13127 " return 'customized toString';"
13128 "}")->Run();
13129
13130 // Normal ToString call should call replaced Object.prototype.toString
13131 Local<v8::Object> instance = templ->GetFunction()->NewInstance();
13132 Local<String> value = instance->ToString();
13133 CHECK(value->IsString() && value->Equals(customized_tostring));
13134
13135 // ObjectProtoToString should not call replace toString function.
13136 value = instance->ObjectProtoToString();
13137 CHECK(value->IsString() && value->Equals(v8_str("[object MyClass]")));
13138
13139 // Check global
13140 value = context->Global()->ObjectProtoToString();
13141 CHECK(value->IsString() && value->Equals(v8_str("[object global]")));
13142
13143 // Check ordinary object
13144 Local<Value> object = v8_compile("new Object()")->Run();
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000013145 value = object.As<v8::Object>()->ObjectProtoToString();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013146 CHECK(value->IsString() && value->Equals(v8_str("[object Object]")));
13147}
13148
13149
ager@chromium.orgbeb25712010-11-29 08:02:25 +000013150THREADED_TEST(ObjectGetConstructorName) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +000013151 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013152 v8::HandleScope scope(context->GetIsolate());
ager@chromium.orgbeb25712010-11-29 08:02:25 +000013153 v8_compile("function Parent() {};"
13154 "function Child() {};"
13155 "Child.prototype = new Parent();"
13156 "var outer = { inner: function() { } };"
13157 "var p = new Parent();"
13158 "var c = new Child();"
13159 "var x = new outer.inner();")->Run();
13160
13161 Local<v8::Value> p = context->Global()->Get(v8_str("p"));
13162 CHECK(p->IsObject() && p->ToObject()->GetConstructorName()->Equals(
13163 v8_str("Parent")));
13164
13165 Local<v8::Value> c = context->Global()->Get(v8_str("c"));
13166 CHECK(c->IsObject() && c->ToObject()->GetConstructorName()->Equals(
13167 v8_str("Child")));
13168
13169 Local<v8::Value> x = context->Global()->Get(v8_str("x"));
13170 CHECK(x->IsObject() && x->ToObject()->GetConstructorName()->Equals(
13171 v8_str("outer.inner")));
13172}
13173
13174
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013175bool ApiTestFuzzer::fuzzing_ = false;
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000013176i::Semaphore ApiTestFuzzer::all_tests_done_(0);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013177int ApiTestFuzzer::active_tests_;
13178int ApiTestFuzzer::tests_being_run_;
13179int ApiTestFuzzer::current_;
13180
13181
13182// We are in a callback and want to switch to another thread (if we
13183// are currently running the thread fuzzing test).
13184void ApiTestFuzzer::Fuzz() {
13185 if (!fuzzing_) return;
13186 ApiTestFuzzer* test = RegisterThreadedTest::nth(current_)->fuzzer_;
13187 test->ContextSwitch();
13188}
13189
13190
13191// Let the next thread go. Since it is also waiting on the V8 lock it may
13192// not start immediately.
13193bool ApiTestFuzzer::NextThread() {
13194 int test_position = GetNextTestNumber();
ager@chromium.orgc4c92722009-11-18 14:12:51 +000013195 const char* test_name = RegisterThreadedTest::nth(current_)->name();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013196 if (test_position == current_) {
ager@chromium.orgc4c92722009-11-18 14:12:51 +000013197 if (kLogThreading)
13198 printf("Stay with %s\n", test_name);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013199 return false;
13200 }
ager@chromium.orgc4c92722009-11-18 14:12:51 +000013201 if (kLogThreading) {
13202 printf("Switch from %s to %s\n",
13203 test_name,
13204 RegisterThreadedTest::nth(test_position)->name());
13205 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013206 current_ = test_position;
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000013207 RegisterThreadedTest::nth(current_)->fuzzer_->gate_.Signal();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013208 return true;
13209}
13210
13211
13212void ApiTestFuzzer::Run() {
13213 // When it is our turn...
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000013214 gate_.Wait();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013215 {
13216 // ... get the V8 lock and start running the test.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013217 v8::Locker locker(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013218 CallTest();
13219 }
13220 // This test finished.
13221 active_ = false;
13222 active_tests_--;
13223 // If it was the last then signal that fact.
13224 if (active_tests_ == 0) {
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000013225 all_tests_done_.Signal();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013226 } else {
13227 // Otherwise select a new test and start that.
13228 NextThread();
13229 }
13230}
13231
13232
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013233static unsigned linear_congruential_generator;
13234
13235
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000013236void ApiTestFuzzer::SetUp(PartOfTest part) {
kasperl@chromium.orgb9123622008-09-17 14:05:56 +000013237 linear_congruential_generator = i::FLAG_testing_prng_seed;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013238 fuzzing_ = true;
lrn@chromium.org1c092762011-05-09 09:42:16 +000013239 int count = RegisterThreadedTest::count();
13240 int start = count * part / (LAST_PART + 1);
13241 int end = (count * (part + 1) / (LAST_PART + 1)) - 1;
13242 active_tests_ = tests_being_run_ = end - start + 1;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013243 for (int i = 0; i < tests_being_run_; i++) {
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000013244 RegisterThreadedTest::nth(i)->fuzzer_ = new ApiTestFuzzer(i + start);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013245 }
13246 for (int i = 0; i < active_tests_; i++) {
13247 RegisterThreadedTest::nth(i)->fuzzer_->Start();
13248 }
13249}
13250
13251
13252static void CallTestNumber(int test_number) {
13253 (RegisterThreadedTest::nth(test_number)->callback())();
13254}
13255
13256
13257void ApiTestFuzzer::RunAllTests() {
13258 // Set off the first test.
13259 current_ = -1;
13260 NextThread();
13261 // Wait till they are all done.
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000013262 all_tests_done_.Wait();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013263}
13264
13265
13266int ApiTestFuzzer::GetNextTestNumber() {
13267 int next_test;
13268 do {
13269 next_test = (linear_congruential_generator >> 16) % tests_being_run_;
13270 linear_congruential_generator *= 1664525u;
13271 linear_congruential_generator += 1013904223u;
13272 } while (!RegisterThreadedTest::nth(next_test)->fuzzer_->active_);
13273 return next_test;
13274}
13275
13276
13277void ApiTestFuzzer::ContextSwitch() {
13278 // If the new thread is the same as the current thread there is nothing to do.
13279 if (NextThread()) {
13280 // Now it can start.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013281 v8::Unlocker unlocker(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013282 // Wait till someone starts us again.
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000013283 gate_.Wait();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013284 // And we're off.
13285 }
13286}
13287
13288
13289void ApiTestFuzzer::TearDown() {
13290 fuzzing_ = false;
ager@chromium.org41826e72009-03-30 13:30:57 +000013291 for (int i = 0; i < RegisterThreadedTest::count(); i++) {
13292 ApiTestFuzzer *fuzzer = RegisterThreadedTest::nth(i)->fuzzer_;
13293 if (fuzzer != NULL) fuzzer->Join();
13294 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013295}
13296
13297
13298// Lets not be needlessly self-referential.
mmassi@chromium.org2f0efde2013-02-06 14:12:58 +000013299TEST(Threading1) {
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000013300 ApiTestFuzzer::SetUp(ApiTestFuzzer::FIRST_PART);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013301 ApiTestFuzzer::RunAllTests();
13302 ApiTestFuzzer::TearDown();
13303}
13304
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000013305
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013306TEST(Threading2) {
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000013307 ApiTestFuzzer::SetUp(ApiTestFuzzer::SECOND_PART);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013308 ApiTestFuzzer::RunAllTests();
13309 ApiTestFuzzer::TearDown();
13310}
13311
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000013312
lrn@chromium.org1c092762011-05-09 09:42:16 +000013313TEST(Threading3) {
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000013314 ApiTestFuzzer::SetUp(ApiTestFuzzer::THIRD_PART);
lrn@chromium.org1c092762011-05-09 09:42:16 +000013315 ApiTestFuzzer::RunAllTests();
13316 ApiTestFuzzer::TearDown();
13317}
13318
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000013319
lrn@chromium.org1c092762011-05-09 09:42:16 +000013320TEST(Threading4) {
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000013321 ApiTestFuzzer::SetUp(ApiTestFuzzer::FOURTH_PART);
lrn@chromium.org1c092762011-05-09 09:42:16 +000013322 ApiTestFuzzer::RunAllTests();
13323 ApiTestFuzzer::TearDown();
13324}
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013325
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000013326
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013327void ApiTestFuzzer::CallTest() {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013328 v8::Isolate::Scope scope(CcTest::isolate());
ager@chromium.orgc4c92722009-11-18 14:12:51 +000013329 if (kLogThreading)
13330 printf("Start test %d\n", test_number_);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013331 CallTestNumber(test_number_);
ager@chromium.orgc4c92722009-11-18 14:12:51 +000013332 if (kLogThreading)
13333 printf("End test %d\n", test_number_);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013334}
13335
13336
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013337static void ThrowInJS(const v8::FunctionCallbackInfo<v8::Value>& args) {
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000013338 v8::Isolate* isolate = args.GetIsolate();
13339 CHECK(v8::Locker::IsLocked(isolate));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013340 ApiTestFuzzer::Fuzz();
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000013341 v8::Unlocker unlocker(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013342 const char* code = "throw 7;";
13343 {
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000013344 v8::Locker nested_locker(isolate);
13345 v8::HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013346 v8::Handle<Value> exception;
13347 { v8::TryCatch try_catch;
13348 v8::Handle<Value> value = CompileRun(code);
13349 CHECK(value.IsEmpty());
13350 CHECK(try_catch.HasCaught());
13351 // Make sure to wrap the exception in a new handle because
13352 // the handle returned from the TryCatch is destroyed
13353 // when the TryCatch is destroyed.
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000013354 exception = Local<Value>::New(isolate, try_catch.Exception());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013355 }
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000013356 args.GetIsolate()->ThrowException(exception);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013357 }
13358}
13359
13360
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013361static void ThrowInJSNoCatch(const v8::FunctionCallbackInfo<v8::Value>& args) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013362 CHECK(v8::Locker::IsLocked(CcTest::isolate()));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013363 ApiTestFuzzer::Fuzz();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013364 v8::Unlocker unlocker(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013365 const char* code = "throw 7;";
13366 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013367 v8::Locker nested_locker(CcTest::isolate());
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013368 v8::HandleScope scope(args.GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013369 v8::Handle<Value> value = CompileRun(code);
13370 CHECK(value.IsEmpty());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013371 args.GetReturnValue().Set(v8_str("foo"));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013372 }
13373}
13374
13375
13376// These are locking tests that don't need to be run again
13377// as part of the locking aggregation tests.
13378TEST(NestedLockers) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000013379 v8::Isolate* isolate = CcTest::isolate();
13380 v8::Locker locker(isolate);
13381 CHECK(v8::Locker::IsLocked(isolate));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013382 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013383 v8::HandleScope scope(env->GetIsolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000013384 Local<v8::FunctionTemplate> fun_templ =
13385 v8::FunctionTemplate::New(isolate, ThrowInJS);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013386 Local<Function> fun = fun_templ->GetFunction();
13387 env->Global()->Set(v8_str("throw_in_js"), fun);
13388 Local<Script> script = v8_compile("(function () {"
13389 " try {"
13390 " throw_in_js();"
13391 " return 42;"
13392 " } catch (e) {"
13393 " return e * 13;"
13394 " }"
13395 "})();");
13396 CHECK_EQ(91, script->Run()->Int32Value());
13397}
13398
13399
13400// These are locking tests that don't need to be run again
13401// as part of the locking aggregation tests.
13402TEST(NestedLockersNoTryCatch) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013403 v8::Locker locker(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013404 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013405 v8::HandleScope scope(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013406 Local<v8::FunctionTemplate> fun_templ =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000013407 v8::FunctionTemplate::New(env->GetIsolate(), ThrowInJSNoCatch);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013408 Local<Function> fun = fun_templ->GetFunction();
13409 env->Global()->Set(v8_str("throw_in_js"), fun);
13410 Local<Script> script = v8_compile("(function () {"
13411 " try {"
13412 " throw_in_js();"
13413 " return 42;"
13414 " } catch (e) {"
13415 " return e * 13;"
13416 " }"
13417 "})();");
13418 CHECK_EQ(91, script->Run()->Int32Value());
13419}
13420
13421
13422THREADED_TEST(RecursiveLocking) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013423 v8::Locker locker(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013424 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013425 v8::Locker locker2(CcTest::isolate());
13426 CHECK(v8::Locker::IsLocked(CcTest::isolate()));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013427 }
13428}
13429
13430
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013431static void UnlockForAMoment(const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013432 ApiTestFuzzer::Fuzz();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013433 v8::Unlocker unlocker(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013434}
13435
13436
13437THREADED_TEST(LockUnlockLock) {
13438 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013439 v8::Locker locker(CcTest::isolate());
13440 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013441 LocalContext env;
13442 Local<v8::FunctionTemplate> fun_templ =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000013443 v8::FunctionTemplate::New(CcTest::isolate(), UnlockForAMoment);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013444 Local<Function> fun = fun_templ->GetFunction();
13445 env->Global()->Set(v8_str("unlock_for_a_moment"), fun);
13446 Local<Script> script = v8_compile("(function () {"
13447 " unlock_for_a_moment();"
13448 " return 42;"
13449 "})();");
13450 CHECK_EQ(42, script->Run()->Int32Value());
13451 }
13452 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013453 v8::Locker locker(CcTest::isolate());
13454 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013455 LocalContext env;
13456 Local<v8::FunctionTemplate> fun_templ =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000013457 v8::FunctionTemplate::New(CcTest::isolate(), UnlockForAMoment);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013458 Local<Function> fun = fun_templ->GetFunction();
13459 env->Global()->Set(v8_str("unlock_for_a_moment"), fun);
13460 Local<Script> script = v8_compile("(function () {"
13461 " unlock_for_a_moment();"
13462 " return 42;"
13463 "})();");
13464 CHECK_EQ(42, script->Run()->Int32Value());
13465 }
13466}
13467
13468
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000013469static int GetGlobalObjectsCount() {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013470 CcTest::heap()->EnsureHeapIsIterable();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013471 int count = 0;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013472 i::HeapIterator it(CcTest::heap());
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000013473 for (i::HeapObject* object = it.next(); object != NULL; object = it.next())
13474 if (object->IsJSGlobalObject()) count++;
13475 return count;
13476}
13477
13478
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000013479static void CheckSurvivingGlobalObjectsCount(int expected) {
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +000013480 // We need to collect all garbage twice to be sure that everything
13481 // has been collected. This is because inline caches are cleared in
13482 // the first garbage collection but some of the maps have already
13483 // been marked at that point. Therefore some of the maps are not
13484 // collected until the second garbage collection.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013485 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
13486 CcTest::heap()->CollectAllGarbage(i::Heap::kMakeHeapIterableMask);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000013487 int count = GetGlobalObjectsCount();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013488#ifdef DEBUG
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013489 if (count != expected) CcTest::heap()->TracePathToGlobal();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013490#endif
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000013491 CHECK_EQ(expected, count);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013492}
13493
13494
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013495TEST(DontLeakGlobalObjects) {
13496 // Regression test for issues 1139850 and 1174891.
13497
machenbach@chromium.orgc8cbc432014-01-21 09:01:57 +000013498 i::FLAG_expose_gc = true;
kasperl@chromium.orgb9123622008-09-17 14:05:56 +000013499 v8::V8::Initialize();
ager@chromium.org9258b6b2008-09-11 09:11:10 +000013500
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013501 for (int i = 0; i < 5; i++) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013502 { v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013503 LocalContext context;
13504 }
svenpanne@chromium.orgc859c4f2012-10-15 11:51:39 +000013505 v8::V8::ContextDisposedNotification();
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000013506 CheckSurvivingGlobalObjectsCount(0);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013507
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013508 { v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013509 LocalContext context;
13510 v8_compile("Date")->Run();
13511 }
svenpanne@chromium.orgc859c4f2012-10-15 11:51:39 +000013512 v8::V8::ContextDisposedNotification();
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000013513 CheckSurvivingGlobalObjectsCount(0);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013514
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013515 { v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013516 LocalContext context;
13517 v8_compile("/aaa/")->Run();
13518 }
svenpanne@chromium.orgc859c4f2012-10-15 11:51:39 +000013519 v8::V8::ContextDisposedNotification();
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000013520 CheckSurvivingGlobalObjectsCount(0);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013521
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013522 { v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013523 const char* extension_list[] = { "v8/gc" };
13524 v8::ExtensionConfiguration extensions(1, extension_list);
13525 LocalContext context(&extensions);
13526 v8_compile("gc();")->Run();
13527 }
svenpanne@chromium.orgc859c4f2012-10-15 11:51:39 +000013528 v8::V8::ContextDisposedNotification();
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000013529 CheckSurvivingGlobalObjectsCount(0);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013530 }
13531}
13532
dslomov@chromium.org639bac02013-09-09 11:58:54 +000013533
13534TEST(CopyablePersistent) {
13535 LocalContext context;
13536 v8::Isolate* isolate = context->GetIsolate();
13537 i::GlobalHandles* globals =
13538 reinterpret_cast<i::Isolate*>(isolate)->global_handles();
13539 int initial_handles = globals->global_handles_count();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013540 typedef v8::Persistent<v8::Object, v8::CopyablePersistentTraits<v8::Object> >
13541 CopyableObject;
dslomov@chromium.org639bac02013-09-09 11:58:54 +000013542 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013543 CopyableObject handle1;
dslomov@chromium.org639bac02013-09-09 11:58:54 +000013544 {
13545 v8::HandleScope scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000013546 handle1.Reset(isolate, v8::Object::New(isolate));
dslomov@chromium.org639bac02013-09-09 11:58:54 +000013547 }
13548 CHECK_EQ(initial_handles + 1, globals->global_handles_count());
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013549 CopyableObject handle2;
dslomov@chromium.org639bac02013-09-09 11:58:54 +000013550 handle2 = handle1;
13551 CHECK(handle1 == handle2);
13552 CHECK_EQ(initial_handles + 2, globals->global_handles_count());
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013553 CopyableObject handle3(handle2);
dslomov@chromium.org639bac02013-09-09 11:58:54 +000013554 CHECK(handle1 == handle3);
13555 CHECK_EQ(initial_handles + 3, globals->global_handles_count());
13556 }
13557 // Verify autodispose
hpayer@chromium.orgc5d49712013-09-11 08:25:48 +000013558 CHECK_EQ(initial_handles, globals->global_handles_count());
dslomov@chromium.org639bac02013-09-09 11:58:54 +000013559}
13560
13561
13562static void WeakApiCallback(
13563 const v8::WeakCallbackData<v8::Object, Persistent<v8::Object> >& data) {
13564 Local<Value> value = data.GetValue()->Get(v8_str("key"));
13565 CHECK_EQ(231, static_cast<int32_t>(Local<v8::Integer>::Cast(value)->Value()));
13566 data.GetParameter()->Reset();
13567 delete data.GetParameter();
13568}
13569
13570
13571TEST(WeakCallbackApi) {
13572 LocalContext context;
13573 v8::Isolate* isolate = context->GetIsolate();
13574 i::GlobalHandles* globals =
13575 reinterpret_cast<i::Isolate*>(isolate)->global_handles();
13576 int initial_handles = globals->global_handles_count();
13577 {
13578 v8::HandleScope scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000013579 v8::Local<v8::Object> obj = v8::Object::New(isolate);
13580 obj->Set(v8_str("key"), v8::Integer::New(isolate, 231));
dslomov@chromium.org639bac02013-09-09 11:58:54 +000013581 v8::Persistent<v8::Object>* handle =
13582 new v8::Persistent<v8::Object>(isolate, obj);
13583 handle->SetWeak<v8::Object, v8::Persistent<v8::Object> >(handle,
13584 WeakApiCallback);
13585 }
13586 reinterpret_cast<i::Isolate*>(isolate)->heap()->
13587 CollectAllGarbage(i::Heap::kNoGCFlags);
13588 // Verify disposed.
13589 CHECK_EQ(initial_handles, globals->global_handles_count());
13590}
13591
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013592
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000013593v8::Persistent<v8::Object> some_object;
13594v8::Persistent<v8::Object> bad_handle;
13595
machenbach@chromium.orgddf38112013-12-04 09:42:52 +000013596void NewPersistentHandleCallback(
13597 const v8::WeakCallbackData<v8::Object, v8::Persistent<v8::Object> >& data) {
13598 v8::HandleScope scope(data.GetIsolate());
13599 bad_handle.Reset(data.GetIsolate(), some_object);
13600 data.GetParameter()->Reset();
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000013601}
13602
13603
13604THREADED_TEST(NewPersistentHandleFromWeakCallback) {
13605 LocalContext context;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000013606 v8::Isolate* isolate = context->GetIsolate();
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000013607
13608 v8::Persistent<v8::Object> handle1, handle2;
13609 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013610 v8::HandleScope scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000013611 some_object.Reset(isolate, v8::Object::New(isolate));
13612 handle1.Reset(isolate, v8::Object::New(isolate));
13613 handle2.Reset(isolate, v8::Object::New(isolate));
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000013614 }
13615 // Note: order is implementation dependent alas: currently
13616 // global handle nodes are processed by PostGarbageCollectionProcessing
13617 // in reverse allocation order, so if second allocated handle is deleted,
13618 // weak callback of the first handle would be able to 'reallocate' it.
machenbach@chromium.orgddf38112013-12-04 09:42:52 +000013619 handle1.SetWeak(&handle1, NewPersistentHandleCallback);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000013620 handle2.Reset();
machenbach@chromium.orgddf38112013-12-04 09:42:52 +000013621 CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000013622}
13623
13624
13625v8::Persistent<v8::Object> to_be_disposed;
13626
machenbach@chromium.orgddf38112013-12-04 09:42:52 +000013627void DisposeAndForceGcCallback(
13628 const v8::WeakCallbackData<v8::Object, v8::Persistent<v8::Object> >& data) {
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000013629 to_be_disposed.Reset();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013630 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
machenbach@chromium.orgddf38112013-12-04 09:42:52 +000013631 data.GetParameter()->Reset();
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000013632}
13633
13634
13635THREADED_TEST(DoNotUseDeletedNodesInSecondLevelGc) {
13636 LocalContext context;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000013637 v8::Isolate* isolate = context->GetIsolate();
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000013638
13639 v8::Persistent<v8::Object> handle1, handle2;
13640 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013641 v8::HandleScope scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000013642 handle1.Reset(isolate, v8::Object::New(isolate));
13643 handle2.Reset(isolate, v8::Object::New(isolate));
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000013644 }
machenbach@chromium.orgddf38112013-12-04 09:42:52 +000013645 handle1.SetWeak(&handle1, DisposeAndForceGcCallback);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000013646 to_be_disposed.Reset(isolate, handle2);
machenbach@chromium.orgddf38112013-12-04 09:42:52 +000013647 CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000013648}
13649
machenbach@chromium.orgddf38112013-12-04 09:42:52 +000013650void DisposingCallback(
13651 const v8::WeakCallbackData<v8::Object, v8::Persistent<v8::Object> >& data) {
13652 data.GetParameter()->Reset();
ager@chromium.orgc4c92722009-11-18 14:12:51 +000013653}
13654
machenbach@chromium.orgddf38112013-12-04 09:42:52 +000013655void HandleCreatingCallback(
13656 const v8::WeakCallbackData<v8::Object, v8::Persistent<v8::Object> >& data) {
13657 v8::HandleScope scope(data.GetIsolate());
ulan@chromium.org0f13e742014-01-03 15:51:11 +000013658 v8::Persistent<v8::Object>(data.GetIsolate(),
13659 v8::Object::New(data.GetIsolate()));
machenbach@chromium.orgddf38112013-12-04 09:42:52 +000013660 data.GetParameter()->Reset();
ager@chromium.orgc4c92722009-11-18 14:12:51 +000013661}
13662
13663
13664THREADED_TEST(NoGlobalHandlesOrphaningDueToWeakCallback) {
13665 LocalContext context;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000013666 v8::Isolate* isolate = context->GetIsolate();
ager@chromium.orgc4c92722009-11-18 14:12:51 +000013667
13668 v8::Persistent<v8::Object> handle1, handle2, handle3;
13669 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013670 v8::HandleScope scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000013671 handle3.Reset(isolate, v8::Object::New(isolate));
13672 handle2.Reset(isolate, v8::Object::New(isolate));
13673 handle1.Reset(isolate, v8::Object::New(isolate));
ager@chromium.orgc4c92722009-11-18 14:12:51 +000013674 }
machenbach@chromium.orgddf38112013-12-04 09:42:52 +000013675 handle2.SetWeak(&handle2, DisposingCallback);
13676 handle3.SetWeak(&handle3, HandleCreatingCallback);
13677 CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
ager@chromium.orgc4c92722009-11-18 14:12:51 +000013678}
13679
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000013680
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013681THREADED_TEST(CheckForCrossContextObjectLiterals) {
kasperl@chromium.orgb9123622008-09-17 14:05:56 +000013682 v8::V8::Initialize();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013683
13684 const int nof = 2;
13685 const char* sources[nof] = {
13686 "try { [ 2, 3, 4 ].forEach(5); } catch(e) { e.toString(); }",
13687 "Object()"
13688 };
13689
13690 for (int i = 0; i < nof; i++) {
13691 const char* source = sources[i];
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013692 { v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013693 LocalContext context;
13694 CompileRun(source);
13695 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013696 { v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013697 LocalContext context;
13698 CompileRun(source);
13699 }
13700 }
13701}
13702
13703
ulan@chromium.org57ff8812013-05-10 08:16:55 +000013704static v8::Handle<Value> NestedScope(v8::Local<Context> env) {
machenbach@chromium.orgafbdadc2013-12-09 16:12:18 +000013705 v8::EscapableHandleScope inner(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013706 env->Enter();
machenbach@chromium.orgafbdadc2013-12-09 16:12:18 +000013707 v8::Local<Value> three = v8_num(3);
13708 v8::Local<Value> value = inner.Escape(three);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013709 env->Exit();
13710 return value;
13711}
13712
13713
13714THREADED_TEST(NestedHandleScopeAndContexts) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013715 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000013716 v8::HandleScope outer(isolate);
13717 v8::Local<Context> env = Context::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013718 env->Enter();
13719 v8::Handle<Value> value = NestedScope(env);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000013720 v8::Handle<String> str(value->ToString());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000013721 CHECK(!str.IsEmpty());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013722 env->Exit();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013723}
13724
13725
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013726static bool MatchPointers(void* key1, void* key2) {
13727 return key1 == key2;
13728}
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013729
13730
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013731struct SymbolInfo {
13732 size_t id;
13733 size_t size;
13734 std::string name;
13735};
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013736
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013737
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013738class SetFunctionEntryHookTest {
13739 public:
13740 SetFunctionEntryHookTest() {
13741 CHECK(instance_ == NULL);
13742 instance_ = this;
13743 }
13744 ~SetFunctionEntryHookTest() {
13745 CHECK(instance_ == this);
13746 instance_ = NULL;
13747 }
13748 void Reset() {
13749 symbols_.clear();
13750 symbol_locations_.clear();
13751 invocations_.clear();
13752 }
13753 void RunTest();
13754 void OnJitEvent(const v8::JitCodeEvent* event);
13755 static void JitEvent(const v8::JitCodeEvent* event) {
13756 CHECK(instance_ != NULL);
13757 instance_->OnJitEvent(event);
13758 }
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013759
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013760 void OnEntryHook(uintptr_t function,
13761 uintptr_t return_addr_location);
13762 static void EntryHook(uintptr_t function,
13763 uintptr_t return_addr_location) {
13764 CHECK(instance_ != NULL);
13765 instance_->OnEntryHook(function, return_addr_location);
13766 }
ulan@chromium.orgdfe53072013-06-06 14:14:51 +000013767
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013768 static void RuntimeCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
13769 CHECK(instance_ != NULL);
13770 args.GetReturnValue().Set(v8_num(42));
13771 }
13772 void RunLoopInNewEnv(v8::Isolate* isolate);
13773
13774 // Records addr as location of symbol.
13775 void InsertSymbolAt(i::Address addr, SymbolInfo* symbol);
13776
13777 // Finds the symbol containing addr
13778 SymbolInfo* FindSymbolForAddr(i::Address addr);
13779 // Returns the number of invocations where the caller name contains
13780 // \p caller_name and the function name contains \p function_name.
13781 int CountInvocations(const char* caller_name,
13782 const char* function_name);
13783
13784 i::Handle<i::JSFunction> foo_func_;
13785 i::Handle<i::JSFunction> bar_func_;
13786
13787 typedef std::map<size_t, SymbolInfo> SymbolMap;
13788 typedef std::map<i::Address, SymbolInfo*> SymbolLocationMap;
13789 typedef std::map<std::pair<SymbolInfo*, SymbolInfo*>, int> InvocationMap;
13790 SymbolMap symbols_;
13791 SymbolLocationMap symbol_locations_;
13792 InvocationMap invocations_;
13793
13794 static SetFunctionEntryHookTest* instance_;
13795};
13796SetFunctionEntryHookTest* SetFunctionEntryHookTest::instance_ = NULL;
13797
13798
13799// Returns true if addr is in the range [start, start+len).
13800static bool Overlaps(i::Address start, size_t len, i::Address addr) {
13801 if (start <= addr && start + len > addr)
13802 return true;
13803
13804 return false;
13805}
13806
13807void SetFunctionEntryHookTest::InsertSymbolAt(i::Address addr,
13808 SymbolInfo* symbol) {
13809 // Insert the symbol at the new location.
13810 SymbolLocationMap::iterator it =
13811 symbol_locations_.insert(std::make_pair(addr, symbol)).first;
13812 // Now erase symbols to the left and right that overlap this one.
13813 while (it != symbol_locations_.begin()) {
13814 SymbolLocationMap::iterator left = it;
13815 --left;
13816 if (!Overlaps(left->first, left->second->size, addr))
13817 break;
13818 symbol_locations_.erase(left);
13819 }
13820
13821 // Now erase symbols to the left and right that overlap this one.
13822 while (true) {
13823 SymbolLocationMap::iterator right = it;
13824 ++right;
13825 if (right == symbol_locations_.end())
13826 break;
13827 if (!Overlaps(addr, symbol->size, right->first))
13828 break;
13829 symbol_locations_.erase(right);
ulan@chromium.orgdfe53072013-06-06 14:14:51 +000013830 }
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013831}
13832
13833
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013834void SetFunctionEntryHookTest::OnJitEvent(const v8::JitCodeEvent* event) {
13835 switch (event->type) {
13836 case v8::JitCodeEvent::CODE_ADDED: {
13837 CHECK(event->code_start != NULL);
13838 CHECK_NE(0, static_cast<int>(event->code_len));
13839 CHECK(event->name.str != NULL);
13840 size_t symbol_id = symbols_.size();
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013841
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013842 // Record the new symbol.
13843 SymbolInfo& info = symbols_[symbol_id];
13844 info.id = symbol_id;
13845 info.size = event->code_len;
13846 info.name.assign(event->name.str, event->name.str + event->name.len);
13847
13848 // And record it's location.
13849 InsertSymbolAt(reinterpret_cast<i::Address>(event->code_start), &info);
13850 }
13851 break;
13852
13853 case v8::JitCodeEvent::CODE_MOVED: {
13854 // We would like to never see code move that we haven't seen before,
13855 // but the code creation event does not happen until the line endings
13856 // have been calculated (this is so that we can report the line in the
13857 // script at which the function source is found, see
13858 // Compiler::RecordFunctionCompilation) and the line endings
13859 // calculations can cause a GC, which can move the newly created code
13860 // before its existence can be logged.
13861 SymbolLocationMap::iterator it(
13862 symbol_locations_.find(
13863 reinterpret_cast<i::Address>(event->code_start)));
13864 if (it != symbol_locations_.end()) {
13865 // Found a symbol at this location, move it.
13866 SymbolInfo* info = it->second;
13867 symbol_locations_.erase(it);
13868 InsertSymbolAt(reinterpret_cast<i::Address>(event->new_code_start),
13869 info);
13870 }
13871 }
13872 default:
13873 break;
13874 }
13875}
13876
13877void SetFunctionEntryHookTest::OnEntryHook(
13878 uintptr_t function, uintptr_t return_addr_location) {
13879 // Get the function's code object.
13880 i::Code* function_code = i::Code::GetCodeFromTargetAddress(
13881 reinterpret_cast<i::Address>(function));
13882 CHECK(function_code != NULL);
13883
13884 // Then try and look up the caller's code object.
13885 i::Address caller = *reinterpret_cast<i::Address*>(return_addr_location);
13886
13887 // Count the invocation.
13888 SymbolInfo* caller_symbol = FindSymbolForAddr(caller);
13889 SymbolInfo* function_symbol =
13890 FindSymbolForAddr(reinterpret_cast<i::Address>(function));
13891 ++invocations_[std::make_pair(caller_symbol, function_symbol)];
13892
13893 if (!bar_func_.is_null() && function_code == bar_func_->code()) {
13894 // Check that we have a symbol for the "bar" function at the right location.
13895 SymbolLocationMap::iterator it(
13896 symbol_locations_.find(function_code->instruction_start()));
13897 CHECK(it != symbol_locations_.end());
13898 }
13899
13900 if (!foo_func_.is_null() && function_code == foo_func_->code()) {
13901 // Check that we have a symbol for "foo" at the right location.
13902 SymbolLocationMap::iterator it(
13903 symbol_locations_.find(function_code->instruction_start()));
13904 CHECK(it != symbol_locations_.end());
13905 }
13906}
13907
13908
13909SymbolInfo* SetFunctionEntryHookTest::FindSymbolForAddr(i::Address addr) {
13910 SymbolLocationMap::iterator it(symbol_locations_.lower_bound(addr));
13911 // Do we have a direct hit on a symbol?
13912 if (it != symbol_locations_.end()) {
13913 if (it->first == addr)
13914 return it->second;
13915 }
13916
13917 // If not a direct hit, it'll have to be the previous symbol.
13918 if (it == symbol_locations_.begin())
13919 return NULL;
13920
13921 --it;
13922 size_t offs = addr - it->first;
13923 if (offs < it->second->size)
13924 return it->second;
13925
13926 return NULL;
13927}
13928
13929
13930int SetFunctionEntryHookTest::CountInvocations(
13931 const char* caller_name, const char* function_name) {
13932 InvocationMap::iterator it(invocations_.begin());
13933 int invocations = 0;
13934 for (; it != invocations_.end(); ++it) {
13935 SymbolInfo* caller = it->first.first;
13936 SymbolInfo* function = it->first.second;
13937
13938 // Filter out non-matching functions.
13939 if (function_name != NULL) {
13940 if (function->name.find(function_name) == std::string::npos)
13941 continue;
13942 }
13943
13944 // Filter out non-matching callers.
13945 if (caller_name != NULL) {
13946 if (caller == NULL)
13947 continue;
13948 if (caller->name.find(caller_name) == std::string::npos)
13949 continue;
13950 }
13951
13952 // It matches add the invocation count to the tally.
13953 invocations += it->second;
13954 }
13955
13956 return invocations;
13957}
13958
13959
13960void SetFunctionEntryHookTest::RunLoopInNewEnv(v8::Isolate* isolate) {
ulan@chromium.org57ff8812013-05-10 08:16:55 +000013961 v8::HandleScope outer(isolate);
13962 v8::Local<Context> env = Context::New(isolate);
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013963 env->Enter();
13964
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000013965 Local<ObjectTemplate> t = ObjectTemplate::New(isolate);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000013966 t->Set(v8_str("asdf"), v8::FunctionTemplate::New(isolate, RuntimeCallback));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013967 env->Global()->Set(v8_str("obj"), t->NewInstance());
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013968
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013969 const char* script =
13970 "function bar() {\n"
13971 " var sum = 0;\n"
13972 " for (i = 0; i < 100; ++i)\n"
13973 " sum = foo(i);\n"
13974 " return sum;\n"
13975 "}\n"
13976 "function foo(i) { return i * i; }\n"
13977 "// Invoke on the runtime function.\n"
13978 "obj.asdf()";
13979 CompileRun(script);
13980 bar_func_ = i::Handle<i::JSFunction>::cast(
13981 v8::Utils::OpenHandle(*env->Global()->Get(v8_str("bar"))));
13982 ASSERT(!bar_func_.is_null());
13983
13984 foo_func_ =
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013985 i::Handle<i::JSFunction>::cast(
13986 v8::Utils::OpenHandle(*env->Global()->Get(v8_str("foo"))));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013987 ASSERT(!foo_func_.is_null());
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013988
13989 v8::Handle<v8::Value> value = CompileRun("bar();");
13990 CHECK(value->IsNumber());
13991 CHECK_EQ(9801.0, v8::Number::Cast(*value)->Value());
13992
13993 // Test the optimized codegen path.
13994 value = CompileRun("%OptimizeFunctionOnNextCall(foo);"
13995 "bar();");
13996 CHECK(value->IsNumber());
13997 CHECK_EQ(9801.0, v8::Number::Cast(*value)->Value());
13998
13999 env->Exit();
14000}
14001
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000014002
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000014003void SetFunctionEntryHookTest::RunTest() {
14004 // Work in a new isolate throughout.
14005 v8::Isolate* isolate = v8::Isolate::New();
14006
14007 // Test setting the entry hook on the new isolate.
14008 CHECK(v8::V8::SetFunctionEntryHook(isolate, EntryHook));
14009
14010 // Replacing the hook, once set should fail.
14011 CHECK_EQ(false, v8::V8::SetFunctionEntryHook(isolate, EntryHook));
14012
14013 {
14014 v8::Isolate::Scope scope(isolate);
14015
14016 v8::V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault, JitEvent);
14017
14018 RunLoopInNewEnv(isolate);
14019
14020 // Check the exepected invocation counts.
14021 CHECK_EQ(2, CountInvocations(NULL, "bar"));
14022 CHECK_EQ(200, CountInvocations("bar", "foo"));
14023 CHECK_EQ(200, CountInvocations(NULL, "foo"));
14024
14025 // Verify that we have an entry hook on some specific stubs.
14026 CHECK_NE(0, CountInvocations(NULL, "CEntryStub"));
14027 CHECK_NE(0, CountInvocations(NULL, "JSEntryStub"));
14028 CHECK_NE(0, CountInvocations(NULL, "JSEntryTrampoline"));
14029 }
14030 isolate->Dispose();
14031
14032 Reset();
14033
14034 // Make sure a second isolate is unaffected by the previous entry hook.
14035 isolate = v8::Isolate::New();
14036 {
14037 v8::Isolate::Scope scope(isolate);
14038
14039 // Reset the entry count to zero and set the entry hook.
14040 RunLoopInNewEnv(isolate);
14041
14042 // We should record no invocations in this isolate.
14043 CHECK_EQ(0, static_cast<int>(invocations_.size()));
14044 }
14045 // Since the isolate has been used, we shouldn't be able to set an entry
14046 // hook anymore.
14047 CHECK_EQ(false, v8::V8::SetFunctionEntryHook(isolate, EntryHook));
14048
14049 isolate->Dispose();
14050}
14051
verwaest@chromium.org753aee42012-07-17 16:15:42 +000014052
14053TEST(SetFunctionEntryHook) {
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000014054 // FunctionEntryHook does not work well with experimental natives.
14055 // Experimental natives are compiled during snapshot deserialization.
14056 // This test breaks because InstallGetter (function from snapshot that
14057 // only gets called from experimental natives) is compiled with entry hooks.
verwaest@chromium.org753aee42012-07-17 16:15:42 +000014058 i::FLAG_allow_natives_syntax = true;
yangguo@chromium.orgfb377212012-11-16 14:43:43 +000014059 i::FLAG_use_inlining = false;
verwaest@chromium.org753aee42012-07-17 16:15:42 +000014060
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000014061 SetFunctionEntryHookTest test;
14062 test.RunTest();
verwaest@chromium.org753aee42012-07-17 16:15:42 +000014063}
14064
14065
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014066static i::HashMap* code_map = NULL;
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +000014067static i::HashMap* jitcode_line_info = NULL;
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014068static int saw_bar = 0;
14069static int move_events = 0;
14070
14071
14072static bool FunctionNameIs(const char* expected,
14073 const v8::JitCodeEvent* event) {
14074 // Log lines for functions are of the general form:
14075 // "LazyCompile:<type><function_name>", where the type is one of
14076 // "*", "~" or "".
14077 static const char kPreamble[] = "LazyCompile:";
14078 static size_t kPreambleLen = sizeof(kPreamble) - 1;
14079
14080 if (event->name.len < sizeof(kPreamble) - 1 ||
14081 strncmp(kPreamble, event->name.str, kPreambleLen) != 0) {
14082 return false;
14083 }
14084
14085 const char* tail = event->name.str + kPreambleLen;
14086 size_t tail_len = event->name.len - kPreambleLen;
14087 size_t expected_len = strlen(expected);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000014088 if (tail_len > 1 && (*tail == '*' || *tail == '~')) {
14089 --tail_len;
14090 ++tail;
14091 }
14092
14093 // Check for tails like 'bar :1'.
14094 if (tail_len > expected_len + 2 &&
14095 tail[expected_len] == ' ' &&
14096 tail[expected_len + 1] == ':' &&
14097 tail[expected_len + 2] &&
14098 !strncmp(tail, expected, expected_len)) {
14099 return true;
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014100 }
14101
14102 if (tail_len != expected_len)
14103 return false;
14104
14105 return strncmp(tail, expected, expected_len) == 0;
14106}
14107
14108
14109static void event_handler(const v8::JitCodeEvent* event) {
14110 CHECK(event != NULL);
14111 CHECK(code_map != NULL);
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +000014112 CHECK(jitcode_line_info != NULL);
14113
14114 class DummyJitCodeLineInfo {
14115 };
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014116
14117 switch (event->type) {
14118 case v8::JitCodeEvent::CODE_ADDED: {
14119 CHECK(event->code_start != NULL);
14120 CHECK_NE(0, static_cast<int>(event->code_len));
14121 CHECK(event->name.str != NULL);
14122 i::HashMap::Entry* entry =
14123 code_map->Lookup(event->code_start,
14124 i::ComputePointerHash(event->code_start),
14125 true);
14126 entry->value = reinterpret_cast<void*>(event->code_len);
14127
14128 if (FunctionNameIs("bar", event)) {
14129 ++saw_bar;
14130 }
14131 }
14132 break;
14133
14134 case v8::JitCodeEvent::CODE_MOVED: {
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014135 uint32_t hash = i::ComputePointerHash(event->code_start);
jkummerow@chromium.org78502a92012-09-06 13:50:42 +000014136 // We would like to never see code move that we haven't seen before,
14137 // but the code creation event does not happen until the line endings
14138 // have been calculated (this is so that we can report the line in the
14139 // script at which the function source is found, see
14140 // Compiler::RecordFunctionCompilation) and the line endings
14141 // calculations can cause a GC, which can move the newly created code
14142 // before its existence can be logged.
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014143 i::HashMap::Entry* entry =
14144 code_map->Lookup(event->code_start, hash, false);
jkummerow@chromium.org78502a92012-09-06 13:50:42 +000014145 if (entry != NULL) {
14146 ++move_events;
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014147
jkummerow@chromium.org78502a92012-09-06 13:50:42 +000014148 CHECK_EQ(reinterpret_cast<void*>(event->code_len), entry->value);
14149 code_map->Remove(event->code_start, hash);
14150
14151 entry = code_map->Lookup(event->new_code_start,
14152 i::ComputePointerHash(event->new_code_start),
14153 true);
14154 CHECK(entry != NULL);
14155 entry->value = reinterpret_cast<void*>(event->code_len);
14156 }
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014157 }
14158 break;
14159
14160 case v8::JitCodeEvent::CODE_REMOVED:
14161 // Object/code removal events are currently not dispatched from the GC.
14162 CHECK(false);
14163 break;
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +000014164
14165 // For CODE_START_LINE_INFO_RECORDING event, we will create one
14166 // DummyJitCodeLineInfo data structure pointed by event->user_dat. We
14167 // record it in jitcode_line_info.
14168 case v8::JitCodeEvent::CODE_START_LINE_INFO_RECORDING: {
14169 DummyJitCodeLineInfo* line_info = new DummyJitCodeLineInfo();
14170 v8::JitCodeEvent* temp_event = const_cast<v8::JitCodeEvent*>(event);
14171 temp_event->user_data = line_info;
14172 i::HashMap::Entry* entry =
14173 jitcode_line_info->Lookup(line_info,
14174 i::ComputePointerHash(line_info),
14175 true);
14176 entry->value = reinterpret_cast<void*>(line_info);
14177 }
14178 break;
14179 // For these two events, we will check whether the event->user_data
14180 // data structure is created before during CODE_START_LINE_INFO_RECORDING
14181 // event. And delete it in CODE_END_LINE_INFO_RECORDING event handling.
14182 case v8::JitCodeEvent::CODE_END_LINE_INFO_RECORDING: {
14183 CHECK(event->user_data != NULL);
14184 uint32_t hash = i::ComputePointerHash(event->user_data);
14185 i::HashMap::Entry* entry =
14186 jitcode_line_info->Lookup(event->user_data, hash, false);
14187 CHECK(entry != NULL);
14188 delete reinterpret_cast<DummyJitCodeLineInfo*>(event->user_data);
14189 }
14190 break;
14191
14192 case v8::JitCodeEvent::CODE_ADD_LINE_POS_INFO: {
14193 CHECK(event->user_data != NULL);
14194 uint32_t hash = i::ComputePointerHash(event->user_data);
14195 i::HashMap::Entry* entry =
14196 jitcode_line_info->Lookup(event->user_data, hash, false);
14197 CHECK(entry != NULL);
14198 }
14199 break;
14200
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014201 default:
14202 // Impossible event.
14203 CHECK(false);
14204 break;
14205 }
14206}
14207
14208
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014209UNINITIALIZED_TEST(SetJitCodeEventHandler) {
ulan@chromium.org6ba1fd02013-02-14 14:56:11 +000014210 i::FLAG_stress_compaction = true;
danno@chromium.orgf005df62013-04-30 16:36:45 +000014211 i::FLAG_incremental_marking = false;
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014212 const char* script =
14213 "function bar() {"
14214 " var sum = 0;"
14215 " for (i = 0; i < 100; ++i)"
14216 " sum = foo(i);"
14217 " return sum;"
14218 "}"
14219 "function foo(i) { return i * i; };"
14220 "bar();";
14221
14222 // Run this test in a new isolate to make sure we don't
14223 // have remnants of state from other code.
14224 v8::Isolate* isolate = v8::Isolate::New();
14225 isolate->Enter();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014226 i::Heap* heap = reinterpret_cast<i::Isolate*>(isolate)->heap();
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014227
14228 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000014229 v8::HandleScope scope(isolate);
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014230 i::HashMap code(MatchPointers);
14231 code_map = &code;
14232
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +000014233 i::HashMap lineinfo(MatchPointers);
14234 jitcode_line_info = &lineinfo;
14235
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014236 saw_bar = 0;
14237 move_events = 0;
14238
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014239 V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault, event_handler);
14240
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014241 // Generate new code objects sparsely distributed across several
14242 // different fragmented code-space pages.
14243 const int kIterations = 10;
14244 for (int i = 0; i < kIterations; ++i) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014245 LocalContext env(isolate);
ulan@chromium.org6ba1fd02013-02-14 14:56:11 +000014246 i::AlwaysAllocateScope always_allocate;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014247 SimulateFullSpace(heap->code_space());
ulan@chromium.org6ba1fd02013-02-14 14:56:11 +000014248 CompileRun(script);
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014249
ulan@chromium.org6ba1fd02013-02-14 14:56:11 +000014250 // Keep a strong reference to the code object in the handle scope.
14251 i::Handle<i::Code> bar_code(i::Handle<i::JSFunction>::cast(
14252 v8::Utils::OpenHandle(*env->Global()->Get(v8_str("bar"))))->code());
14253 i::Handle<i::Code> foo_code(i::Handle<i::JSFunction>::cast(
14254 v8::Utils::OpenHandle(*env->Global()->Get(v8_str("foo"))))->code());
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014255
14256 // Clear the compilation cache to get more wastage.
hpayer@chromium.orgc5d49712013-09-11 08:25:48 +000014257 reinterpret_cast<i::Isolate*>(isolate)->compilation_cache()->Clear();
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014258 }
14259
14260 // Force code movement.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014261 heap->CollectAllAvailableGarbage("TestSetJitCodeEventHandler");
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014262
ulan@chromium.org6ba1fd02013-02-14 14:56:11 +000014263 V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault, NULL);
14264
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014265 CHECK_LE(kIterations, saw_bar);
ulan@chromium.org6ba1fd02013-02-14 14:56:11 +000014266 CHECK_LT(0, move_events);
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014267
14268 code_map = NULL;
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +000014269 jitcode_line_info = NULL;
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014270 }
14271
14272 isolate->Exit();
14273 isolate->Dispose();
14274
14275 // Do this in a new isolate.
14276 isolate = v8::Isolate::New();
14277 isolate->Enter();
14278
14279 // Verify that we get callbacks for existing code objects when we
14280 // request enumeration of existing code.
14281 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000014282 v8::HandleScope scope(isolate);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014283 LocalContext env(isolate);
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014284 CompileRun(script);
14285
14286 // Now get code through initial iteration.
14287 i::HashMap code(MatchPointers);
14288 code_map = &code;
14289
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +000014290 i::HashMap lineinfo(MatchPointers);
14291 jitcode_line_info = &lineinfo;
14292
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014293 V8::SetJitCodeEventHandler(v8::kJitCodeEventEnumExisting, event_handler);
14294 V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault, NULL);
14295
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +000014296 jitcode_line_info = NULL;
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014297 // We expect that we got some events. Note that if we could get code removal
14298 // notifications, we could compare two collections, one created by listening
14299 // from the time of creation of an isolate, and the other by subscribing
14300 // with EnumExisting.
ulan@chromium.org6ba1fd02013-02-14 14:56:11 +000014301 CHECK_LT(0, code.occupancy());
14302
14303 code_map = NULL;
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014304 }
14305
14306 isolate->Exit();
14307 isolate->Dispose();
14308}
14309
14310
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000014311THREADED_TEST(ExternalAllocatedMemory) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014312 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000014313 v8::HandleScope outer(isolate);
14314 v8::Local<Context> env(Context::New(isolate));
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000014315 CHECK(!env.IsEmpty());
machenbach@chromium.org7ff76072013-11-21 09:47:43 +000014316 const int64_t kSize = 1024*1024;
14317 int64_t baseline = isolate->AdjustAmountOfExternalAllocatedMemory(0);
14318 CHECK_EQ(baseline + kSize,
14319 isolate->AdjustAmountOfExternalAllocatedMemory(kSize));
danno@chromium.orgf005df62013-04-30 16:36:45 +000014320 CHECK_EQ(baseline,
machenbach@chromium.org7ff76072013-11-21 09:47:43 +000014321 isolate->AdjustAmountOfExternalAllocatedMemory(-kSize));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000014322}
14323
14324
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014325// Regression test for issue 54, object templates with internal fields
14326// but no accessors or interceptors did not get their internal field
14327// count set on instances.
14328THREADED_TEST(Regress54) {
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014329 LocalContext context;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000014330 v8::Isolate* isolate = context->GetIsolate();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000014331 v8::HandleScope outer(isolate);
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014332 static v8::Persistent<v8::ObjectTemplate> templ;
14333 if (templ.IsEmpty()) {
machenbach@chromium.orgafbdadc2013-12-09 16:12:18 +000014334 v8::EscapableHandleScope inner(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000014335 v8::Local<v8::ObjectTemplate> local = v8::ObjectTemplate::New(isolate);
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014336 local->SetInternalFieldCount(1);
machenbach@chromium.orgafbdadc2013-12-09 16:12:18 +000014337 templ.Reset(isolate, inner.Escape(local));
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014338 }
rossberg@chromium.org79e79022013-06-03 15:43:46 +000014339 v8::Handle<v8::Object> result =
14340 v8::Local<v8::ObjectTemplate>::New(isolate, templ)->NewInstance();
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014341 CHECK_EQ(1, result->InternalFieldCount());
14342}
14343
14344
14345// If part of the threaded tests, this test makes ThreadingTest fail
14346// on mac.
14347TEST(CatchStackOverflow) {
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014348 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000014349 v8::HandleScope scope(context->GetIsolate());
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014350 v8::TryCatch try_catch;
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000014351 v8::Handle<v8::Script> script = v8::Script::Compile(v8::String::NewFromUtf8(
14352 context->GetIsolate(),
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014353 "function f() {"
14354 " return f();"
14355 "}"
14356 ""
14357 "f();"));
14358 v8::Handle<v8::Value> result = script->Run();
14359 CHECK(result.IsEmpty());
14360}
14361
14362
kasperl@chromium.org7be3c992009-03-12 07:19:55 +000014363static void CheckTryCatchSourceInfo(v8::Handle<v8::Script> script,
14364 const char* resource_name,
14365 int line_offset) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014366 v8::HandleScope scope(CcTest::isolate());
kasperl@chromium.org7be3c992009-03-12 07:19:55 +000014367 v8::TryCatch try_catch;
14368 v8::Handle<v8::Value> result = script->Run();
14369 CHECK(result.IsEmpty());
14370 CHECK(try_catch.HasCaught());
14371 v8::Handle<v8::Message> message = try_catch.Message();
14372 CHECK(!message.IsEmpty());
14373 CHECK_EQ(10 + line_offset, message->GetLineNumber());
14374 CHECK_EQ(91, message->GetStartPosition());
14375 CHECK_EQ(92, message->GetEndPosition());
14376 CHECK_EQ(2, message->GetStartColumn());
14377 CHECK_EQ(3, message->GetEndColumn());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000014378 v8::String::Utf8Value line(message->GetSourceLine());
kasperl@chromium.org7be3c992009-03-12 07:19:55 +000014379 CHECK_EQ(" throw 'nirk';", *line);
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000014380 v8::String::Utf8Value name(message->GetScriptResourceName());
kasperl@chromium.org7be3c992009-03-12 07:19:55 +000014381 CHECK_EQ(resource_name, *name);
14382}
14383
14384
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014385THREADED_TEST(TryCatchSourceInfo) {
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014386 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000014387 v8::HandleScope scope(context->GetIsolate());
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000014388 v8::Handle<v8::String> source = v8::String::NewFromUtf8(
14389 context->GetIsolate(),
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014390 "function Foo() {\n"
14391 " return Bar();\n"
14392 "}\n"
14393 "\n"
14394 "function Bar() {\n"
14395 " return Baz();\n"
14396 "}\n"
14397 "\n"
14398 "function Baz() {\n"
14399 " throw 'nirk';\n"
14400 "}\n"
14401 "\n"
14402 "Foo();\n");
kasperl@chromium.org7be3c992009-03-12 07:19:55 +000014403
14404 const char* resource_name;
14405 v8::Handle<v8::Script> script;
14406 resource_name = "test.js";
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000014407 script = v8::Script::Compile(
14408 source, v8::String::NewFromUtf8(context->GetIsolate(), resource_name));
kasperl@chromium.org7be3c992009-03-12 07:19:55 +000014409 CheckTryCatchSourceInfo(script, resource_name, 0);
14410
14411 resource_name = "test1.js";
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000014412 v8::ScriptOrigin origin1(
14413 v8::String::NewFromUtf8(context->GetIsolate(), resource_name));
kasperl@chromium.org7be3c992009-03-12 07:19:55 +000014414 script = v8::Script::Compile(source, &origin1);
14415 CheckTryCatchSourceInfo(script, resource_name, 0);
14416
14417 resource_name = "test2.js";
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000014418 v8::ScriptOrigin origin2(
14419 v8::String::NewFromUtf8(context->GetIsolate(), resource_name),
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014420 v8::Integer::New(context->GetIsolate(), 7));
kasperl@chromium.org7be3c992009-03-12 07:19:55 +000014421 script = v8::Script::Compile(source, &origin2);
14422 CheckTryCatchSourceInfo(script, resource_name, 7);
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014423}
kasperl@chromium.orgb9123622008-09-17 14:05:56 +000014424
14425
14426THREADED_TEST(CompilationCache) {
kasperl@chromium.orgb9123622008-09-17 14:05:56 +000014427 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000014428 v8::HandleScope scope(context->GetIsolate());
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000014429 v8::Handle<v8::String> source0 =
14430 v8::String::NewFromUtf8(context->GetIsolate(), "1234");
14431 v8::Handle<v8::String> source1 =
14432 v8::String::NewFromUtf8(context->GetIsolate(), "1234");
14433 v8::Handle<v8::Script> script0 = v8::Script::Compile(
14434 source0, v8::String::NewFromUtf8(context->GetIsolate(), "test.js"));
14435 v8::Handle<v8::Script> script1 = v8::Script::Compile(
14436 source1, v8::String::NewFromUtf8(context->GetIsolate(), "test.js"));
kasperl@chromium.orgb9123622008-09-17 14:05:56 +000014437 v8::Handle<v8::Script> script2 =
14438 v8::Script::Compile(source0); // different origin
14439 CHECK_EQ(1234, script0->Run()->Int32Value());
14440 CHECK_EQ(1234, script1->Run()->Int32Value());
14441 CHECK_EQ(1234, script2->Run()->Int32Value());
14442}
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000014443
14444
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000014445static void FunctionNameCallback(
14446 const v8::FunctionCallbackInfo<v8::Value>& args) {
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000014447 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000014448 args.GetReturnValue().Set(v8_num(42));
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000014449}
14450
14451
14452THREADED_TEST(CallbackFunctionName) {
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000014453 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000014454 v8::Isolate* isolate = context->GetIsolate();
14455 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000014456 Local<ObjectTemplate> t = ObjectTemplate::New(isolate);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000014457 t->Set(v8_str("asdf"),
14458 v8::FunctionTemplate::New(isolate, FunctionNameCallback));
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000014459 context->Global()->Set(v8_str("obj"), t->NewInstance());
14460 v8::Handle<v8::Value> value = CompileRun("obj.asdf.name");
14461 CHECK(value->IsString());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000014462 v8::String::Utf8Value name(value);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000014463 CHECK_EQ("asdf", *name);
14464}
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014465
14466
14467THREADED_TEST(DateAccess) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014468 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000014469 v8::HandleScope scope(context->GetIsolate());
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000014470 v8::Handle<v8::Value> date =
14471 v8::Date::New(context->GetIsolate(), 1224744689038.0);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014472 CHECK(date->IsDate());
danno@chromium.orgd3c42102013-08-01 16:58:23 +000014473 CHECK_EQ(1224744689038.0, date.As<v8::Date>()->ValueOf());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014474}
14475
14476
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014477void CheckProperties(v8::Isolate* isolate,
14478 v8::Handle<v8::Value> val,
14479 int elmc,
14480 const char* elmv[]) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000014481 v8::Handle<v8::Object> obj = val.As<v8::Object>();
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014482 v8::Handle<v8::Array> props = obj->GetPropertyNames();
14483 CHECK_EQ(elmc, props->Length());
14484 for (int i = 0; i < elmc; i++) {
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014485 v8::String::Utf8Value elm(props->Get(v8::Integer::New(isolate, i)));
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014486 CHECK_EQ(elmv[i], *elm);
14487 }
14488}
14489
14490
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014491void CheckOwnProperties(v8::Isolate* isolate,
14492 v8::Handle<v8::Value> val,
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000014493 int elmc,
14494 const char* elmv[]) {
14495 v8::Handle<v8::Object> obj = val.As<v8::Object>();
14496 v8::Handle<v8::Array> props = obj->GetOwnPropertyNames();
14497 CHECK_EQ(elmc, props->Length());
14498 for (int i = 0; i < elmc; i++) {
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014499 v8::String::Utf8Value elm(props->Get(v8::Integer::New(isolate, i)));
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000014500 CHECK_EQ(elmv[i], *elm);
14501 }
14502}
14503
14504
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014505THREADED_TEST(PropertyEnumeration) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014506 LocalContext context;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014507 v8::Isolate* isolate = context->GetIsolate();
14508 v8::HandleScope scope(isolate);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000014509 v8::Handle<v8::Value> obj = v8::Script::Compile(v8::String::NewFromUtf8(
14510 context->GetIsolate(),
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014511 "var result = [];"
14512 "result[0] = {};"
14513 "result[1] = {a: 1, b: 2};"
14514 "result[2] = [1, 2, 3];"
14515 "var proto = {x: 1, y: 2, z: 3};"
14516 "var x = { __proto__: proto, w: 0, z: 1 };"
14517 "result[3] = x;"
14518 "result;"))->Run();
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000014519 v8::Handle<v8::Array> elms = obj.As<v8::Array>();
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014520 CHECK_EQ(4, elms->Length());
14521 int elmc0 = 0;
14522 const char** elmv0 = NULL;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014523 CheckProperties(
14524 isolate, elms->Get(v8::Integer::New(isolate, 0)), elmc0, elmv0);
14525 CheckOwnProperties(
14526 isolate, elms->Get(v8::Integer::New(isolate, 0)), elmc0, elmv0);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014527 int elmc1 = 2;
14528 const char* elmv1[] = {"a", "b"};
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014529 CheckProperties(
14530 isolate, elms->Get(v8::Integer::New(isolate, 1)), elmc1, elmv1);
14531 CheckOwnProperties(
14532 isolate, elms->Get(v8::Integer::New(isolate, 1)), elmc1, elmv1);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014533 int elmc2 = 3;
14534 const char* elmv2[] = {"0", "1", "2"};
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014535 CheckProperties(
14536 isolate, elms->Get(v8::Integer::New(isolate, 2)), elmc2, elmv2);
14537 CheckOwnProperties(
14538 isolate, elms->Get(v8::Integer::New(isolate, 2)), elmc2, elmv2);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014539 int elmc3 = 4;
14540 const char* elmv3[] = {"w", "z", "x", "y"};
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014541 CheckProperties(
14542 isolate, elms->Get(v8::Integer::New(isolate, 3)), elmc3, elmv3);
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000014543 int elmc4 = 2;
14544 const char* elmv4[] = {"w", "z"};
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014545 CheckOwnProperties(
14546 isolate, elms->Get(v8::Integer::New(isolate, 3)), elmc4, elmv4);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014547}
ager@chromium.org870a0b62008-11-04 11:43:05 +000014548
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000014549
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000014550THREADED_TEST(PropertyEnumeration2) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000014551 LocalContext context;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014552 v8::Isolate* isolate = context->GetIsolate();
14553 v8::HandleScope scope(isolate);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000014554 v8::Handle<v8::Value> obj = v8::Script::Compile(v8::String::NewFromUtf8(
14555 context->GetIsolate(),
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000014556 "var result = [];"
14557 "result[0] = {};"
14558 "result[1] = {a: 1, b: 2};"
14559 "result[2] = [1, 2, 3];"
14560 "var proto = {x: 1, y: 2, z: 3};"
14561 "var x = { __proto__: proto, w: 0, z: 1 };"
14562 "result[3] = x;"
14563 "result;"))->Run();
14564 v8::Handle<v8::Array> elms = obj.As<v8::Array>();
14565 CHECK_EQ(4, elms->Length());
14566 int elmc0 = 0;
14567 const char** elmv0 = NULL;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014568 CheckProperties(isolate,
14569 elms->Get(v8::Integer::New(isolate, 0)), elmc0, elmv0);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000014570
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014571 v8::Handle<v8::Value> val = elms->Get(v8::Integer::New(isolate, 0));
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000014572 v8::Handle<v8::Array> props = val.As<v8::Object>()->GetPropertyNames();
14573 CHECK_EQ(0, props->Length());
14574 for (uint32_t i = 0; i < props->Length(); i++) {
14575 printf("p[%d]\n", i);
14576 }
14577}
ager@chromium.org870a0b62008-11-04 11:43:05 +000014578
ager@chromium.org870a0b62008-11-04 11:43:05 +000014579static bool NamedSetAccessBlocker(Local<v8::Object> obj,
14580 Local<Value> name,
14581 v8::AccessType type,
14582 Local<Value> data) {
14583 return type != v8::ACCESS_SET;
14584}
14585
14586
14587static bool IndexedSetAccessBlocker(Local<v8::Object> obj,
14588 uint32_t key,
14589 v8::AccessType type,
14590 Local<Value> data) {
14591 return type != v8::ACCESS_SET;
14592}
14593
14594
14595THREADED_TEST(DisableAccessChecksWhileConfiguring) {
ager@chromium.org870a0b62008-11-04 11:43:05 +000014596 LocalContext context;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000014597 v8::Isolate* isolate = context->GetIsolate();
14598 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000014599 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org870a0b62008-11-04 11:43:05 +000014600 templ->SetAccessCheckCallbacks(NamedSetAccessBlocker,
14601 IndexedSetAccessBlocker);
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000014602 templ->Set(v8_str("x"), v8::True(isolate));
ager@chromium.org870a0b62008-11-04 11:43:05 +000014603 Local<v8::Object> instance = templ->NewInstance();
14604 context->Global()->Set(v8_str("obj"), instance);
14605 Local<Value> value = CompileRun("obj.x");
14606 CHECK(value->BooleanValue());
14607}
ager@chromium.orga74f0da2008-12-03 16:05:52 +000014608
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000014609
ager@chromium.org32912102009-01-16 10:38:43 +000014610static bool NamedGetAccessBlocker(Local<v8::Object> obj,
14611 Local<Value> name,
14612 v8::AccessType type,
14613 Local<Value> data) {
14614 return false;
14615}
14616
14617
14618static bool IndexedGetAccessBlocker(Local<v8::Object> obj,
14619 uint32_t key,
14620 v8::AccessType type,
14621 Local<Value> data) {
14622 return false;
14623}
14624
14625
14626
14627THREADED_TEST(AccessChecksReenabledCorrectly) {
ager@chromium.org32912102009-01-16 10:38:43 +000014628 LocalContext context;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000014629 v8::Isolate* isolate = context->GetIsolate();
14630 v8::HandleScope scope(isolate);
14631 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org32912102009-01-16 10:38:43 +000014632 templ->SetAccessCheckCallbacks(NamedGetAccessBlocker,
14633 IndexedGetAccessBlocker);
14634 templ->Set(v8_str("a"), v8_str("a"));
14635 // Add more than 8 (see kMaxFastProperties) properties
14636 // so that the constructor will force copying map.
14637 // Cannot sprintf, gcc complains unsafety.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000014638 char buf[4];
ager@chromium.org32912102009-01-16 10:38:43 +000014639 for (char i = '0'; i <= '9' ; i++) {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000014640 buf[0] = i;
ager@chromium.org32912102009-01-16 10:38:43 +000014641 for (char j = '0'; j <= '9'; j++) {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000014642 buf[1] = j;
ager@chromium.org32912102009-01-16 10:38:43 +000014643 for (char k = '0'; k <= '9'; k++) {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000014644 buf[2] = k;
14645 buf[3] = 0;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000014646 templ->Set(v8_str(buf), v8::Number::New(isolate, k));
ager@chromium.org32912102009-01-16 10:38:43 +000014647 }
14648 }
14649 }
14650
14651 Local<v8::Object> instance_1 = templ->NewInstance();
14652 context->Global()->Set(v8_str("obj_1"), instance_1);
14653
14654 Local<Value> value_1 = CompileRun("obj_1.a");
14655 CHECK(value_1->IsUndefined());
14656
14657 Local<v8::Object> instance_2 = templ->NewInstance();
14658 context->Global()->Set(v8_str("obj_2"), instance_2);
14659
14660 Local<Value> value_2 = CompileRun("obj_2.a");
14661 CHECK(value_2->IsUndefined());
14662}
ager@chromium.orga74f0da2008-12-03 16:05:52 +000014663
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000014664
ager@chromium.org8bb60582008-12-11 12:02:20 +000014665// This tests that access check information remains on the global
14666// object template when creating contexts.
14667THREADED_TEST(AccessControlRepeatedContextCreation) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014668 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000014669 v8::HandleScope handle_scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000014670 v8::Handle<v8::ObjectTemplate> global_template =
14671 v8::ObjectTemplate::New(isolate);
ager@chromium.org8bb60582008-12-11 12:02:20 +000014672 global_template->SetAccessCheckCallbacks(NamedSetAccessBlocker,
14673 IndexedSetAccessBlocker);
14674 i::Handle<i::ObjectTemplateInfo> internal_template =
14675 v8::Utils::OpenHandle(*global_template);
14676 CHECK(!internal_template->constructor()->IsUndefined());
14677 i::Handle<i::FunctionTemplateInfo> constructor(
14678 i::FunctionTemplateInfo::cast(internal_template->constructor()));
14679 CHECK(!constructor->access_check_info()->IsUndefined());
ulan@chromium.org57ff8812013-05-10 08:16:55 +000014680 v8::Local<Context> context0(Context::New(isolate, NULL, global_template));
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000014681 CHECK(!context0.IsEmpty());
ager@chromium.org8bb60582008-12-11 12:02:20 +000014682 CHECK(!constructor->access_check_info()->IsUndefined());
14683}
14684
14685
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000014686THREADED_TEST(TurnOnAccessCheck) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014687 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000014688 v8::HandleScope handle_scope(isolate);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000014689
14690 // Create an environment with access check to the global object disabled by
14691 // default.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000014692 v8::Handle<v8::ObjectTemplate> global_template =
14693 v8::ObjectTemplate::New(isolate);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000014694 global_template->SetAccessCheckCallbacks(NamedGetAccessBlocker,
14695 IndexedGetAccessBlocker,
14696 v8::Handle<v8::Value>(),
14697 false);
ulan@chromium.org57ff8812013-05-10 08:16:55 +000014698 v8::Local<Context> context = Context::New(isolate, NULL, global_template);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000014699 Context::Scope context_scope(context);
14700
14701 // Set up a property and a number of functions.
14702 context->Global()->Set(v8_str("a"), v8_num(1));
14703 CompileRun("function f1() {return a;}"
14704 "function f2() {return a;}"
14705 "function g1() {return h();}"
14706 "function g2() {return h();}"
14707 "function h() {return 1;}");
14708 Local<Function> f1 =
14709 Local<Function>::Cast(context->Global()->Get(v8_str("f1")));
14710 Local<Function> f2 =
14711 Local<Function>::Cast(context->Global()->Get(v8_str("f2")));
14712 Local<Function> g1 =
14713 Local<Function>::Cast(context->Global()->Get(v8_str("g1")));
14714 Local<Function> g2 =
14715 Local<Function>::Cast(context->Global()->Get(v8_str("g2")));
14716 Local<Function> h =
14717 Local<Function>::Cast(context->Global()->Get(v8_str("h")));
14718
14719 // Get the global object.
14720 v8::Handle<v8::Object> global = context->Global();
14721
14722 // Call f1 one time and f2 a number of times. This will ensure that f1 still
14723 // uses the runtime system to retreive property a whereas f2 uses global load
14724 // inline cache.
14725 CHECK(f1->Call(global, 0, NULL)->Equals(v8_num(1)));
14726 for (int i = 0; i < 4; i++) {
14727 CHECK(f2->Call(global, 0, NULL)->Equals(v8_num(1)));
14728 }
14729
14730 // Same for g1 and g2.
14731 CHECK(g1->Call(global, 0, NULL)->Equals(v8_num(1)));
14732 for (int i = 0; i < 4; i++) {
14733 CHECK(g2->Call(global, 0, NULL)->Equals(v8_num(1)));
14734 }
14735
14736 // Detach the global and turn on access check.
jkummerow@chromium.org113035e2013-12-13 15:13:40 +000014737 Local<Object> hidden_global = Local<Object>::Cast(
14738 context->Global()->GetPrototype());
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000014739 context->DetachGlobal();
jkummerow@chromium.org113035e2013-12-13 15:13:40 +000014740 hidden_global->TurnOnAccessCheck();
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000014741
14742 // Failing access check to property get results in undefined.
14743 CHECK(f1->Call(global, 0, NULL)->IsUndefined());
14744 CHECK(f2->Call(global, 0, NULL)->IsUndefined());
14745
14746 // Failing access check to function call results in exception.
14747 CHECK(g1->Call(global, 0, NULL).IsEmpty());
14748 CHECK(g2->Call(global, 0, NULL).IsEmpty());
14749
14750 // No failing access check when just returning a constant.
14751 CHECK(h->Call(global, 0, NULL)->Equals(v8_num(1)));
14752}
14753
14754
jkummerow@chromium.orgf7a58842012-02-21 10:08:21 +000014755static const char* kPropertyA = "a";
14756static const char* kPropertyH = "h";
kasperl@chromium.orga5551262010-12-07 12:49:48 +000014757
14758static bool NamedGetAccessBlockAandH(Local<v8::Object> obj,
14759 Local<Value> name,
14760 v8::AccessType type,
14761 Local<Value> data) {
jkummerow@chromium.orgf7a58842012-02-21 10:08:21 +000014762 if (!name->IsString()) return false;
14763 i::Handle<i::String> name_handle =
14764 v8::Utils::OpenHandle(String::Cast(*name));
jkummerow@chromium.org59297c72013-01-09 16:32:23 +000014765 return !name_handle->IsUtf8EqualTo(i::CStrVector(kPropertyA))
14766 && !name_handle->IsUtf8EqualTo(i::CStrVector(kPropertyH));
kasperl@chromium.orga5551262010-12-07 12:49:48 +000014767}
14768
14769
jkummerow@chromium.orgf7a58842012-02-21 10:08:21 +000014770THREADED_TEST(TurnOnAccessCheckAndRecompile) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014771 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000014772 v8::HandleScope handle_scope(isolate);
kasperl@chromium.orga5551262010-12-07 12:49:48 +000014773
14774 // Create an environment with access check to the global object disabled by
14775 // default. When the registered access checker will block access to properties
jkummerow@chromium.orgf7a58842012-02-21 10:08:21 +000014776 // a and h.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000014777 v8::Handle<v8::ObjectTemplate> global_template =
14778 v8::ObjectTemplate::New(isolate);
kasperl@chromium.orga5551262010-12-07 12:49:48 +000014779 global_template->SetAccessCheckCallbacks(NamedGetAccessBlockAandH,
14780 IndexedGetAccessBlocker,
14781 v8::Handle<v8::Value>(),
14782 false);
ulan@chromium.org57ff8812013-05-10 08:16:55 +000014783 v8::Local<Context> context = Context::New(isolate, NULL, global_template);
kasperl@chromium.orga5551262010-12-07 12:49:48 +000014784 Context::Scope context_scope(context);
14785
14786 // Set up a property and a number of functions.
14787 context->Global()->Set(v8_str("a"), v8_num(1));
14788 static const char* source = "function f1() {return a;}"
14789 "function f2() {return a;}"
14790 "function g1() {return h();}"
14791 "function g2() {return h();}"
14792 "function h() {return 1;}";
14793
14794 CompileRun(source);
14795 Local<Function> f1;
14796 Local<Function> f2;
14797 Local<Function> g1;
14798 Local<Function> g2;
14799 Local<Function> h;
14800 f1 = Local<Function>::Cast(context->Global()->Get(v8_str("f1")));
14801 f2 = Local<Function>::Cast(context->Global()->Get(v8_str("f2")));
14802 g1 = Local<Function>::Cast(context->Global()->Get(v8_str("g1")));
14803 g2 = Local<Function>::Cast(context->Global()->Get(v8_str("g2")));
14804 h = Local<Function>::Cast(context->Global()->Get(v8_str("h")));
14805
14806 // Get the global object.
14807 v8::Handle<v8::Object> global = context->Global();
14808
14809 // Call f1 one time and f2 a number of times. This will ensure that f1 still
14810 // uses the runtime system to retreive property a whereas f2 uses global load
14811 // inline cache.
14812 CHECK(f1->Call(global, 0, NULL)->Equals(v8_num(1)));
14813 for (int i = 0; i < 4; i++) {
14814 CHECK(f2->Call(global, 0, NULL)->Equals(v8_num(1)));
14815 }
14816
14817 // Same for g1 and g2.
14818 CHECK(g1->Call(global, 0, NULL)->Equals(v8_num(1)));
14819 for (int i = 0; i < 4; i++) {
14820 CHECK(g2->Call(global, 0, NULL)->Equals(v8_num(1)));
14821 }
14822
14823 // Detach the global and turn on access check now blocking access to property
14824 // a and function h.
jkummerow@chromium.org113035e2013-12-13 15:13:40 +000014825 Local<Object> hidden_global = Local<Object>::Cast(
14826 context->Global()->GetPrototype());
kasperl@chromium.orga5551262010-12-07 12:49:48 +000014827 context->DetachGlobal();
jkummerow@chromium.org113035e2013-12-13 15:13:40 +000014828 hidden_global->TurnOnAccessCheck();
kasperl@chromium.orga5551262010-12-07 12:49:48 +000014829
14830 // Failing access check to property get results in undefined.
14831 CHECK(f1->Call(global, 0, NULL)->IsUndefined());
14832 CHECK(f2->Call(global, 0, NULL)->IsUndefined());
14833
14834 // Failing access check to function call results in exception.
14835 CHECK(g1->Call(global, 0, NULL).IsEmpty());
14836 CHECK(g2->Call(global, 0, NULL).IsEmpty());
14837
14838 // No failing access check when just returning a constant.
14839 CHECK(h->Call(global, 0, NULL)->Equals(v8_num(1)));
14840
14841 // Now compile the source again. And get the newly compiled functions, except
14842 // for h for which access is blocked.
14843 CompileRun(source);
jkummerow@chromium.org113035e2013-12-13 15:13:40 +000014844 f1 = Local<Function>::Cast(hidden_global->Get(v8_str("f1")));
14845 f2 = Local<Function>::Cast(hidden_global->Get(v8_str("f2")));
14846 g1 = Local<Function>::Cast(hidden_global->Get(v8_str("g1")));
14847 g2 = Local<Function>::Cast(hidden_global->Get(v8_str("g2")));
14848 CHECK(hidden_global->Get(v8_str("h"))->IsUndefined());
kasperl@chromium.orga5551262010-12-07 12:49:48 +000014849
14850 // Failing access check to property get results in undefined.
14851 CHECK(f1->Call(global, 0, NULL)->IsUndefined());
14852 CHECK(f2->Call(global, 0, NULL)->IsUndefined());
14853
14854 // Failing access check to function call results in exception.
14855 CHECK(g1->Call(global, 0, NULL).IsEmpty());
14856 CHECK(g2->Call(global, 0, NULL).IsEmpty());
14857}
14858
14859
ager@chromium.orga74f0da2008-12-03 16:05:52 +000014860// This test verifies that pre-compilation (aka preparsing) can be called
14861// without initializing the whole VM. Thus we cannot run this test in a
14862// multi-threaded setup.
14863TEST(PreCompile) {
14864 // TODO(155): This test would break without the initialization of V8. This is
14865 // a workaround for now to make this test not fail.
14866 v8::V8::Initialize();
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +000014867 v8::Isolate* isolate = CcTest::isolate();
machenbach@chromium.org4ddd2f12014-01-14 08:13:44 +000014868 HandleScope handle_scope(isolate);
kmillikin@chromium.org9155e252010-05-26 13:27:57 +000014869 const char* script = "function foo(a) { return a+1; }";
machenbach@chromium.org4ddd2f12014-01-14 08:13:44 +000014870 v8::ScriptData* sd = v8::ScriptData::PreCompile(v8::String::NewFromUtf8(
14871 isolate, script, v8::String::kNormalString, i::StrLength(script)));
ager@chromium.orga74f0da2008-12-03 16:05:52 +000014872 CHECK_NE(sd->Length(), 0);
14873 CHECK_NE(sd->Data(), NULL);
fschneider@chromium.org0c20e672010-01-14 15:28:53 +000014874 CHECK(!sd->HasError());
14875 delete sd;
14876}
14877
14878
14879TEST(PreCompileWithError) {
14880 v8::V8::Initialize();
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +000014881 v8::Isolate* isolate = CcTest::isolate();
machenbach@chromium.org4ddd2f12014-01-14 08:13:44 +000014882 HandleScope handle_scope(isolate);
kmillikin@chromium.org9155e252010-05-26 13:27:57 +000014883 const char* script = "function foo(a) { return 1 * * 2; }";
machenbach@chromium.org4ddd2f12014-01-14 08:13:44 +000014884 v8::ScriptData* sd = v8::ScriptData::PreCompile(v8::String::NewFromUtf8(
14885 isolate, script, v8::String::kNormalString, i::StrLength(script)));
fschneider@chromium.org0c20e672010-01-14 15:28:53 +000014886 CHECK(sd->HasError());
14887 delete sd;
14888}
14889
14890
14891TEST(Regress31661) {
14892 v8::V8::Initialize();
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +000014893 v8::Isolate* isolate = CcTest::isolate();
machenbach@chromium.org4ddd2f12014-01-14 08:13:44 +000014894 HandleScope handle_scope(isolate);
kmillikin@chromium.org9155e252010-05-26 13:27:57 +000014895 const char* script = " The Definintive Guide";
machenbach@chromium.org4ddd2f12014-01-14 08:13:44 +000014896 v8::ScriptData* sd = v8::ScriptData::PreCompile(v8::String::NewFromUtf8(
14897 isolate, script, v8::String::kNormalString, i::StrLength(script)));
fschneider@chromium.org0c20e672010-01-14 15:28:53 +000014898 CHECK(sd->HasError());
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000014899 delete sd;
ager@chromium.orga74f0da2008-12-03 16:05:52 +000014900}
14901
14902
kmillikin@chromium.org9155e252010-05-26 13:27:57 +000014903// Tests that ScriptData can be serialized and deserialized.
14904TEST(PreCompileSerialization) {
14905 v8::V8::Initialize();
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +000014906 v8::Isolate* isolate = CcTest::isolate();
machenbach@chromium.org4ddd2f12014-01-14 08:13:44 +000014907 HandleScope handle_scope(isolate);
kmillikin@chromium.org9155e252010-05-26 13:27:57 +000014908 const char* script = "function foo(a) { return a+1; }";
machenbach@chromium.org4ddd2f12014-01-14 08:13:44 +000014909 v8::ScriptData* sd = v8::ScriptData::PreCompile(v8::String::NewFromUtf8(
14910 isolate, script, v8::String::kNormalString, i::StrLength(script)));
kmillikin@chromium.org9155e252010-05-26 13:27:57 +000014911
14912 // Serialize.
14913 int serialized_data_length = sd->Length();
14914 char* serialized_data = i::NewArray<char>(serialized_data_length);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +000014915 i::OS::MemCopy(serialized_data, sd->Data(), serialized_data_length);
kmillikin@chromium.org9155e252010-05-26 13:27:57 +000014916
14917 // Deserialize.
14918 v8::ScriptData* deserialized_sd =
14919 v8::ScriptData::New(serialized_data, serialized_data_length);
14920
14921 // Verify that the original is the same as the deserialized.
14922 CHECK_EQ(sd->Length(), deserialized_sd->Length());
14923 CHECK_EQ(0, memcmp(sd->Data(), deserialized_sd->Data(), sd->Length()));
14924 CHECK_EQ(sd->HasError(), deserialized_sd->HasError());
14925
14926 delete sd;
14927 delete deserialized_sd;
14928}
14929
14930
14931// Attempts to deserialize bad data.
14932TEST(PreCompileDeserializationError) {
14933 v8::V8::Initialize();
14934 const char* data = "DONT CARE";
14935 int invalid_size = 3;
14936 v8::ScriptData* sd = v8::ScriptData::New(data, invalid_size);
14937
14938 CHECK_EQ(0, sd->Length());
14939
14940 delete sd;
14941}
14942
14943
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014944// Attempts to deserialize bad data.
14945TEST(PreCompileInvalidPreparseDataError) {
14946 v8::V8::Initialize();
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +000014947 v8::Isolate* isolate = CcTest::isolate();
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014948 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000014949 v8::HandleScope scope(context->GetIsolate());
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014950
14951 const char* script = "function foo(){ return 5;}\n"
14952 "function bar(){ return 6 + 7;} foo();";
machenbach@chromium.org4ddd2f12014-01-14 08:13:44 +000014953 v8::ScriptData* sd = v8::ScriptData::PreCompile(v8::String::NewFromUtf8(
14954 isolate, script, v8::String::kNormalString, i::StrLength(script)));
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014955 CHECK(!sd->HasError());
14956 // ScriptDataImpl private implementation details
ager@chromium.orgbeb25712010-11-29 08:02:25 +000014957 const int kHeaderSize = i::PreparseDataConstants::kHeaderSize;
ager@chromium.org5b2fbee2010-09-08 06:38:15 +000014958 const int kFunctionEntrySize = i::FunctionEntry::kSize;
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014959 const int kFunctionEntryStartOffset = 0;
14960 const int kFunctionEntryEndOffset = 1;
14961 unsigned* sd_data =
14962 reinterpret_cast<unsigned*>(const_cast<char*>(sd->Data()));
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014963
14964 // Overwrite function bar's end position with 0.
14965 sd_data[kHeaderSize + 1 * kFunctionEntrySize + kFunctionEntryEndOffset] = 0;
14966 v8::TryCatch try_catch;
14967
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000014968 Local<String> source = String::NewFromUtf8(isolate, script);
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014969 Local<Script> compiled_script = Script::New(source, NULL, sd);
14970 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000014971 String::Utf8Value exception_value(try_catch.Message()->Get());
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014972 CHECK_EQ("Uncaught SyntaxError: Invalid preparser data for function bar",
14973 *exception_value);
14974
14975 try_catch.Reset();
lrn@chromium.orgd4e9e222011-08-03 12:01:58 +000014976
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014977 // Overwrite function bar's start position with 200. The function entry
lrn@chromium.orgd4e9e222011-08-03 12:01:58 +000014978 // will not be found when searching for it by position and we should fall
14979 // back on eager compilation.
machenbach@chromium.org4ddd2f12014-01-14 08:13:44 +000014980 sd = v8::ScriptData::PreCompile(v8::String::NewFromUtf8(
14981 isolate, script, v8::String::kNormalString, i::StrLength(script)));
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +000014982 sd_data = reinterpret_cast<unsigned*>(const_cast<char*>(sd->Data()));
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014983 sd_data[kHeaderSize + 1 * kFunctionEntrySize + kFunctionEntryStartOffset] =
14984 200;
14985 compiled_script = Script::New(source, NULL, sd);
lrn@chromium.orgd4e9e222011-08-03 12:01:58 +000014986 CHECK(!try_catch.HasCaught());
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014987
14988 delete sd;
14989}
14990
14991
ager@chromium.orga74f0da2008-12-03 16:05:52 +000014992// This tests that we do not allow dictionary load/call inline caches
14993// to use functions that have not yet been compiled. The potential
14994// problem of loading a function that has not yet been compiled can
14995// arise because we share code between contexts via the compilation
14996// cache.
14997THREADED_TEST(DictionaryICLoadedFunction) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014998 v8::HandleScope scope(CcTest::isolate());
ager@chromium.orga74f0da2008-12-03 16:05:52 +000014999 // Test LoadIC.
15000 for (int i = 0; i < 2; i++) {
15001 LocalContext context;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000015002 context->Global()->Set(v8_str("tmp"), v8::True(CcTest::isolate()));
ager@chromium.orga74f0da2008-12-03 16:05:52 +000015003 context->Global()->Delete(v8_str("tmp"));
15004 CompileRun("for (var j = 0; j < 10; j++) new RegExp('');");
15005 }
15006 // Test CallIC.
15007 for (int i = 0; i < 2; i++) {
15008 LocalContext context;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000015009 context->Global()->Set(v8_str("tmp"), v8::True(CcTest::isolate()));
ager@chromium.orga74f0da2008-12-03 16:05:52 +000015010 context->Global()->Delete(v8_str("tmp"));
15011 CompileRun("for (var j = 0; j < 10; j++) RegExp('')");
15012 }
15013}
ager@chromium.orgddb913d2009-01-27 10:01:48 +000015014
15015
15016// Test that cross-context new calls use the context of the callee to
15017// create the new JavaScript object.
15018THREADED_TEST(CrossContextNew) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015019 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000015020 v8::HandleScope scope(isolate);
15021 v8::Local<Context> context0 = Context::New(isolate);
15022 v8::Local<Context> context1 = Context::New(isolate);
ager@chromium.orgddb913d2009-01-27 10:01:48 +000015023
15024 // Allow cross-domain access.
15025 Local<String> token = v8_str("<security token>");
15026 context0->SetSecurityToken(token);
15027 context1->SetSecurityToken(token);
15028
15029 // Set an 'x' property on the Object prototype and define a
15030 // constructor function in context0.
15031 context0->Enter();
15032 CompileRun("Object.prototype.x = 42; function C() {};");
15033 context0->Exit();
15034
15035 // Call the constructor function from context0 and check that the
15036 // result has the 'x' property.
15037 context1->Enter();
15038 context1->Global()->Set(v8_str("other"), context0->Global());
15039 Local<Value> value = CompileRun("var instance = new other.C(); instance.x");
15040 CHECK(value->IsInt32());
15041 CHECK_EQ(42, value->Int32Value());
15042 context1->Exit();
ager@chromium.orgddb913d2009-01-27 10:01:48 +000015043}
ager@chromium.org381abbb2009-02-25 13:23:22 +000015044
15045
ager@chromium.org3b45ab52009-03-19 22:21:34 +000015046// Verify that we can clone an object
15047TEST(ObjectClone) {
ager@chromium.org3b45ab52009-03-19 22:21:34 +000015048 LocalContext env;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015049 v8::Isolate* isolate = env->GetIsolate();
15050 v8::HandleScope scope(isolate);
ager@chromium.org3b45ab52009-03-19 22:21:34 +000015051
15052 const char* sample =
15053 "var rv = {};" \
15054 "rv.alpha = 'hello';" \
15055 "rv.beta = 123;" \
15056 "rv;";
15057
15058 // Create an object, verify basics.
15059 Local<Value> val = CompileRun(sample);
15060 CHECK(val->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000015061 Local<v8::Object> obj = val.As<v8::Object>();
ager@chromium.org3b45ab52009-03-19 22:21:34 +000015062 obj->Set(v8_str("gamma"), v8_str("cloneme"));
15063
15064 CHECK_EQ(v8_str("hello"), obj->Get(v8_str("alpha")));
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015065 CHECK_EQ(v8::Integer::New(isolate, 123), obj->Get(v8_str("beta")));
ager@chromium.org3b45ab52009-03-19 22:21:34 +000015066 CHECK_EQ(v8_str("cloneme"), obj->Get(v8_str("gamma")));
15067
15068 // Clone it.
15069 Local<v8::Object> clone = obj->Clone();
15070 CHECK_EQ(v8_str("hello"), clone->Get(v8_str("alpha")));
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015071 CHECK_EQ(v8::Integer::New(isolate, 123), clone->Get(v8_str("beta")));
ager@chromium.org3b45ab52009-03-19 22:21:34 +000015072 CHECK_EQ(v8_str("cloneme"), clone->Get(v8_str("gamma")));
15073
15074 // Set a property on the clone, verify each object.
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015075 clone->Set(v8_str("beta"), v8::Integer::New(isolate, 456));
15076 CHECK_EQ(v8::Integer::New(isolate, 123), obj->Get(v8_str("beta")));
15077 CHECK_EQ(v8::Integer::New(isolate, 456), clone->Get(v8_str("beta")));
ager@chromium.org3b45ab52009-03-19 22:21:34 +000015078}
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015079
15080
ager@chromium.org5ec48922009-05-05 07:25:34 +000015081class AsciiVectorResource : public v8::String::ExternalAsciiStringResource {
15082 public:
15083 explicit AsciiVectorResource(i::Vector<const char> vector)
15084 : data_(vector) {}
15085 virtual ~AsciiVectorResource() {}
15086 virtual size_t length() const { return data_.length(); }
15087 virtual const char* data() const { return data_.start(); }
15088 private:
15089 i::Vector<const char> data_;
15090};
15091
15092
15093class UC16VectorResource : public v8::String::ExternalStringResource {
15094 public:
15095 explicit UC16VectorResource(i::Vector<const i::uc16> vector)
15096 : data_(vector) {}
15097 virtual ~UC16VectorResource() {}
15098 virtual size_t length() const { return data_.length(); }
15099 virtual const i::uc16* data() const { return data_.start(); }
15100 private:
15101 i::Vector<const i::uc16> data_;
15102};
15103
15104
15105static void MorphAString(i::String* string,
15106 AsciiVectorResource* ascii_resource,
15107 UC16VectorResource* uc16_resource) {
15108 CHECK(i::StringShape(string).IsExternal());
ulan@chromium.org8e8d8822012-11-23 14:36:46 +000015109 if (string->IsOneByteRepresentation()) {
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +000015110 // Check old map is not internalized or long.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015111 CHECK(string->map() == CcTest::heap()->external_ascii_string_map());
ager@chromium.org5ec48922009-05-05 07:25:34 +000015112 // Morph external string to be TwoByte string.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015113 string->set_map(CcTest::heap()->external_string_map());
ager@chromium.org5ec48922009-05-05 07:25:34 +000015114 i::ExternalTwoByteString* morphed =
15115 i::ExternalTwoByteString::cast(string);
15116 morphed->set_resource(uc16_resource);
15117 } else {
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +000015118 // Check old map is not internalized or long.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015119 CHECK(string->map() == CcTest::heap()->external_string_map());
ager@chromium.org5ec48922009-05-05 07:25:34 +000015120 // Morph external string to be ASCII string.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015121 string->set_map(CcTest::heap()->external_ascii_string_map());
ager@chromium.org5ec48922009-05-05 07:25:34 +000015122 i::ExternalAsciiString* morphed =
15123 i::ExternalAsciiString::cast(string);
15124 morphed->set_resource(ascii_resource);
15125 }
15126}
15127
15128
15129// Test that we can still flatten a string if the components it is built up
15130// from have been turned into 16 bit strings in the mean time.
15131THREADED_TEST(MorphCompositeStringTest) {
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +000015132 char utf_buffer[129];
ager@chromium.org5ec48922009-05-05 07:25:34 +000015133 const char* c_string = "Now is the time for all good men"
15134 " to come to the aid of the party";
15135 uint16_t* two_byte_string = AsciiToTwoByteString(c_string);
15136 {
ager@chromium.org5ec48922009-05-05 07:25:34 +000015137 LocalContext env;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015138 i::Factory* factory = CcTest::i_isolate()->factory();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015139 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org5ec48922009-05-05 07:25:34 +000015140 AsciiVectorResource ascii_resource(
ager@chromium.orgc4c92722009-11-18 14:12:51 +000015141 i::Vector<const char>(c_string, i::StrLength(c_string)));
ager@chromium.org5ec48922009-05-05 07:25:34 +000015142 UC16VectorResource uc16_resource(
ager@chromium.orgc4c92722009-11-18 14:12:51 +000015143 i::Vector<const uint16_t>(two_byte_string,
15144 i::StrLength(c_string)));
ager@chromium.org5ec48922009-05-05 07:25:34 +000015145
15146 Local<String> lhs(v8::Utils::ToLocal(
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000015147 factory->NewExternalStringFromAscii(&ascii_resource)));
ager@chromium.org5ec48922009-05-05 07:25:34 +000015148 Local<String> rhs(v8::Utils::ToLocal(
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000015149 factory->NewExternalStringFromAscii(&ascii_resource)));
ager@chromium.org5ec48922009-05-05 07:25:34 +000015150
15151 env->Global()->Set(v8_str("lhs"), lhs);
15152 env->Global()->Set(v8_str("rhs"), rhs);
15153
15154 CompileRun(
15155 "var cons = lhs + rhs;"
15156 "var slice = lhs.substring(1, lhs.length - 1);"
15157 "var slice_on_cons = (lhs + rhs).substring(1, lhs.length *2 - 1);");
15158
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015159 CHECK(lhs->IsOneByte());
15160 CHECK(rhs->IsOneByte());
rossberg@chromium.org2c067b12012-03-19 11:01:52 +000015161
ager@chromium.org5ec48922009-05-05 07:25:34 +000015162 MorphAString(*v8::Utils::OpenHandle(*lhs), &ascii_resource, &uc16_resource);
15163 MorphAString(*v8::Utils::OpenHandle(*rhs), &ascii_resource, &uc16_resource);
15164
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +000015165 // This should UTF-8 without flattening, since everything is ASCII.
15166 Handle<String> cons = v8_compile("cons")->Run().As<String>();
15167 CHECK_EQ(128, cons->Utf8Length());
15168 int nchars = -1;
15169 CHECK_EQ(129, cons->WriteUtf8(utf_buffer, -1, &nchars));
15170 CHECK_EQ(128, nchars);
15171 CHECK_EQ(0, strcmp(
15172 utf_buffer,
15173 "Now is the time for all good men to come to the aid of the party"
15174 "Now is the time for all good men to come to the aid of the party"));
15175
ager@chromium.org5ec48922009-05-05 07:25:34 +000015176 // Now do some stuff to make sure the strings are flattened, etc.
15177 CompileRun(
15178 "/[^a-z]/.test(cons);"
15179 "/[^a-z]/.test(slice);"
15180 "/[^a-z]/.test(slice_on_cons);");
15181 const char* expected_cons =
15182 "Now is the time for all good men to come to the aid of the party"
15183 "Now is the time for all good men to come to the aid of the party";
15184 const char* expected_slice =
15185 "ow is the time for all good men to come to the aid of the part";
15186 const char* expected_slice_on_cons =
15187 "ow is the time for all good men to come to the aid of the party"
15188 "Now is the time for all good men to come to the aid of the part";
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015189 CHECK_EQ(String::NewFromUtf8(env->GetIsolate(), expected_cons),
ager@chromium.org5ec48922009-05-05 07:25:34 +000015190 env->Global()->Get(v8_str("cons")));
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015191 CHECK_EQ(String::NewFromUtf8(env->GetIsolate(), expected_slice),
ager@chromium.org5ec48922009-05-05 07:25:34 +000015192 env->Global()->Get(v8_str("slice")));
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015193 CHECK_EQ(String::NewFromUtf8(env->GetIsolate(), expected_slice_on_cons),
ager@chromium.org5ec48922009-05-05 07:25:34 +000015194 env->Global()->Get(v8_str("slice_on_cons")));
15195 }
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000015196 i::DeleteArray(two_byte_string);
ager@chromium.org5ec48922009-05-05 07:25:34 +000015197}
15198
15199
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000015200TEST(CompileExternalTwoByteSource) {
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000015201 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015202 v8::HandleScope scope(context->GetIsolate());
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000015203
15204 // This is a very short list of sources, which currently is to check for a
15205 // regression caused by r2703.
15206 const char* ascii_sources[] = {
15207 "0.5",
15208 "-0.5", // This mainly testes PushBack in the Scanner.
15209 "--0.5", // This mainly testes PushBack in the Scanner.
15210 NULL
15211 };
15212
15213 // Compile the sources as external two byte strings.
15214 for (int i = 0; ascii_sources[i] != NULL; i++) {
15215 uint16_t* two_byte_string = AsciiToTwoByteString(ascii_sources[i]);
15216 UC16VectorResource uc16_resource(
ager@chromium.orgc4c92722009-11-18 14:12:51 +000015217 i::Vector<const uint16_t>(two_byte_string,
15218 i::StrLength(ascii_sources[i])));
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000015219 v8::Local<v8::String> source =
15220 v8::String::NewExternal(context->GetIsolate(), &uc16_resource);
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000015221 v8::Script::Compile(source);
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000015222 i::DeleteArray(two_byte_string);
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000015223 }
15224}
15225
15226
mstarzinger@chromium.orgb4968be2013-10-16 09:00:56 +000015227#ifndef V8_INTERPRETED_REGEXP
15228
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +000015229struct RegExpInterruptionData {
15230 int loop_count;
15231 UC16VectorResource* string_resource;
15232 v8::Persistent<v8::String> string;
15233} regexp_interruption_data;
15234
15235
15236class RegExpInterruptionThread : public i::Thread {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015237 public:
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +000015238 explicit RegExpInterruptionThread(v8::Isolate* isolate)
15239 : Thread("TimeoutThread"), isolate_(isolate) {}
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000015240
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +000015241 virtual void Run() {
15242 for (regexp_interruption_data.loop_count = 0;
15243 regexp_interruption_data.loop_count < 7;
15244 regexp_interruption_data.loop_count++) {
15245 i::OS::Sleep(50); // Wait a bit before requesting GC.
15246 reinterpret_cast<i::Isolate*>(isolate_)->stack_guard()->RequestGC();
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015247 }
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +000015248 i::OS::Sleep(50); // Wait a bit before terminating.
15249 v8::V8::TerminateExecution(isolate_);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015250 }
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015251
jkummerow@chromium.orge297f592011-06-08 10:05:15 +000015252 private:
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +000015253 v8::Isolate* isolate_;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015254};
15255
15256
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +000015257void RunBeforeGC(v8::GCType type, v8::GCCallbackFlags flags) {
15258 if (regexp_interruption_data.loop_count != 2) return;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015259 v8::HandleScope scope(CcTest::isolate());
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +000015260 v8::Local<v8::String> string = v8::Local<v8::String>::New(
15261 CcTest::isolate(), regexp_interruption_data.string);
15262 string->MakeExternal(regexp_interruption_data.string_resource);
15263}
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015264
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015265
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +000015266// Test that RegExp execution can be interrupted. Specifically, we test
15267// * interrupting with GC
15268// * turn the subject string from one-byte internal to two-byte external string
15269// * force termination
15270TEST(RegExpInterruption) {
15271 v8::HandleScope scope(CcTest::isolate());
15272 LocalContext env;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015273
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +000015274 RegExpInterruptionThread timeout_thread(CcTest::isolate());
15275
15276 v8::V8::AddGCPrologueCallback(RunBeforeGC);
15277 static const char* ascii_content = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
15278 i::uc16* uc16_content = AsciiToTwoByteString(ascii_content);
15279 v8::Local<v8::String> string = v8_str(ascii_content);
15280
15281 CcTest::global()->Set(v8_str("a"), string);
15282 regexp_interruption_data.string.Reset(CcTest::isolate(), string);
15283 regexp_interruption_data.string_resource = new UC16VectorResource(
15284 i::Vector<const i::uc16>(uc16_content, i::StrLength(ascii_content)));
15285
15286 v8::TryCatch try_catch;
15287 timeout_thread.Start();
15288
15289 CompileRun("/((a*)*)*b/.exec(a)");
15290 CHECK(try_catch.HasTerminated());
15291
15292 timeout_thread.Join();
15293
15294 delete regexp_interruption_data.string_resource;
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015295 regexp_interruption_data.string.Reset();
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015296}
15297
mstarzinger@chromium.orgb4968be2013-10-16 09:00:56 +000015298#endif // V8_INTERPRETED_REGEXP
15299
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015300
mmassi@chromium.org7028c052012-06-13 11:51:58 +000015301// Test that we cannot set a property on the global object if there
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015302// is a read-only property in the prototype chain.
15303TEST(ReadOnlyPropertyInGlobalProto) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +000015304 i::FLAG_es5_readonly = true;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015305 v8::Isolate* isolate = CcTest::isolate();
15306 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000015307 v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015308 LocalContext context(0, templ);
15309 v8::Handle<v8::Object> global = context->Global();
15310 v8::Handle<v8::Object> global_proto =
15311 v8::Handle<v8::Object>::Cast(global->Get(v8_str("__proto__")));
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015312 global_proto->Set(v8_str("x"), v8::Integer::New(isolate, 0), v8::ReadOnly);
15313 global_proto->Set(v8_str("y"), v8::Integer::New(isolate, 0), v8::ReadOnly);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015314 // Check without 'eval' or 'with'.
15315 v8::Handle<v8::Value> res =
15316 CompileRun("function f() { x = 42; return x; }; f()");
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015317 CHECK_EQ(v8::Integer::New(isolate, 0), res);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015318 // Check with 'eval'.
mmassi@chromium.org7028c052012-06-13 11:51:58 +000015319 res = CompileRun("function f() { eval('1'); y = 43; return y; }; f()");
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015320 CHECK_EQ(v8::Integer::New(isolate, 0), res);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015321 // Check with 'with'.
mmassi@chromium.org7028c052012-06-13 11:51:58 +000015322 res = CompileRun("function f() { with (this) { y = 44 }; return y; }; f()");
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015323 CHECK_EQ(v8::Integer::New(isolate, 0), res);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015324}
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015325
15326static int force_set_set_count = 0;
15327static int force_set_get_count = 0;
15328bool pass_on_get = false;
15329
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015330static void ForceSetGetter(v8::Local<v8::String> name,
15331 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015332 force_set_get_count++;
15333 if (pass_on_get) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015334 return;
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015335 }
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015336 info.GetReturnValue().Set(3);
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015337}
15338
15339static void ForceSetSetter(v8::Local<v8::String> name,
15340 v8::Local<v8::Value> value,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015341 const v8::PropertyCallbackInfo<void>& info) {
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015342 force_set_set_count++;
15343}
15344
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015345static void ForceSetInterceptSetter(
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015346 v8::Local<v8::String> name,
15347 v8::Local<v8::Value> value,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015348 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015349 force_set_set_count++;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015350 info.GetReturnValue().SetUndefined();
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015351}
15352
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000015353
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015354TEST(ForceSet) {
15355 force_set_get_count = 0;
15356 force_set_set_count = 0;
15357 pass_on_get = false;
15358
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015359 v8::Isolate* isolate = CcTest::isolate();
15360 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000015361 v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015362 v8::Handle<v8::String> access_property =
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015363 v8::String::NewFromUtf8(isolate, "a");
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015364 templ->SetAccessor(access_property, ForceSetGetter, ForceSetSetter);
15365 LocalContext context(NULL, templ);
15366 v8::Handle<v8::Object> global = context->Global();
15367
15368 // Ordinary properties
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015369 v8::Handle<v8::String> simple_property =
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015370 v8::String::NewFromUtf8(isolate, "p");
15371 global->Set(simple_property, v8::Int32::New(isolate, 4), v8::ReadOnly);
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015372 CHECK_EQ(4, global->Get(simple_property)->Int32Value());
15373 // This should fail because the property is read-only
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015374 global->Set(simple_property, v8::Int32::New(isolate, 5));
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015375 CHECK_EQ(4, global->Get(simple_property)->Int32Value());
15376 // This should succeed even though the property is read-only
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015377 global->ForceSet(simple_property, v8::Int32::New(isolate, 6));
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015378 CHECK_EQ(6, global->Get(simple_property)->Int32Value());
15379
15380 // Accessors
15381 CHECK_EQ(0, force_set_set_count);
15382 CHECK_EQ(0, force_set_get_count);
15383 CHECK_EQ(3, global->Get(access_property)->Int32Value());
15384 // CHECK_EQ the property shouldn't override it, just call the setter
15385 // which in this case does nothing.
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015386 global->Set(access_property, v8::Int32::New(isolate, 7));
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015387 CHECK_EQ(3, global->Get(access_property)->Int32Value());
15388 CHECK_EQ(1, force_set_set_count);
15389 CHECK_EQ(2, force_set_get_count);
15390 // Forcing the property to be set should override the accessor without
15391 // calling it
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015392 global->ForceSet(access_property, v8::Int32::New(isolate, 8));
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015393 CHECK_EQ(8, global->Get(access_property)->Int32Value());
15394 CHECK_EQ(1, force_set_set_count);
15395 CHECK_EQ(2, force_set_get_count);
15396}
15397
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000015398
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015399TEST(ForceSetWithInterceptor) {
15400 force_set_get_count = 0;
15401 force_set_set_count = 0;
15402 pass_on_get = false;
15403
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015404 v8::Isolate* isolate = CcTest::isolate();
15405 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000015406 v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015407 templ->SetNamedPropertyHandler(ForceSetGetter, ForceSetInterceptSetter);
15408 LocalContext context(NULL, templ);
15409 v8::Handle<v8::Object> global = context->Global();
15410
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015411 v8::Handle<v8::String> some_property =
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015412 v8::String::NewFromUtf8(isolate, "a");
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015413 CHECK_EQ(0, force_set_set_count);
15414 CHECK_EQ(0, force_set_get_count);
15415 CHECK_EQ(3, global->Get(some_property)->Int32Value());
15416 // Setting the property shouldn't override it, just call the setter
15417 // which in this case does nothing.
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015418 global->Set(some_property, v8::Int32::New(isolate, 7));
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015419 CHECK_EQ(3, global->Get(some_property)->Int32Value());
15420 CHECK_EQ(1, force_set_set_count);
15421 CHECK_EQ(2, force_set_get_count);
15422 // Getting the property when the interceptor returns an empty handle
15423 // should yield undefined, since the property isn't present on the
15424 // object itself yet.
15425 pass_on_get = true;
15426 CHECK(global->Get(some_property)->IsUndefined());
15427 CHECK_EQ(1, force_set_set_count);
15428 CHECK_EQ(3, force_set_get_count);
15429 // Forcing the property to be set should cause the value to be
15430 // set locally without calling the interceptor.
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015431 global->ForceSet(some_property, v8::Int32::New(isolate, 8));
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015432 CHECK_EQ(8, global->Get(some_property)->Int32Value());
15433 CHECK_EQ(1, force_set_set_count);
15434 CHECK_EQ(4, force_set_get_count);
15435 // Reenabling the interceptor should cause it to take precedence over
15436 // the property
15437 pass_on_get = false;
15438 CHECK_EQ(3, global->Get(some_property)->Int32Value());
15439 CHECK_EQ(1, force_set_set_count);
15440 CHECK_EQ(5, force_set_get_count);
15441 // The interceptor should also work for other properties
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015442 CHECK_EQ(3, global->Get(v8::String::NewFromUtf8(isolate, "b"))
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015443 ->Int32Value());
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015444 CHECK_EQ(1, force_set_set_count);
15445 CHECK_EQ(6, force_set_get_count);
15446}
ager@chromium.org1bf0cd02009-05-20 11:34:19 +000015447
15448
ager@chromium.orge2902be2009-06-08 12:21:35 +000015449THREADED_TEST(ForceDelete) {
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015450 v8::Isolate* isolate = CcTest::isolate();
15451 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000015452 v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
ager@chromium.orge2902be2009-06-08 12:21:35 +000015453 LocalContext context(NULL, templ);
15454 v8::Handle<v8::Object> global = context->Global();
15455
15456 // Ordinary properties
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015457 v8::Handle<v8::String> simple_property =
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015458 v8::String::NewFromUtf8(isolate, "p");
15459 global->Set(simple_property, v8::Int32::New(isolate, 4), v8::DontDelete);
ager@chromium.orge2902be2009-06-08 12:21:35 +000015460 CHECK_EQ(4, global->Get(simple_property)->Int32Value());
15461 // This should fail because the property is dont-delete.
15462 CHECK(!global->Delete(simple_property));
15463 CHECK_EQ(4, global->Get(simple_property)->Int32Value());
15464 // This should succeed even though the property is dont-delete.
15465 CHECK(global->ForceDelete(simple_property));
15466 CHECK(global->Get(simple_property)->IsUndefined());
15467}
15468
15469
15470static int force_delete_interceptor_count = 0;
15471static bool pass_on_delete = false;
15472
15473
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015474static void ForceDeleteDeleter(
ager@chromium.orge2902be2009-06-08 12:21:35 +000015475 v8::Local<v8::String> name,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015476 const v8::PropertyCallbackInfo<v8::Boolean>& info) {
ager@chromium.orge2902be2009-06-08 12:21:35 +000015477 force_delete_interceptor_count++;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015478 if (pass_on_delete) return;
15479 info.GetReturnValue().Set(true);
ager@chromium.orge2902be2009-06-08 12:21:35 +000015480}
15481
15482
15483THREADED_TEST(ForceDeleteWithInterceptor) {
15484 force_delete_interceptor_count = 0;
15485 pass_on_delete = false;
15486
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015487 v8::Isolate* isolate = CcTest::isolate();
15488 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000015489 v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
ager@chromium.orge2902be2009-06-08 12:21:35 +000015490 templ->SetNamedPropertyHandler(0, 0, 0, ForceDeleteDeleter);
15491 LocalContext context(NULL, templ);
15492 v8::Handle<v8::Object> global = context->Global();
15493
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015494 v8::Handle<v8::String> some_property =
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015495 v8::String::NewFromUtf8(isolate, "a");
15496 global->Set(some_property, v8::Integer::New(isolate, 42), v8::DontDelete);
ager@chromium.orge2902be2009-06-08 12:21:35 +000015497
15498 // Deleting a property should get intercepted and nothing should
15499 // happen.
15500 CHECK_EQ(0, force_delete_interceptor_count);
15501 CHECK(global->Delete(some_property));
15502 CHECK_EQ(1, force_delete_interceptor_count);
15503 CHECK_EQ(42, global->Get(some_property)->Int32Value());
15504 // Deleting the property when the interceptor returns an empty
15505 // handle should not delete the property since it is DontDelete.
15506 pass_on_delete = true;
15507 CHECK(!global->Delete(some_property));
15508 CHECK_EQ(2, force_delete_interceptor_count);
15509 CHECK_EQ(42, global->Get(some_property)->Int32Value());
15510 // Forcing the property to be deleted should delete the value
15511 // without calling the interceptor.
15512 CHECK(global->ForceDelete(some_property));
15513 CHECK(global->Get(some_property)->IsUndefined());
15514 CHECK_EQ(2, force_delete_interceptor_count);
15515}
15516
15517
kasperl@chromium.org68ac0092009-07-09 06:00:35 +000015518// Make sure that forcing a delete invalidates any IC stubs, so we
15519// don't read the hole value.
15520THREADED_TEST(ForceDeleteIC) {
kasperl@chromium.org68ac0092009-07-09 06:00:35 +000015521 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015522 v8::HandleScope scope(context->GetIsolate());
kasperl@chromium.org68ac0092009-07-09 06:00:35 +000015523 // Create a DontDelete variable on the global object.
15524 CompileRun("this.__proto__ = { foo: 'horse' };"
15525 "var foo = 'fish';"
15526 "function f() { return foo.length; }");
15527 // Initialize the IC for foo in f.
15528 CompileRun("for (var i = 0; i < 4; i++) f();");
15529 // Make sure the value of foo is correct before the deletion.
15530 CHECK_EQ(4, CompileRun("f()")->Int32Value());
15531 // Force the deletion of foo.
15532 CHECK(context->Global()->ForceDelete(v8_str("foo")));
15533 // Make sure the value for foo is read from the prototype, and that
15534 // we don't get in trouble with reading the deleted cell value
15535 // sentinel.
15536 CHECK_EQ(5, CompileRun("f()")->Int32Value());
15537}
15538
15539
mstarzinger@chromium.org88d326b2012-04-23 12:57:22 +000015540TEST(InlinedFunctionAcrossContexts) {
15541 i::FLAG_allow_natives_syntax = true;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015542 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000015543 v8::HandleScope outer_scope(isolate);
15544 v8::Local<v8::Context> ctx1 = v8::Context::New(isolate);
15545 v8::Local<v8::Context> ctx2 = v8::Context::New(isolate);
mstarzinger@chromium.org88d326b2012-04-23 12:57:22 +000015546 ctx1->Enter();
15547
15548 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015549 v8::HandleScope inner_scope(CcTest::isolate());
mstarzinger@chromium.org88d326b2012-04-23 12:57:22 +000015550 CompileRun("var G = 42; function foo() { return G; }");
15551 v8::Local<v8::Value> foo = ctx1->Global()->Get(v8_str("foo"));
15552 ctx2->Enter();
15553 ctx2->Global()->Set(v8_str("o"), foo);
15554 v8::Local<v8::Value> res = CompileRun(
15555 "function f() { return o(); }"
15556 "for (var i = 0; i < 10; ++i) f();"
15557 "%OptimizeFunctionOnNextCall(f);"
15558 "f();");
15559 CHECK_EQ(42, res->Int32Value());
15560 ctx2->Exit();
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015561 v8::Handle<v8::String> G_property =
15562 v8::String::NewFromUtf8(CcTest::isolate(), "G");
mstarzinger@chromium.org88d326b2012-04-23 12:57:22 +000015563 CHECK(ctx1->Global()->ForceDelete(G_property));
15564 ctx2->Enter();
15565 ExpectString(
15566 "(function() {"
15567 " try {"
15568 " return f();"
15569 " } catch(e) {"
15570 " return e.toString();"
15571 " }"
15572 " })()",
15573 "ReferenceError: G is not defined");
15574 ctx2->Exit();
15575 ctx1->Exit();
mstarzinger@chromium.org88d326b2012-04-23 12:57:22 +000015576 }
mstarzinger@chromium.org88d326b2012-04-23 12:57:22 +000015577}
15578
15579
ulan@chromium.org57ff8812013-05-10 08:16:55 +000015580static v8::Local<Context> calling_context0;
15581static v8::Local<Context> calling_context1;
15582static v8::Local<Context> calling_context2;
ager@chromium.org1bf0cd02009-05-20 11:34:19 +000015583
15584
15585// Check that the call to the callback is initiated in
15586// calling_context2, the directly calling context is calling_context1
15587// and the callback itself is in calling_context0.
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015588static void GetCallingContextCallback(
15589 const v8::FunctionCallbackInfo<v8::Value>& args) {
ager@chromium.org1bf0cd02009-05-20 11:34:19 +000015590 ApiTestFuzzer::Fuzz();
mvstanton@chromium.org40ce96b2013-04-09 09:52:22 +000015591 CHECK(args.GetIsolate()->GetCurrentContext() == calling_context0);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015592 CHECK(args.GetIsolate()->GetCallingContext() == calling_context1);
15593 CHECK(args.GetIsolate()->GetEnteredContext() == calling_context2);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015594 args.GetReturnValue().Set(42);
15595}
15596
15597
15598THREADED_TEST(GetCurrentContextWhenNotInContext) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015599 i::Isolate* isolate = CcTest::i_isolate();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015600 CHECK(isolate != NULL);
15601 CHECK(isolate->context() == NULL);
15602 v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
15603 v8::HandleScope scope(v8_isolate);
15604 // The following should not crash, but return an empty handle.
15605 v8::Local<v8::Context> current = v8_isolate->GetCurrentContext();
15606 CHECK(current.IsEmpty());
ager@chromium.org1bf0cd02009-05-20 11:34:19 +000015607}
15608
15609
15610THREADED_TEST(GetCallingContext) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015611 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000015612 v8::HandleScope scope(isolate);
ager@chromium.org1bf0cd02009-05-20 11:34:19 +000015613
ulan@chromium.org57ff8812013-05-10 08:16:55 +000015614 Local<Context> calling_context0(Context::New(isolate));
15615 Local<Context> calling_context1(Context::New(isolate));
15616 Local<Context> calling_context2(Context::New(isolate));
15617 ::calling_context0 = calling_context0;
15618 ::calling_context1 = calling_context1;
15619 ::calling_context2 = calling_context2;
ager@chromium.org1bf0cd02009-05-20 11:34:19 +000015620
15621 // Allow cross-domain access.
15622 Local<String> token = v8_str("<security token>");
15623 calling_context0->SetSecurityToken(token);
15624 calling_context1->SetSecurityToken(token);
15625 calling_context2->SetSecurityToken(token);
15626
15627 // Create an object with a C++ callback in context0.
15628 calling_context0->Enter();
15629 Local<v8::FunctionTemplate> callback_templ =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000015630 v8::FunctionTemplate::New(isolate, GetCallingContextCallback);
ager@chromium.org1bf0cd02009-05-20 11:34:19 +000015631 calling_context0->Global()->Set(v8_str("callback"),
15632 callback_templ->GetFunction());
15633 calling_context0->Exit();
15634
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000015635 // Expose context0 in context1 and set up a function that calls the
ager@chromium.org1bf0cd02009-05-20 11:34:19 +000015636 // callback function.
15637 calling_context1->Enter();
15638 calling_context1->Global()->Set(v8_str("context0"),
15639 calling_context0->Global());
15640 CompileRun("function f() { context0.callback() }");
15641 calling_context1->Exit();
15642
15643 // Expose context1 in context2 and call the callback function in
15644 // context0 indirectly through f in context1.
15645 calling_context2->Enter();
15646 calling_context2->Global()->Set(v8_str("context1"),
15647 calling_context1->Global());
15648 CompileRun("context1.f()");
15649 calling_context2->Exit();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000015650 ::calling_context0.Clear();
15651 ::calling_context1.Clear();
15652 ::calling_context2.Clear();
ager@chromium.org1bf0cd02009-05-20 11:34:19 +000015653}
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000015654
15655
15656// Check that a variable declaration with no explicit initialization
erik.corry@gmail.comed49e962012-04-17 11:57:53 +000015657// value does shadow an existing property in the prototype chain.
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000015658THREADED_TEST(InitGlobalVarInProtoChain) {
mstarzinger@chromium.org88d326b2012-04-23 12:57:22 +000015659 i::FLAG_es52_globals = true;
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000015660 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015661 v8::HandleScope scope(context->GetIsolate());
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000015662 // Introduce a variable in the prototype chain.
15663 CompileRun("__proto__.x = 42");
erik.corry@gmail.comed49e962012-04-17 11:57:53 +000015664 v8::Handle<v8::Value> result = CompileRun("var x = 43; x");
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000015665 CHECK(!result->IsUndefined());
erik.corry@gmail.comed49e962012-04-17 11:57:53 +000015666 CHECK_EQ(43, result->Int32Value());
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000015667}
kasperl@chromium.org68ac0092009-07-09 06:00:35 +000015668
15669
15670// Regression test for issue 398.
15671// If a function is added to an object, creating a constant function
15672// field, and the result is cloned, replacing the constant function on the
15673// original should not affect the clone.
15674// See http://code.google.com/p/v8/issues/detail?id=398
15675THREADED_TEST(ReplaceConstantFunction) {
kasperl@chromium.org68ac0092009-07-09 06:00:35 +000015676 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000015677 v8::Isolate* isolate = context->GetIsolate();
15678 v8::HandleScope scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015679 v8::Handle<v8::Object> obj = v8::Object::New(isolate);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000015680 v8::Handle<v8::FunctionTemplate> func_templ =
15681 v8::FunctionTemplate::New(isolate);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015682 v8::Handle<v8::String> foo_string =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000015683 v8::String::NewFromUtf8(isolate, "foo");
kasperl@chromium.org68ac0092009-07-09 06:00:35 +000015684 obj->Set(foo_string, func_templ->GetFunction());
15685 v8::Handle<v8::Object> obj_clone = obj->Clone();
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015686 obj_clone->Set(foo_string,
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000015687 v8::String::NewFromUtf8(isolate, "Hello"));
kasperl@chromium.org68ac0092009-07-09 06:00:35 +000015688 CHECK(!obj->Get(foo_string)->IsUndefined());
15689}
kasperl@chromium.orge959c182009-07-27 08:59:04 +000015690
15691
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015692static void CheckElementValue(i::Isolate* isolate,
15693 int expected,
15694 i::Handle<i::Object> obj,
15695 int offset) {
15696 i::Object* element = obj->GetElement(isolate, offset)->ToObjectChecked();
15697 CHECK_EQ(expected, i::Smi::cast(element)->value());
15698}
15699
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015700
15701THREADED_TEST(PixelArray) {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015702 LocalContext context;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015703 i::Isolate* isolate = CcTest::i_isolate();
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015704 i::Factory* factory = isolate->factory();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015705 v8::HandleScope scope(context->GetIsolate());
ager@chromium.orgc4c92722009-11-18 14:12:51 +000015706 const int kElementCount = 260;
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015707 uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(kElementCount));
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000015708 i::Handle<i::ExternalUint8ClampedArray> pixels =
15709 i::Handle<i::ExternalUint8ClampedArray>::cast(
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000015710 factory->NewExternalArray(kElementCount,
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000015711 v8::kExternalUint8ClampedArray,
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000015712 pixel_data));
15713 // Force GC to trigger verification.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015714 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015715 for (int i = 0; i < kElementCount; i++) {
ager@chromium.orgc4c92722009-11-18 14:12:51 +000015716 pixels->set(i, i % 256);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015717 }
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000015718 // Force GC to trigger verification.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015719 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015720 for (int i = 0; i < kElementCount; i++) {
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +000015721 CHECK_EQ(i % 256, pixels->get_scalar(i));
ager@chromium.orgc4c92722009-11-18 14:12:51 +000015722 CHECK_EQ(i % 256, pixel_data[i]);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015723 }
15724
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015725 v8::Handle<v8::Object> obj = v8::Object::New(context->GetIsolate());
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015726 i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
15727 // Set the elements to be the pixels.
15728 // jsobj->set_elements(*pixels);
15729 obj->SetIndexedPropertiesToPixelData(pixel_data, kElementCount);
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015730 CheckElementValue(isolate, 1, jsobj, 1);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015731 obj->Set(v8_str("field"), v8::Int32::New(CcTest::isolate(), 1503));
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015732 context->Global()->Set(v8_str("pixels"), obj);
15733 v8::Handle<v8::Value> result = CompileRun("pixels.field");
15734 CHECK_EQ(1503, result->Int32Value());
15735 result = CompileRun("pixels[1]");
15736 CHECK_EQ(1, result->Int32Value());
sgjesse@chromium.org9eceac12009-09-30 07:18:41 +000015737
15738 result = CompileRun("var sum = 0;"
15739 "for (var i = 0; i < 8; i++) {"
15740 " sum += pixels[i] = pixels[i] = -i;"
15741 "}"
15742 "sum;");
15743 CHECK_EQ(-28, result->Int32Value());
15744
15745 result = CompileRun("var sum = 0;"
15746 "for (var i = 0; i < 8; i++) {"
15747 " sum += pixels[i] = pixels[i] = 0;"
15748 "}"
15749 "sum;");
15750 CHECK_EQ(0, result->Int32Value());
15751
15752 result = CompileRun("var sum = 0;"
15753 "for (var i = 0; i < 8; i++) {"
15754 " sum += pixels[i] = pixels[i] = 255;"
15755 "}"
15756 "sum;");
15757 CHECK_EQ(8 * 255, result->Int32Value());
15758
15759 result = CompileRun("var sum = 0;"
15760 "for (var i = 0; i < 8; i++) {"
15761 " sum += pixels[i] = pixels[i] = 256 + i;"
15762 "}"
15763 "sum;");
15764 CHECK_EQ(2076, result->Int32Value());
15765
15766 result = CompileRun("var sum = 0;"
15767 "for (var i = 0; i < 8; i++) {"
15768 " sum += pixels[i] = pixels[i] = i;"
15769 "}"
15770 "sum;");
15771 CHECK_EQ(28, result->Int32Value());
15772
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015773 result = CompileRun("var sum = 0;"
15774 "for (var i = 0; i < 8; i++) {"
15775 " sum += pixels[i];"
15776 "}"
15777 "sum;");
15778 CHECK_EQ(28, result->Int32Value());
15779
ulan@chromium.org09d7ab52013-02-25 15:50:35 +000015780 i::Handle<i::Smi> value(i::Smi::FromInt(2),
15781 reinterpret_cast<i::Isolate*>(context->GetIsolate()));
jkummerow@chromium.org486075a2011-09-07 12:44:28 +000015782 i::Handle<i::Object> no_failure;
yangguo@chromium.orgab30bb82012-02-24 14:41:46 +000015783 no_failure =
15784 i::JSObject::SetElement(jsobj, 1, value, NONE, i::kNonStrictMode);
jkummerow@chromium.org486075a2011-09-07 12:44:28 +000015785 ASSERT(!no_failure.is_null());
15786 i::USE(no_failure);
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015787 CheckElementValue(isolate, 2, jsobj, 1);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015788 *value.location() = i::Smi::FromInt(256);
yangguo@chromium.orgab30bb82012-02-24 14:41:46 +000015789 no_failure =
15790 i::JSObject::SetElement(jsobj, 1, value, NONE, i::kNonStrictMode);
jkummerow@chromium.org486075a2011-09-07 12:44:28 +000015791 ASSERT(!no_failure.is_null());
15792 i::USE(no_failure);
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015793 CheckElementValue(isolate, 255, jsobj, 1);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015794 *value.location() = i::Smi::FromInt(-1);
yangguo@chromium.orgab30bb82012-02-24 14:41:46 +000015795 no_failure =
15796 i::JSObject::SetElement(jsobj, 1, value, NONE, i::kNonStrictMode);
jkummerow@chromium.org486075a2011-09-07 12:44:28 +000015797 ASSERT(!no_failure.is_null());
15798 i::USE(no_failure);
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015799 CheckElementValue(isolate, 0, jsobj, 1);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015800
15801 result = CompileRun("for (var i = 0; i < 8; i++) {"
15802 " pixels[i] = (i * 65) - 109;"
15803 "}"
15804 "pixels[1] + pixels[6];");
15805 CHECK_EQ(255, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015806 CheckElementValue(isolate, 0, jsobj, 0);
15807 CheckElementValue(isolate, 0, jsobj, 1);
15808 CheckElementValue(isolate, 21, jsobj, 2);
15809 CheckElementValue(isolate, 86, jsobj, 3);
15810 CheckElementValue(isolate, 151, jsobj, 4);
15811 CheckElementValue(isolate, 216, jsobj, 5);
15812 CheckElementValue(isolate, 255, jsobj, 6);
15813 CheckElementValue(isolate, 255, jsobj, 7);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015814 result = CompileRun("var sum = 0;"
15815 "for (var i = 0; i < 8; i++) {"
15816 " sum += pixels[i];"
15817 "}"
15818 "sum;");
15819 CHECK_EQ(984, result->Int32Value());
15820
15821 result = CompileRun("for (var i = 0; i < 8; i++) {"
15822 " pixels[i] = (i * 1.1);"
15823 "}"
15824 "pixels[1] + pixels[6];");
15825 CHECK_EQ(8, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015826 CheckElementValue(isolate, 0, jsobj, 0);
15827 CheckElementValue(isolate, 1, jsobj, 1);
15828 CheckElementValue(isolate, 2, jsobj, 2);
15829 CheckElementValue(isolate, 3, jsobj, 3);
15830 CheckElementValue(isolate, 4, jsobj, 4);
15831 CheckElementValue(isolate, 6, jsobj, 5);
15832 CheckElementValue(isolate, 7, jsobj, 6);
15833 CheckElementValue(isolate, 8, jsobj, 7);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015834
15835 result = CompileRun("for (var i = 0; i < 8; i++) {"
15836 " pixels[7] = undefined;"
15837 "}"
15838 "pixels[7];");
15839 CHECK_EQ(0, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015840 CheckElementValue(isolate, 0, jsobj, 7);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015841
15842 result = CompileRun("for (var i = 0; i < 8; i++) {"
15843 " pixels[6] = '2.3';"
15844 "}"
15845 "pixels[6];");
15846 CHECK_EQ(2, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015847 CheckElementValue(isolate, 2, jsobj, 6);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015848
15849 result = CompileRun("for (var i = 0; i < 8; i++) {"
15850 " pixels[5] = NaN;"
15851 "}"
15852 "pixels[5];");
15853 CHECK_EQ(0, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015854 CheckElementValue(isolate, 0, jsobj, 5);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015855
15856 result = CompileRun("for (var i = 0; i < 8; i++) {"
15857 " pixels[8] = Infinity;"
15858 "}"
15859 "pixels[8];");
15860 CHECK_EQ(255, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015861 CheckElementValue(isolate, 255, jsobj, 8);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015862
15863 result = CompileRun("for (var i = 0; i < 8; i++) {"
15864 " pixels[9] = -Infinity;"
15865 "}"
15866 "pixels[9];");
15867 CHECK_EQ(0, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015868 CheckElementValue(isolate, 0, jsobj, 9);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015869
15870 result = CompileRun("pixels[3] = 33;"
15871 "delete pixels[3];"
15872 "pixels[3];");
15873 CHECK_EQ(33, result->Int32Value());
15874
15875 result = CompileRun("pixels[0] = 10; pixels[1] = 11;"
15876 "pixels[2] = 12; pixels[3] = 13;"
15877 "pixels.__defineGetter__('2',"
15878 "function() { return 120; });"
15879 "pixels[2];");
15880 CHECK_EQ(12, result->Int32Value());
15881
15882 result = CompileRun("var js_array = new Array(40);"
15883 "js_array[0] = 77;"
15884 "js_array;");
15885 CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
15886
15887 result = CompileRun("pixels[1] = 23;"
15888 "pixels.__proto__ = [];"
15889 "js_array.__proto__ = pixels;"
15890 "js_array.concat(pixels);");
15891 CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
15892 CHECK_EQ(23, v8::Object::Cast(*result)->Get(v8_str("1"))->Int32Value());
15893
sgjesse@chromium.org9eceac12009-09-30 07:18:41 +000015894 result = CompileRun("pixels[1] = 23;");
15895 CHECK_EQ(23, result->Int32Value());
15896
ager@chromium.orgc4c92722009-11-18 14:12:51 +000015897 // Test for index greater than 255. Regression test for:
15898 // http://code.google.com/p/chromium/issues/detail?id=26337.
15899 result = CompileRun("pixels[256] = 255;");
15900 CHECK_EQ(255, result->Int32Value());
15901 result = CompileRun("var i = 0;"
15902 "for (var j = 0; j < 8; j++) { i = pixels[256]; }"
15903 "i");
15904 CHECK_EQ(255, result->Int32Value());
15905
ricow@chromium.org83aa5492011-02-07 12:42:56 +000015906 // Make sure that pixel array ICs recognize when a non-pixel array
15907 // is passed to it.
15908 result = CompileRun("function pa_load(p) {"
15909 " var sum = 0;"
15910 " for (var j = 0; j < 256; j++) { sum += p[j]; }"
15911 " return sum;"
15912 "}"
15913 "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
15914 "for (var i = 0; i < 10; ++i) { pa_load(pixels); }"
15915 "just_ints = new Object();"
15916 "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
15917 "for (var i = 0; i < 10; ++i) {"
15918 " result = pa_load(just_ints);"
15919 "}"
15920 "result");
15921 CHECK_EQ(32640, result->Int32Value());
15922
15923 // Make sure that pixel array ICs recognize out-of-bound accesses.
15924 result = CompileRun("function pa_load(p, start) {"
15925 " var sum = 0;"
15926 " for (var j = start; j < 256; j++) { sum += p[j]; }"
15927 " return sum;"
15928 "}"
15929 "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
15930 "for (var i = 0; i < 10; ++i) { pa_load(pixels,0); }"
15931 "for (var i = 0; i < 10; ++i) {"
15932 " result = pa_load(pixels,-10);"
15933 "}"
15934 "result");
15935 CHECK_EQ(0, result->Int32Value());
15936
15937 // Make sure that generic ICs properly handles a pixel array.
15938 result = CompileRun("function pa_load(p) {"
15939 " var sum = 0;"
15940 " for (var j = 0; j < 256; j++) { sum += p[j]; }"
15941 " return sum;"
15942 "}"
15943 "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
15944 "just_ints = new Object();"
15945 "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
15946 "for (var i = 0; i < 10; ++i) { pa_load(just_ints); }"
15947 "for (var i = 0; i < 10; ++i) {"
15948 " result = pa_load(pixels);"
15949 "}"
15950 "result");
15951 CHECK_EQ(32640, result->Int32Value());
15952
15953 // Make sure that generic load ICs recognize out-of-bound accesses in
15954 // pixel arrays.
15955 result = CompileRun("function pa_load(p, start) {"
15956 " var sum = 0;"
15957 " for (var j = start; j < 256; j++) { sum += p[j]; }"
15958 " return sum;"
15959 "}"
15960 "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
15961 "just_ints = new Object();"
15962 "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
15963 "for (var i = 0; i < 10; ++i) { pa_load(just_ints,0); }"
15964 "for (var i = 0; i < 10; ++i) { pa_load(pixels,0); }"
15965 "for (var i = 0; i < 10; ++i) {"
15966 " result = pa_load(pixels,-10);"
15967 "}"
15968 "result");
15969 CHECK_EQ(0, result->Int32Value());
15970
15971 // Make sure that generic ICs properly handles other types than pixel
15972 // arrays (that the inlined fast pixel array test leaves the right information
15973 // in the right registers).
15974 result = CompileRun("function pa_load(p) {"
15975 " var sum = 0;"
15976 " for (var j = 0; j < 256; j++) { sum += p[j]; }"
15977 " return sum;"
15978 "}"
15979 "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
15980 "just_ints = new Object();"
15981 "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
15982 "for (var i = 0; i < 10; ++i) { pa_load(just_ints); }"
15983 "for (var i = 0; i < 10; ++i) { pa_load(pixels); }"
15984 "sparse_array = new Object();"
15985 "for (var i = 0; i < 256; ++i) { sparse_array[i] = i; }"
15986 "sparse_array[1000000] = 3;"
15987 "for (var i = 0; i < 10; ++i) {"
15988 " result = pa_load(sparse_array);"
15989 "}"
15990 "result");
15991 CHECK_EQ(32640, result->Int32Value());
15992
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +000015993 // Make sure that pixel array store ICs clamp values correctly.
15994 result = CompileRun("function pa_store(p) {"
15995 " for (var j = 0; j < 256; j++) { p[j] = j * 2; }"
15996 "}"
15997 "pa_store(pixels);"
15998 "var sum = 0;"
15999 "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
16000 "sum");
16001 CHECK_EQ(48896, result->Int32Value());
16002
16003 // Make sure that pixel array stores correctly handle accesses outside
16004 // of the pixel array..
16005 result = CompileRun("function pa_store(p,start) {"
16006 " for (var j = 0; j < 256; j++) {"
16007 " p[j+start] = j * 2;"
16008 " }"
16009 "}"
16010 "pa_store(pixels,0);"
16011 "pa_store(pixels,-128);"
16012 "var sum = 0;"
16013 "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
16014 "sum");
16015 CHECK_EQ(65280, result->Int32Value());
16016
16017 // Make sure that the generic store stub correctly handle accesses outside
16018 // of the pixel array..
16019 result = CompileRun("function pa_store(p,start) {"
16020 " for (var j = 0; j < 256; j++) {"
16021 " p[j+start] = j * 2;"
16022 " }"
16023 "}"
16024 "pa_store(pixels,0);"
16025 "just_ints = new Object();"
16026 "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
16027 "pa_store(just_ints, 0);"
16028 "pa_store(pixels,-128);"
16029 "var sum = 0;"
16030 "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
16031 "sum");
16032 CHECK_EQ(65280, result->Int32Value());
16033
16034 // Make sure that the generic keyed store stub clamps pixel array values
16035 // correctly.
16036 result = CompileRun("function pa_store(p) {"
16037 " for (var j = 0; j < 256; j++) { p[j] = j * 2; }"
16038 "}"
16039 "pa_store(pixels);"
16040 "just_ints = new Object();"
16041 "pa_store(just_ints);"
16042 "pa_store(pixels);"
16043 "var sum = 0;"
16044 "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
16045 "sum");
16046 CHECK_EQ(48896, result->Int32Value());
16047
16048 // Make sure that pixel array loads are optimized by crankshaft.
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000016049 result = CompileRun("function pa_load(p) {"
16050 " var sum = 0;"
16051 " for (var i=0; i<256; ++i) {"
16052 " sum += p[i];"
16053 " }"
16054 " return sum; "
16055 "}"
16056 "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000016057 "for (var i = 0; i < 5000; ++i) {"
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000016058 " result = pa_load(pixels);"
16059 "}"
16060 "result");
16061 CHECK_EQ(32640, result->Int32Value());
16062
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000016063 // Make sure that pixel array stores are optimized by crankshaft.
16064 result = CompileRun("function pa_init(p) {"
16065 "for (var i = 0; i < 256; ++i) { p[i] = i; }"
16066 "}"
16067 "function pa_load(p) {"
16068 " var sum = 0;"
16069 " for (var i=0; i<256; ++i) {"
16070 " sum += p[i];"
16071 " }"
16072 " return sum; "
16073 "}"
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000016074 "for (var i = 0; i < 5000; ++i) {"
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000016075 " pa_init(pixels);"
16076 "}"
16077 "result = pa_load(pixels);"
16078 "result");
16079 CHECK_EQ(32640, result->Int32Value());
16080
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000016081 free(pixel_data);
16082}
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000016083
ager@chromium.org96c75b52009-08-26 09:13:16 +000016084
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016085THREADED_TEST(PixelArrayInfo) {
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016086 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016087 v8::HandleScope scope(context->GetIsolate());
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016088 for (int size = 0; size < 100; size += 10) {
16089 uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(size));
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016090 v8::Handle<v8::Object> obj = v8::Object::New(context->GetIsolate());
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016091 obj->SetIndexedPropertiesToPixelData(pixel_data, size);
16092 CHECK(obj->HasIndexedPropertiesInPixelData());
16093 CHECK_EQ(pixel_data, obj->GetIndexedPropertiesPixelData());
16094 CHECK_EQ(size, obj->GetIndexedPropertiesPixelDataLength());
16095 free(pixel_data);
16096 }
16097}
16098
16099
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000016100static void NotHandledIndexedPropertyGetter(
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000016101 uint32_t index,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000016102 const v8::PropertyCallbackInfo<v8::Value>& info) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000016103 ApiTestFuzzer::Fuzz();
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000016104}
16105
16106
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000016107static void NotHandledIndexedPropertySetter(
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000016108 uint32_t index,
16109 Local<Value> value,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000016110 const v8::PropertyCallbackInfo<v8::Value>& info) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000016111 ApiTestFuzzer::Fuzz();
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000016112}
16113
16114
16115THREADED_TEST(PixelArrayWithInterceptor) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000016116 LocalContext context;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000016117 i::Factory* factory = CcTest::i_isolate()->factory();
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000016118 v8::Isolate* isolate = context->GetIsolate();
16119 v8::HandleScope scope(isolate);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000016120 const int kElementCount = 260;
16121 uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(kElementCount));
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016122 i::Handle<i::ExternalUint8ClampedArray> pixels =
16123 i::Handle<i::ExternalUint8ClampedArray>::cast(
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000016124 factory->NewExternalArray(kElementCount,
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016125 v8::kExternalUint8ClampedArray,
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000016126 pixel_data));
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000016127 for (int i = 0; i < kElementCount; i++) {
16128 pixels->set(i, i % 256);
16129 }
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000016130 v8::Handle<v8::ObjectTemplate> templ =
16131 v8::ObjectTemplate::New(context->GetIsolate());
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000016132 templ->SetIndexedPropertyHandler(NotHandledIndexedPropertyGetter,
16133 NotHandledIndexedPropertySetter);
16134 v8::Handle<v8::Object> obj = templ->NewInstance();
16135 obj->SetIndexedPropertiesToPixelData(pixel_data, kElementCount);
16136 context->Global()->Set(v8_str("pixels"), obj);
16137 v8::Handle<v8::Value> result = CompileRun("pixels[1]");
16138 CHECK_EQ(1, result->Int32Value());
16139 result = CompileRun("var sum = 0;"
16140 "for (var i = 0; i < 8; i++) {"
16141 " sum += pixels[i] = pixels[i] = -i;"
16142 "}"
16143 "sum;");
16144 CHECK_EQ(-28, result->Int32Value());
16145 result = CompileRun("pixels.hasOwnProperty('1')");
16146 CHECK(result->BooleanValue());
16147 free(pixel_data);
16148}
16149
16150
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016151static int ExternalArrayElementSize(v8::ExternalArrayType array_type) {
16152 switch (array_type) {
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016153 case v8::kExternalInt8Array:
16154 case v8::kExternalUint8Array:
16155 case v8::kExternalUint8ClampedArray:
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016156 return 1;
16157 break;
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016158 case v8::kExternalInt16Array:
16159 case v8::kExternalUint16Array:
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016160 return 2;
16161 break;
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016162 case v8::kExternalInt32Array:
16163 case v8::kExternalUint32Array:
16164 case v8::kExternalFloat32Array:
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016165 return 4;
16166 break;
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016167 case v8::kExternalFloat64Array:
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +000016168 return 8;
16169 break;
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016170 default:
16171 UNREACHABLE();
16172 return -1;
16173 }
16174 UNREACHABLE();
16175 return -1;
16176}
16177
16178
ager@chromium.org3811b432009-10-28 14:53:37 +000016179template <class ExternalArrayClass, class ElementType>
danno@chromium.orgf005df62013-04-30 16:36:45 +000016180static void ObjectWithExternalArrayTestHelper(
16181 Handle<Context> context,
16182 v8::Handle<Object> obj,
16183 int element_count,
16184 v8::ExternalArrayType array_type,
16185 int64_t low, int64_t high) {
ager@chromium.org3811b432009-10-28 14:53:37 +000016186 i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000016187 i::Isolate* isolate = jsobj->GetIsolate();
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016188 obj->Set(v8_str("field"),
16189 v8::Int32::New(reinterpret_cast<v8::Isolate*>(isolate), 1503));
ager@chromium.org3811b432009-10-28 14:53:37 +000016190 context->Global()->Set(v8_str("ext_array"), obj);
16191 v8::Handle<v8::Value> result = CompileRun("ext_array.field");
16192 CHECK_EQ(1503, result->Int32Value());
16193 result = CompileRun("ext_array[1]");
16194 CHECK_EQ(1, result->Int32Value());
16195
ager@chromium.org3811b432009-10-28 14:53:37 +000016196 // Check assigned smis
16197 result = CompileRun("for (var i = 0; i < 8; i++) {"
16198 " ext_array[i] = i;"
16199 "}"
16200 "var sum = 0;"
16201 "for (var i = 0; i < 8; i++) {"
16202 " sum += ext_array[i];"
16203 "}"
16204 "sum;");
machenbach@chromium.org5c88bc32014-01-17 08:10:36 +000016205
ager@chromium.org3811b432009-10-28 14:53:37 +000016206 CHECK_EQ(28, result->Int32Value());
machenbach@chromium.org5c88bc32014-01-17 08:10:36 +000016207 // Check pass through of assigned smis
16208 result = CompileRun("var sum = 0;"
16209 "for (var i = 0; i < 8; i++) {"
16210 " sum += ext_array[i] = ext_array[i] = -i;"
16211 "}"
16212 "sum;");
16213 CHECK_EQ(-28, result->Int32Value());
16214
ager@chromium.org3811b432009-10-28 14:53:37 +000016215
16216 // Check assigned smis in reverse order
16217 result = CompileRun("for (var i = 8; --i >= 0; ) {"
16218 " ext_array[i] = i;"
16219 "}"
16220 "var sum = 0;"
16221 "for (var i = 0; i < 8; i++) {"
16222 " sum += ext_array[i];"
16223 "}"
16224 "sum;");
16225 CHECK_EQ(28, result->Int32Value());
16226
16227 // Check pass through of assigned HeapNumbers
16228 result = CompileRun("var sum = 0;"
16229 "for (var i = 0; i < 16; i+=2) {"
16230 " sum += ext_array[i] = ext_array[i] = (-i * 0.5);"
16231 "}"
16232 "sum;");
16233 CHECK_EQ(-28, result->Int32Value());
16234
16235 // Check assigned HeapNumbers
16236 result = CompileRun("for (var i = 0; i < 16; i+=2) {"
16237 " ext_array[i] = (i * 0.5);"
16238 "}"
16239 "var sum = 0;"
16240 "for (var i = 0; i < 16; i+=2) {"
16241 " sum += ext_array[i];"
16242 "}"
16243 "sum;");
16244 CHECK_EQ(28, result->Int32Value());
16245
16246 // Check assigned HeapNumbers in reverse order
16247 result = CompileRun("for (var i = 14; i >= 0; i-=2) {"
16248 " ext_array[i] = (i * 0.5);"
16249 "}"
16250 "var sum = 0;"
16251 "for (var i = 0; i < 16; i+=2) {"
16252 " sum += ext_array[i];"
16253 "}"
16254 "sum;");
16255 CHECK_EQ(28, result->Int32Value());
16256
16257 i::ScopedVector<char> test_buf(1024);
16258
16259 // Check legal boundary conditions.
16260 // The repeated loads and stores ensure the ICs are exercised.
16261 const char* boundary_program =
16262 "var res = 0;"
16263 "for (var i = 0; i < 16; i++) {"
16264 " ext_array[i] = %lld;"
16265 " if (i > 8) {"
16266 " res = ext_array[i];"
16267 " }"
16268 "}"
16269 "res;";
16270 i::OS::SNPrintF(test_buf,
16271 boundary_program,
16272 low);
16273 result = CompileRun(test_buf.start());
16274 CHECK_EQ(low, result->IntegerValue());
16275
16276 i::OS::SNPrintF(test_buf,
16277 boundary_program,
16278 high);
16279 result = CompileRun(test_buf.start());
16280 CHECK_EQ(high, result->IntegerValue());
16281
16282 // Check misprediction of type in IC.
16283 result = CompileRun("var tmp_array = ext_array;"
16284 "var sum = 0;"
16285 "for (var i = 0; i < 8; i++) {"
16286 " tmp_array[i] = i;"
16287 " sum += tmp_array[i];"
16288 " if (i == 4) {"
16289 " tmp_array = {};"
16290 " }"
16291 "}"
16292 "sum;");
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000016293 // Force GC to trigger verification.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000016294 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org3811b432009-10-28 14:53:37 +000016295 CHECK_EQ(28, result->Int32Value());
16296
16297 // Make sure out-of-range loads do not throw.
16298 i::OS::SNPrintF(test_buf,
16299 "var caught_exception = false;"
16300 "try {"
16301 " ext_array[%d];"
16302 "} catch (e) {"
16303 " caught_exception = true;"
16304 "}"
16305 "caught_exception;",
danno@chromium.orgf005df62013-04-30 16:36:45 +000016306 element_count);
ager@chromium.org3811b432009-10-28 14:53:37 +000016307 result = CompileRun(test_buf.start());
16308 CHECK_EQ(false, result->BooleanValue());
16309
16310 // Make sure out-of-range stores do not throw.
16311 i::OS::SNPrintF(test_buf,
16312 "var caught_exception = false;"
16313 "try {"
16314 " ext_array[%d] = 1;"
16315 "} catch (e) {"
16316 " caught_exception = true;"
16317 "}"
16318 "caught_exception;",
danno@chromium.orgf005df62013-04-30 16:36:45 +000016319 element_count);
ager@chromium.org3811b432009-10-28 14:53:37 +000016320 result = CompileRun(test_buf.start());
16321 CHECK_EQ(false, result->BooleanValue());
16322
16323 // Check other boundary conditions, values and operations.
16324 result = CompileRun("for (var i = 0; i < 8; i++) {"
16325 " ext_array[7] = undefined;"
16326 "}"
16327 "ext_array[7];");
16328 CHECK_EQ(0, result->Int32Value());
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016329 if (array_type == v8::kExternalFloat64Array ||
16330 array_type == v8::kExternalFloat32Array) {
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000016331 CHECK_EQ(static_cast<int>(i::OS::nan_value()),
16332 static_cast<int>(
16333 jsobj->GetElement(isolate, 7)->ToObjectChecked()->Number()));
yangguo@chromium.org56454712012-02-16 15:33:53 +000016334 } else {
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000016335 CheckElementValue(isolate, 0, jsobj, 7);
yangguo@chromium.org56454712012-02-16 15:33:53 +000016336 }
ager@chromium.org3811b432009-10-28 14:53:37 +000016337
16338 result = CompileRun("for (var i = 0; i < 8; i++) {"
16339 " ext_array[6] = '2.3';"
16340 "}"
16341 "ext_array[6];");
16342 CHECK_EQ(2, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000016343 CHECK_EQ(2,
16344 static_cast<int>(
16345 jsobj->GetElement(isolate, 6)->ToObjectChecked()->Number()));
ager@chromium.org3811b432009-10-28 14:53:37 +000016346
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016347 if (array_type != v8::kExternalFloat32Array &&
16348 array_type != v8::kExternalFloat64Array) {
ager@chromium.org3811b432009-10-28 14:53:37 +000016349 // Though the specification doesn't state it, be explicit about
16350 // converting NaNs and +/-Infinity to zero.
16351 result = CompileRun("for (var i = 0; i < 8; i++) {"
16352 " ext_array[i] = 5;"
16353 "}"
16354 "for (var i = 0; i < 8; i++) {"
16355 " ext_array[i] = NaN;"
16356 "}"
16357 "ext_array[5];");
16358 CHECK_EQ(0, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000016359 CheckElementValue(isolate, 0, jsobj, 5);
ager@chromium.org3811b432009-10-28 14:53:37 +000016360
16361 result = CompileRun("for (var i = 0; i < 8; i++) {"
16362 " ext_array[i] = 5;"
16363 "}"
16364 "for (var i = 0; i < 8; i++) {"
16365 " ext_array[i] = Infinity;"
16366 "}"
16367 "ext_array[5];");
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000016368 int expected_value =
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016369 (array_type == v8::kExternalUint8ClampedArray) ? 255 : 0;
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000016370 CHECK_EQ(expected_value, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000016371 CheckElementValue(isolate, expected_value, jsobj, 5);
ager@chromium.org3811b432009-10-28 14:53:37 +000016372
16373 result = CompileRun("for (var i = 0; i < 8; i++) {"
16374 " ext_array[i] = 5;"
16375 "}"
16376 "for (var i = 0; i < 8; i++) {"
16377 " ext_array[i] = -Infinity;"
16378 "}"
16379 "ext_array[5];");
16380 CHECK_EQ(0, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000016381 CheckElementValue(isolate, 0, jsobj, 5);
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +000016382
16383 // Check truncation behavior of integral arrays.
16384 const char* unsigned_data =
16385 "var source_data = [0.6, 10.6];"
16386 "var expected_results = [0, 10];";
16387 const char* signed_data =
16388 "var source_data = [0.6, 10.6, -0.6, -10.6];"
16389 "var expected_results = [0, 10, 0, -10];";
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000016390 const char* pixel_data =
16391 "var source_data = [0.6, 10.6];"
16392 "var expected_results = [1, 11];";
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +000016393 bool is_unsigned =
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016394 (array_type == v8::kExternalUint8Array ||
16395 array_type == v8::kExternalUint16Array ||
16396 array_type == v8::kExternalUint32Array);
16397 bool is_pixel_data = array_type == v8::kExternalUint8ClampedArray;
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +000016398
16399 i::OS::SNPrintF(test_buf,
16400 "%s"
16401 "var all_passed = true;"
16402 "for (var i = 0; i < source_data.length; i++) {"
16403 " for (var j = 0; j < 8; j++) {"
16404 " ext_array[j] = source_data[i];"
16405 " }"
16406 " all_passed = all_passed &&"
16407 " (ext_array[5] == expected_results[i]);"
16408 "}"
16409 "all_passed;",
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000016410 (is_unsigned ?
16411 unsigned_data :
16412 (is_pixel_data ? pixel_data : signed_data)));
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +000016413 result = CompileRun(test_buf.start());
16414 CHECK_EQ(true, result->BooleanValue());
ager@chromium.org3811b432009-10-28 14:53:37 +000016415 }
16416
danno@chromium.orgf005df62013-04-30 16:36:45 +000016417 i::Handle<ExternalArrayClass> array(
16418 ExternalArrayClass::cast(jsobj->elements()));
16419 for (int i = 0; i < element_count; i++) {
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000016420 array->set(i, static_cast<ElementType>(i));
16421 }
danno@chromium.orgf005df62013-04-30 16:36:45 +000016422
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000016423 // Test complex assignments
16424 result = CompileRun("function ee_op_test_complex_func(sum) {"
16425 " for (var i = 0; i < 40; ++i) {"
16426 " sum += (ext_array[i] += 1);"
16427 " sum += (ext_array[i] -= 1);"
16428 " } "
16429 " return sum;"
16430 "}"
16431 "sum=0;"
16432 "for (var i=0;i<10000;++i) {"
16433 " sum=ee_op_test_complex_func(sum);"
16434 "}"
16435 "sum;");
16436 CHECK_EQ(16000000, result->Int32Value());
16437
16438 // Test count operations
16439 result = CompileRun("function ee_op_test_count_func(sum) {"
16440 " for (var i = 0; i < 40; ++i) {"
16441 " sum += (++ext_array[i]);"
16442 " sum += (--ext_array[i]);"
16443 " } "
16444 " return sum;"
16445 "}"
16446 "sum=0;"
16447 "for (var i=0;i<10000;++i) {"
16448 " sum=ee_op_test_count_func(sum);"
16449 "}"
16450 "sum;");
16451 CHECK_EQ(16000000, result->Int32Value());
16452
ager@chromium.org3811b432009-10-28 14:53:37 +000016453 result = CompileRun("ext_array[3] = 33;"
16454 "delete ext_array[3];"
16455 "ext_array[3];");
16456 CHECK_EQ(33, result->Int32Value());
16457
16458 result = CompileRun("ext_array[0] = 10; ext_array[1] = 11;"
16459 "ext_array[2] = 12; ext_array[3] = 13;"
16460 "ext_array.__defineGetter__('2',"
16461 "function() { return 120; });"
16462 "ext_array[2];");
16463 CHECK_EQ(12, result->Int32Value());
16464
16465 result = CompileRun("var js_array = new Array(40);"
16466 "js_array[0] = 77;"
16467 "js_array;");
16468 CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
16469
16470 result = CompileRun("ext_array[1] = 23;"
16471 "ext_array.__proto__ = [];"
16472 "js_array.__proto__ = ext_array;"
16473 "js_array.concat(ext_array);");
16474 CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
16475 CHECK_EQ(23, v8::Object::Cast(*result)->Get(v8_str("1"))->Int32Value());
16476
16477 result = CompileRun("ext_array[1] = 23;");
16478 CHECK_EQ(23, result->Int32Value());
danno@chromium.orgf005df62013-04-30 16:36:45 +000016479}
16480
16481
machenbach@chromium.org5c88bc32014-01-17 08:10:36 +000016482template <class FixedTypedArrayClass,
16483 i::ElementsKind elements_kind,
16484 class ElementType>
16485static void FixedTypedArrayTestHelper(
16486 v8::ExternalArrayType array_type,
16487 ElementType low,
16488 ElementType high) {
16489 i::FLAG_allow_natives_syntax = true;
16490 LocalContext context;
16491 i::Isolate* isolate = CcTest::i_isolate();
16492 i::Factory* factory = isolate->factory();
16493 v8::HandleScope scope(context->GetIsolate());
16494 const int kElementCount = 260;
16495 i::Handle<FixedTypedArrayClass> fixed_array =
16496 i::Handle<FixedTypedArrayClass>::cast(
16497 factory->NewFixedTypedArray(kElementCount, array_type));
16498 CHECK_EQ(FixedTypedArrayClass::kInstanceType,
16499 fixed_array->map()->instance_type());
16500 CHECK_EQ(kElementCount, fixed_array->length());
16501 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
16502 for (int i = 0; i < kElementCount; i++) {
16503 fixed_array->set(i, static_cast<ElementType>(i));
16504 }
16505 // Force GC to trigger verification.
16506 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
16507 for (int i = 0; i < kElementCount; i++) {
16508 CHECK_EQ(static_cast<int64_t>(static_cast<ElementType>(i)),
16509 static_cast<int64_t>(fixed_array->get_scalar(i)));
16510 }
16511 v8::Handle<v8::Object> obj = v8::Object::New(CcTest::isolate());
16512 i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
16513 i::Handle<i::Map> fixed_array_map =
16514 isolate->factory()->GetElementsTransitionMap(jsobj, elements_kind);
16515 jsobj->set_map(*fixed_array_map);
16516 jsobj->set_elements(*fixed_array);
16517
16518 ObjectWithExternalArrayTestHelper<FixedTypedArrayClass, ElementType>(
16519 context.local(), obj, kElementCount, array_type,
16520 static_cast<int64_t>(low),
16521 static_cast<int64_t>(high));
16522}
16523
16524
16525THREADED_TEST(FixedUint8Array) {
16526 FixedTypedArrayTestHelper<i::FixedUint8Array, i::UINT8_ELEMENTS, uint8_t>(
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016527 v8::kExternalUint8Array,
machenbach@chromium.org5c88bc32014-01-17 08:10:36 +000016528 0x0, 0xFF);
16529}
16530
16531
16532THREADED_TEST(FixedUint8ClampedArray) {
16533 FixedTypedArrayTestHelper<i::FixedUint8ClampedArray,
16534 i::UINT8_CLAMPED_ELEMENTS, uint8_t>(
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016535 v8::kExternalUint8ClampedArray,
machenbach@chromium.org5c88bc32014-01-17 08:10:36 +000016536 0x0, 0xFF);
16537}
16538
16539
16540THREADED_TEST(FixedInt8Array) {
16541 FixedTypedArrayTestHelper<i::FixedInt8Array, i::INT8_ELEMENTS, int8_t>(
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016542 v8::kExternalInt8Array,
machenbach@chromium.org5c88bc32014-01-17 08:10:36 +000016543 -0x80, 0x7F);
16544}
16545
16546
16547THREADED_TEST(FixedUint16Array) {
16548 FixedTypedArrayTestHelper<i::FixedUint16Array, i::UINT16_ELEMENTS, uint16_t>(
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016549 v8::kExternalUint16Array,
machenbach@chromium.org5c88bc32014-01-17 08:10:36 +000016550 0x0, 0xFFFF);
16551}
16552
16553
16554THREADED_TEST(FixedInt16Array) {
16555 FixedTypedArrayTestHelper<i::FixedInt16Array, i::INT16_ELEMENTS, int16_t>(
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016556 v8::kExternalInt16Array,
machenbach@chromium.org5c88bc32014-01-17 08:10:36 +000016557 -0x8000, 0x7FFF);
16558}
16559
16560
16561THREADED_TEST(FixedUint32Array) {
16562 FixedTypedArrayTestHelper<i::FixedUint32Array, i::UINT32_ELEMENTS, uint32_t>(
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016563 v8::kExternalUint32Array,
machenbach@chromium.org5c88bc32014-01-17 08:10:36 +000016564 0x0, UINT_MAX);
16565}
16566
16567
16568THREADED_TEST(FixedInt32Array) {
16569 FixedTypedArrayTestHelper<i::FixedInt32Array, i::INT32_ELEMENTS, int32_t>(
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016570 v8::kExternalInt32Array,
machenbach@chromium.org5c88bc32014-01-17 08:10:36 +000016571 INT_MIN, INT_MAX);
16572}
16573
16574
16575THREADED_TEST(FixedFloat32Array) {
16576 FixedTypedArrayTestHelper<i::FixedFloat32Array, i::FLOAT32_ELEMENTS, float>(
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016577 v8::kExternalFloat32Array,
machenbach@chromium.org5c88bc32014-01-17 08:10:36 +000016578 -500, 500);
16579}
16580
16581
16582THREADED_TEST(FixedFloat64Array) {
16583 FixedTypedArrayTestHelper<i::FixedFloat64Array, i::FLOAT64_ELEMENTS, float>(
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016584 v8::kExternalFloat64Array,
machenbach@chromium.org5c88bc32014-01-17 08:10:36 +000016585 -500, 500);
16586}
16587
16588
danno@chromium.orgf005df62013-04-30 16:36:45 +000016589template <class ExternalArrayClass, class ElementType>
16590static void ExternalArrayTestHelper(v8::ExternalArrayType array_type,
16591 int64_t low,
16592 int64_t high) {
16593 LocalContext context;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000016594 i::Isolate* isolate = CcTest::i_isolate();
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000016595 i::Factory* factory = isolate->factory();
danno@chromium.orgf005df62013-04-30 16:36:45 +000016596 v8::HandleScope scope(context->GetIsolate());
16597 const int kElementCount = 40;
16598 int element_size = ExternalArrayElementSize(array_type);
16599 ElementType* array_data =
16600 static_cast<ElementType*>(malloc(kElementCount * element_size));
16601 i::Handle<ExternalArrayClass> array =
16602 i::Handle<ExternalArrayClass>::cast(
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000016603 factory->NewExternalArray(kElementCount, array_type, array_data));
danno@chromium.orgf005df62013-04-30 16:36:45 +000016604 // Force GC to trigger verification.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000016605 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
danno@chromium.orgf005df62013-04-30 16:36:45 +000016606 for (int i = 0; i < kElementCount; i++) {
16607 array->set(i, static_cast<ElementType>(i));
16608 }
16609 // Force GC to trigger verification.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000016610 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
danno@chromium.orgf005df62013-04-30 16:36:45 +000016611 for (int i = 0; i < kElementCount; i++) {
16612 CHECK_EQ(static_cast<int64_t>(i),
16613 static_cast<int64_t>(array->get_scalar(i)));
16614 CHECK_EQ(static_cast<int64_t>(i), static_cast<int64_t>(array_data[i]));
16615 }
16616
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016617 v8::Handle<v8::Object> obj = v8::Object::New(context->GetIsolate());
danno@chromium.orgf005df62013-04-30 16:36:45 +000016618 i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
16619 // Set the elements to be the external array.
16620 obj->SetIndexedPropertiesToExternalArrayData(array_data,
16621 array_type,
16622 kElementCount);
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000016623 CHECK_EQ(1,
16624 static_cast<int>(
16625 jsobj->GetElement(isolate, 1)->ToObjectChecked()->Number()));
danno@chromium.orgf005df62013-04-30 16:36:45 +000016626
16627 ObjectWithExternalArrayTestHelper<ExternalArrayClass, ElementType>(
16628 context.local(), obj, kElementCount, array_type, low, high);
16629
16630 v8::Handle<v8::Value> result;
ager@chromium.org3811b432009-10-28 14:53:37 +000016631
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +000016632 // Test more complex manipulations which cause eax to contain values
16633 // that won't be completely overwritten by loads from the arrays.
16634 // This catches bugs in the instructions used for the KeyedLoadIC
16635 // for byte and word types.
16636 {
16637 const int kXSize = 300;
16638 const int kYSize = 300;
16639 const int kLargeElementCount = kXSize * kYSize * 4;
16640 ElementType* large_array_data =
16641 static_cast<ElementType*>(malloc(kLargeElementCount * element_size));
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016642 v8::Handle<v8::Object> large_obj = v8::Object::New(context->GetIsolate());
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +000016643 // Set the elements to be the external array.
16644 large_obj->SetIndexedPropertiesToExternalArrayData(large_array_data,
16645 array_type,
16646 kLargeElementCount);
16647 context->Global()->Set(v8_str("large_array"), large_obj);
16648 // Initialize contents of a few rows.
16649 for (int x = 0; x < 300; x++) {
16650 int row = 0;
16651 int offset = row * 300 * 4;
16652 large_array_data[offset + 4 * x + 0] = (ElementType) 127;
16653 large_array_data[offset + 4 * x + 1] = (ElementType) 0;
16654 large_array_data[offset + 4 * x + 2] = (ElementType) 0;
16655 large_array_data[offset + 4 * x + 3] = (ElementType) 127;
16656 row = 150;
16657 offset = row * 300 * 4;
16658 large_array_data[offset + 4 * x + 0] = (ElementType) 127;
16659 large_array_data[offset + 4 * x + 1] = (ElementType) 0;
16660 large_array_data[offset + 4 * x + 2] = (ElementType) 0;
16661 large_array_data[offset + 4 * x + 3] = (ElementType) 127;
16662 row = 298;
16663 offset = row * 300 * 4;
16664 large_array_data[offset + 4 * x + 0] = (ElementType) 127;
16665 large_array_data[offset + 4 * x + 1] = (ElementType) 0;
16666 large_array_data[offset + 4 * x + 2] = (ElementType) 0;
16667 large_array_data[offset + 4 * x + 3] = (ElementType) 127;
16668 }
16669 // The goal of the code below is to make "offset" large enough
16670 // that the computation of the index (which goes into eax) has
16671 // high bits set which will not be overwritten by a byte or short
16672 // load.
16673 result = CompileRun("var failed = false;"
16674 "var offset = 0;"
16675 "for (var i = 0; i < 300; i++) {"
16676 " if (large_array[4 * i] != 127 ||"
16677 " large_array[4 * i + 1] != 0 ||"
16678 " large_array[4 * i + 2] != 0 ||"
16679 " large_array[4 * i + 3] != 127) {"
16680 " failed = true;"
16681 " }"
16682 "}"
16683 "offset = 150 * 300 * 4;"
16684 "for (var i = 0; i < 300; i++) {"
16685 " if (large_array[offset + 4 * i] != 127 ||"
16686 " large_array[offset + 4 * i + 1] != 0 ||"
16687 " large_array[offset + 4 * i + 2] != 0 ||"
16688 " large_array[offset + 4 * i + 3] != 127) {"
16689 " failed = true;"
16690 " }"
16691 "}"
16692 "offset = 298 * 300 * 4;"
16693 "for (var i = 0; i < 300; i++) {"
16694 " if (large_array[offset + 4 * i] != 127 ||"
16695 " large_array[offset + 4 * i + 1] != 0 ||"
16696 " large_array[offset + 4 * i + 2] != 0 ||"
16697 " large_array[offset + 4 * i + 3] != 127) {"
16698 " failed = true;"
16699 " }"
16700 "}"
16701 "!failed;");
16702 CHECK_EQ(true, result->BooleanValue());
16703 free(large_array_data);
16704 }
16705
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000016706 // The "" property descriptor is overloaded to store information about
16707 // the external array. Ensure that setting and accessing the "" property
16708 // works (it should overwrite the information cached about the external
16709 // array in the DescriptorArray) in various situations.
16710 result = CompileRun("ext_array[''] = 23; ext_array['']");
16711 CHECK_EQ(23, result->Int32Value());
16712
16713 // Property "" set after the external array is associated with the object.
16714 {
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016715 v8::Handle<v8::Object> obj2 = v8::Object::New(context->GetIsolate());
16716 obj2->Set(v8_str("ee_test_field"),
16717 v8::Int32::New(context->GetIsolate(), 256));
16718 obj2->Set(v8_str(""), v8::Int32::New(context->GetIsolate(), 1503));
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000016719 // Set the elements to be the external array.
16720 obj2->SetIndexedPropertiesToExternalArrayData(array_data,
16721 array_type,
16722 kElementCount);
16723 context->Global()->Set(v8_str("ext_array"), obj2);
16724 result = CompileRun("ext_array['']");
16725 CHECK_EQ(1503, result->Int32Value());
16726 }
16727
16728 // Property "" set after the external array is associated with the object.
16729 {
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016730 v8::Handle<v8::Object> obj2 = v8::Object::New(context->GetIsolate());
16731 obj2->Set(v8_str("ee_test_field_2"),
16732 v8::Int32::New(context->GetIsolate(), 256));
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000016733 // Set the elements to be the external array.
16734 obj2->SetIndexedPropertiesToExternalArrayData(array_data,
16735 array_type,
16736 kElementCount);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016737 obj2->Set(v8_str(""), v8::Int32::New(context->GetIsolate(), 1503));
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000016738 context->Global()->Set(v8_str("ext_array"), obj2);
16739 result = CompileRun("ext_array['']");
16740 CHECK_EQ(1503, result->Int32Value());
16741 }
16742
16743 // Should reuse the map from previous test.
16744 {
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016745 v8::Handle<v8::Object> obj2 = v8::Object::New(context->GetIsolate());
16746 obj2->Set(v8_str("ee_test_field_2"),
16747 v8::Int32::New(context->GetIsolate(), 256));
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000016748 // Set the elements to be the external array. Should re-use the map
16749 // from previous test.
16750 obj2->SetIndexedPropertiesToExternalArrayData(array_data,
16751 array_type,
16752 kElementCount);
16753 context->Global()->Set(v8_str("ext_array"), obj2);
16754 result = CompileRun("ext_array['']");
16755 }
16756
16757 // Property "" is a constant function that shouldn't not be interfered with
16758 // when an external array is set.
16759 {
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016760 v8::Handle<v8::Object> obj2 = v8::Object::New(context->GetIsolate());
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000016761 // Start
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016762 obj2->Set(v8_str("ee_test_field3"),
16763 v8::Int32::New(context->GetIsolate(), 256));
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000016764
16765 // Add a constant function to an object.
16766 context->Global()->Set(v8_str("ext_array"), obj2);
16767 result = CompileRun("ext_array[''] = function() {return 1503;};"
16768 "ext_array['']();");
16769
16770 // Add an external array transition to the same map that
16771 // has the constant transition.
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016772 v8::Handle<v8::Object> obj3 = v8::Object::New(context->GetIsolate());
16773 obj3->Set(v8_str("ee_test_field3"),
16774 v8::Int32::New(context->GetIsolate(), 256));
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000016775 obj3->SetIndexedPropertiesToExternalArrayData(array_data,
16776 array_type,
16777 kElementCount);
16778 context->Global()->Set(v8_str("ext_array"), obj3);
16779 }
16780
16781 // If a external array transition is in the map, it should get clobbered
16782 // by a constant function.
16783 {
16784 // Add an external array transition.
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016785 v8::Handle<v8::Object> obj3 = v8::Object::New(context->GetIsolate());
16786 obj3->Set(v8_str("ee_test_field4"),
16787 v8::Int32::New(context->GetIsolate(), 256));
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000016788 obj3->SetIndexedPropertiesToExternalArrayData(array_data,
16789 array_type,
16790 kElementCount);
16791
16792 // Add a constant function to the same map that just got an external array
16793 // transition.
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016794 v8::Handle<v8::Object> obj2 = v8::Object::New(context->GetIsolate());
16795 obj2->Set(v8_str("ee_test_field4"),
16796 v8::Int32::New(context->GetIsolate(), 256));
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000016797 context->Global()->Set(v8_str("ext_array"), obj2);
16798 result = CompileRun("ext_array[''] = function() {return 1503;};"
16799 "ext_array['']();");
16800 }
16801
ager@chromium.org3811b432009-10-28 14:53:37 +000016802 free(array_data);
16803}
16804
16805
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016806THREADED_TEST(ExternalInt8Array) {
16807 ExternalArrayTestHelper<i::ExternalInt8Array, int8_t>(
16808 v8::kExternalInt8Array,
ager@chromium.org3811b432009-10-28 14:53:37 +000016809 -128,
16810 127);
16811}
16812
16813
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016814THREADED_TEST(ExternalUint8Array) {
16815 ExternalArrayTestHelper<i::ExternalUint8Array, uint8_t>(
16816 v8::kExternalUint8Array,
ager@chromium.org3811b432009-10-28 14:53:37 +000016817 0,
16818 255);
16819}
16820
16821
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016822THREADED_TEST(ExternalUint8ClampedArray) {
16823 ExternalArrayTestHelper<i::ExternalUint8ClampedArray, uint8_t>(
16824 v8::kExternalUint8ClampedArray,
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000016825 0,
16826 255);
16827}
16828
16829
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016830THREADED_TEST(ExternalInt16Array) {
16831 ExternalArrayTestHelper<i::ExternalInt16Array, int16_t>(
16832 v8::kExternalInt16Array,
ager@chromium.org3811b432009-10-28 14:53:37 +000016833 -32768,
16834 32767);
16835}
16836
16837
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016838THREADED_TEST(ExternalUint16Array) {
16839 ExternalArrayTestHelper<i::ExternalUint16Array, uint16_t>(
16840 v8::kExternalUint16Array,
ager@chromium.org3811b432009-10-28 14:53:37 +000016841 0,
16842 65535);
16843}
16844
16845
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016846THREADED_TEST(ExternalInt32Array) {
16847 ExternalArrayTestHelper<i::ExternalInt32Array, int32_t>(
16848 v8::kExternalInt32Array,
ager@chromium.org3811b432009-10-28 14:53:37 +000016849 INT_MIN, // -2147483648
16850 INT_MAX); // 2147483647
16851}
16852
16853
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016854THREADED_TEST(ExternalUint32Array) {
16855 ExternalArrayTestHelper<i::ExternalUint32Array, uint32_t>(
16856 v8::kExternalUint32Array,
ager@chromium.org3811b432009-10-28 14:53:37 +000016857 0,
16858 UINT_MAX); // 4294967295
16859}
16860
16861
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016862THREADED_TEST(ExternalFloat32Array) {
16863 ExternalArrayTestHelper<i::ExternalFloat32Array, float>(
16864 v8::kExternalFloat32Array,
ager@chromium.org3811b432009-10-28 14:53:37 +000016865 -500,
16866 500);
16867}
16868
16869
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016870THREADED_TEST(ExternalFloat64Array) {
16871 ExternalArrayTestHelper<i::ExternalFloat64Array, double>(
16872 v8::kExternalFloat64Array,
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +000016873 -500,
16874 500);
16875}
16876
16877
ager@chromium.org3811b432009-10-28 14:53:37 +000016878THREADED_TEST(ExternalArrays) {
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016879 TestExternalInt8Array();
16880 TestExternalUint8Array();
16881 TestExternalInt16Array();
16882 TestExternalUint16Array();
16883 TestExternalInt32Array();
16884 TestExternalUint32Array();
16885 TestExternalFloat32Array();
ager@chromium.org3811b432009-10-28 14:53:37 +000016886}
16887
16888
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016889void ExternalArrayInfoTestHelper(v8::ExternalArrayType array_type) {
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016890 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016891 v8::HandleScope scope(context->GetIsolate());
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016892 for (int size = 0; size < 100; size += 10) {
16893 int element_size = ExternalArrayElementSize(array_type);
16894 void* external_data = malloc(size * element_size);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016895 v8::Handle<v8::Object> obj = v8::Object::New(context->GetIsolate());
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016896 obj->SetIndexedPropertiesToExternalArrayData(
16897 external_data, array_type, size);
16898 CHECK(obj->HasIndexedPropertiesInExternalArrayData());
16899 CHECK_EQ(external_data, obj->GetIndexedPropertiesExternalArrayData());
16900 CHECK_EQ(array_type, obj->GetIndexedPropertiesExternalArrayDataType());
16901 CHECK_EQ(size, obj->GetIndexedPropertiesExternalArrayDataLength());
16902 free(external_data);
16903 }
16904}
16905
16906
16907THREADED_TEST(ExternalArrayInfo) {
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016908 ExternalArrayInfoTestHelper(v8::kExternalInt8Array);
16909 ExternalArrayInfoTestHelper(v8::kExternalUint8Array);
16910 ExternalArrayInfoTestHelper(v8::kExternalInt16Array);
16911 ExternalArrayInfoTestHelper(v8::kExternalUint16Array);
16912 ExternalArrayInfoTestHelper(v8::kExternalInt32Array);
16913 ExternalArrayInfoTestHelper(v8::kExternalUint32Array);
16914 ExternalArrayInfoTestHelper(v8::kExternalFloat32Array);
16915 ExternalArrayInfoTestHelper(v8::kExternalFloat64Array);
16916 ExternalArrayInfoTestHelper(v8::kExternalUint8ClampedArray);
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016917}
16918
16919
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016920void ExtArrayLimitsHelper(v8::Isolate* isolate,
16921 v8::ExternalArrayType array_type,
16922 int size) {
16923 v8::Handle<v8::Object> obj = v8::Object::New(isolate);
danno@chromium.org412fa512012-09-14 13:28:26 +000016924 v8::V8::SetFatalErrorHandler(StoringErrorCallback);
16925 last_location = last_message = NULL;
16926 obj->SetIndexedPropertiesToExternalArrayData(NULL, array_type, size);
16927 CHECK(!obj->HasIndexedPropertiesInExternalArrayData());
16928 CHECK_NE(NULL, last_location);
16929 CHECK_NE(NULL, last_message);
16930}
16931
16932
16933TEST(ExternalArrayLimits) {
danno@chromium.org412fa512012-09-14 13:28:26 +000016934 LocalContext context;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016935 v8::Isolate* isolate = context->GetIsolate();
16936 v8::HandleScope scope(isolate);
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016937 ExtArrayLimitsHelper(isolate, v8::kExternalInt8Array, 0x40000000);
16938 ExtArrayLimitsHelper(isolate, v8::kExternalInt8Array, 0xffffffff);
16939 ExtArrayLimitsHelper(isolate, v8::kExternalUint8Array, 0x40000000);
16940 ExtArrayLimitsHelper(isolate, v8::kExternalUint8Array, 0xffffffff);
16941 ExtArrayLimitsHelper(isolate, v8::kExternalInt16Array, 0x40000000);
16942 ExtArrayLimitsHelper(isolate, v8::kExternalInt16Array, 0xffffffff);
16943 ExtArrayLimitsHelper(isolate, v8::kExternalUint16Array, 0x40000000);
16944 ExtArrayLimitsHelper(isolate, v8::kExternalUint16Array, 0xffffffff);
16945 ExtArrayLimitsHelper(isolate, v8::kExternalInt32Array, 0x40000000);
16946 ExtArrayLimitsHelper(isolate, v8::kExternalInt32Array, 0xffffffff);
16947 ExtArrayLimitsHelper(isolate, v8::kExternalUint32Array, 0x40000000);
16948 ExtArrayLimitsHelper(isolate, v8::kExternalUint32Array, 0xffffffff);
16949 ExtArrayLimitsHelper(isolate, v8::kExternalFloat32Array, 0x40000000);
16950 ExtArrayLimitsHelper(isolate, v8::kExternalFloat32Array, 0xffffffff);
16951 ExtArrayLimitsHelper(isolate, v8::kExternalFloat64Array, 0x40000000);
16952 ExtArrayLimitsHelper(isolate, v8::kExternalFloat64Array, 0xffffffff);
16953 ExtArrayLimitsHelper(isolate, v8::kExternalUint8ClampedArray, 0x40000000);
16954 ExtArrayLimitsHelper(isolate, v8::kExternalUint8ClampedArray, 0xffffffff);
danno@chromium.org412fa512012-09-14 13:28:26 +000016955}
16956
16957
danno@chromium.orgf005df62013-04-30 16:36:45 +000016958template <typename ElementType, typename TypedArray,
16959 class ExternalArrayClass>
16960void TypedArrayTestHelper(v8::ExternalArrayType array_type,
16961 int64_t low, int64_t high) {
16962 const int kElementCount = 50;
danno@chromium.orgf005df62013-04-30 16:36:45 +000016963
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +000016964 i::ScopedVector<ElementType> backing_store(kElementCount+2);
16965
danno@chromium.orgf005df62013-04-30 16:36:45 +000016966 LocalContext env;
16967 v8::Isolate* isolate = env->GetIsolate();
16968 v8::HandleScope handle_scope(isolate);
16969
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000016970 Local<v8::ArrayBuffer> ab =
16971 v8::ArrayBuffer::New(isolate, backing_store.start(),
16972 (kElementCount + 2) * sizeof(ElementType));
danno@chromium.orgf005df62013-04-30 16:36:45 +000016973 Local<TypedArray> ta =
16974 TypedArray::New(ab, 2*sizeof(ElementType), kElementCount);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000016975 CheckInternalFieldsAreZero<v8::ArrayBufferView>(ta);
danno@chromium.orgf005df62013-04-30 16:36:45 +000016976 CHECK_EQ(kElementCount, static_cast<int>(ta->Length()));
16977 CHECK_EQ(2*sizeof(ElementType), static_cast<int>(ta->ByteOffset()));
16978 CHECK_EQ(kElementCount*sizeof(ElementType),
16979 static_cast<int>(ta->ByteLength()));
16980 CHECK_EQ(ab, ta->Buffer());
16981
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +000016982 ElementType* data = backing_store.start() + 2;
danno@chromium.orgf005df62013-04-30 16:36:45 +000016983 for (int i = 0; i < kElementCount; i++) {
16984 data[i] = static_cast<ElementType>(i);
16985 }
16986
16987 ObjectWithExternalArrayTestHelper<ExternalArrayClass, ElementType>(
16988 env.local(), ta, kElementCount, array_type, low, high);
16989}
16990
16991
16992THREADED_TEST(Uint8Array) {
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016993 TypedArrayTestHelper<uint8_t, v8::Uint8Array, i::ExternalUint8Array>(
16994 v8::kExternalUint8Array, 0, 0xFF);
danno@chromium.orgf005df62013-04-30 16:36:45 +000016995}
16996
16997
16998THREADED_TEST(Int8Array) {
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016999 TypedArrayTestHelper<int8_t, v8::Int8Array, i::ExternalInt8Array>(
17000 v8::kExternalInt8Array, -0x80, 0x7F);
danno@chromium.orgf005df62013-04-30 16:36:45 +000017001}
17002
17003
17004THREADED_TEST(Uint16Array) {
17005 TypedArrayTestHelper<uint16_t,
17006 v8::Uint16Array,
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000017007 i::ExternalUint16Array>(
17008 v8::kExternalUint16Array, 0, 0xFFFF);
danno@chromium.orgf005df62013-04-30 16:36:45 +000017009}
17010
17011
17012THREADED_TEST(Int16Array) {
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000017013 TypedArrayTestHelper<int16_t, v8::Int16Array, i::ExternalInt16Array>(
17014 v8::kExternalInt16Array, -0x8000, 0x7FFF);
danno@chromium.orgf005df62013-04-30 16:36:45 +000017015}
17016
17017
17018THREADED_TEST(Uint32Array) {
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000017019 TypedArrayTestHelper<uint32_t, v8::Uint32Array, i::ExternalUint32Array>(
17020 v8::kExternalUint32Array, 0, UINT_MAX);
danno@chromium.orgf005df62013-04-30 16:36:45 +000017021}
17022
17023
17024THREADED_TEST(Int32Array) {
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000017025 TypedArrayTestHelper<int32_t, v8::Int32Array, i::ExternalInt32Array>(
17026 v8::kExternalInt32Array, INT_MIN, INT_MAX);
danno@chromium.orgf005df62013-04-30 16:36:45 +000017027}
17028
17029
17030THREADED_TEST(Float32Array) {
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000017031 TypedArrayTestHelper<float, v8::Float32Array, i::ExternalFloat32Array>(
17032 v8::kExternalFloat32Array, -500, 500);
danno@chromium.orgf005df62013-04-30 16:36:45 +000017033}
17034
17035
17036THREADED_TEST(Float64Array) {
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000017037 TypedArrayTestHelper<double, v8::Float64Array, i::ExternalFloat64Array>(
17038 v8::kExternalFloat64Array, -500, 500);
danno@chromium.orgf005df62013-04-30 16:36:45 +000017039}
17040
17041
ulan@chromium.org57ff8812013-05-10 08:16:55 +000017042THREADED_TEST(Uint8ClampedArray) {
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000017043 TypedArrayTestHelper<uint8_t,
17044 v8::Uint8ClampedArray, i::ExternalUint8ClampedArray>(
17045 v8::kExternalUint8ClampedArray, 0, 0xFF);
ulan@chromium.org57ff8812013-05-10 08:16:55 +000017046}
17047
17048
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000017049THREADED_TEST(DataView) {
17050 const int kSize = 50;
17051
17052 i::ScopedVector<uint8_t> backing_store(kSize+2);
17053
17054 LocalContext env;
17055 v8::Isolate* isolate = env->GetIsolate();
17056 v8::HandleScope handle_scope(isolate);
17057
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000017058 Local<v8::ArrayBuffer> ab =
17059 v8::ArrayBuffer::New(isolate, backing_store.start(), 2 + kSize);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000017060 Local<v8::DataView> dv =
17061 v8::DataView::New(ab, 2, kSize);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000017062 CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000017063 CHECK_EQ(2, static_cast<int>(dv->ByteOffset()));
17064 CHECK_EQ(kSize, static_cast<int>(dv->ByteLength()));
17065 CHECK_EQ(ab, dv->Buffer());
17066}
17067
17068
17069#define IS_ARRAY_BUFFER_VIEW_TEST(View) \
17070 THREADED_TEST(Is##View) { \
ulan@chromium.org57ff8812013-05-10 08:16:55 +000017071 LocalContext env; \
17072 v8::Isolate* isolate = env->GetIsolate(); \
17073 v8::HandleScope handle_scope(isolate); \
17074 \
17075 Handle<Value> result = CompileRun( \
17076 "var ab = new ArrayBuffer(128);" \
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000017077 "new " #View "(ab)"); \
17078 CHECK(result->IsArrayBufferView()); \
17079 CHECK(result->Is##View()); \
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000017080 CheckInternalFieldsAreZero<v8::ArrayBufferView>(result.As<v8::View>()); \
ulan@chromium.org57ff8812013-05-10 08:16:55 +000017081 }
17082
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000017083IS_ARRAY_BUFFER_VIEW_TEST(Uint8Array)
17084IS_ARRAY_BUFFER_VIEW_TEST(Int8Array)
17085IS_ARRAY_BUFFER_VIEW_TEST(Uint16Array)
17086IS_ARRAY_BUFFER_VIEW_TEST(Int16Array)
17087IS_ARRAY_BUFFER_VIEW_TEST(Uint32Array)
17088IS_ARRAY_BUFFER_VIEW_TEST(Int32Array)
17089IS_ARRAY_BUFFER_VIEW_TEST(Float32Array)
17090IS_ARRAY_BUFFER_VIEW_TEST(Float64Array)
17091IS_ARRAY_BUFFER_VIEW_TEST(Uint8ClampedArray)
17092IS_ARRAY_BUFFER_VIEW_TEST(DataView)
ulan@chromium.org57ff8812013-05-10 08:16:55 +000017093
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000017094#undef IS_ARRAY_BUFFER_VIEW_TEST
ulan@chromium.org57ff8812013-05-10 08:16:55 +000017095
17096
17097
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000017098THREADED_TEST(ScriptContextDependence) {
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000017099 LocalContext c1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017100 v8::HandleScope scope(c1->GetIsolate());
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000017101 const char *source = "foo";
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000017102 v8::Handle<v8::Script> dep =
17103 v8::Script::Compile(v8::String::NewFromUtf8(c1->GetIsolate(), source));
17104 v8::Handle<v8::Script> indep =
17105 v8::Script::New(v8::String::NewFromUtf8(c1->GetIsolate(), source));
17106 c1->Global()->Set(v8::String::NewFromUtf8(c1->GetIsolate(), "foo"),
ulan@chromium.org0f13e742014-01-03 15:51:11 +000017107 v8::Integer::New(c1->GetIsolate(), 100));
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000017108 CHECK_EQ(dep->Run()->Int32Value(), 100);
17109 CHECK_EQ(indep->Run()->Int32Value(), 100);
17110 LocalContext c2;
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000017111 c2->Global()->Set(v8::String::NewFromUtf8(c2->GetIsolate(), "foo"),
ulan@chromium.org0f13e742014-01-03 15:51:11 +000017112 v8::Integer::New(c2->GetIsolate(), 101));
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000017113 CHECK_EQ(dep->Run()->Int32Value(), 100);
17114 CHECK_EQ(indep->Run()->Int32Value(), 101);
17115}
17116
ager@chromium.org96c75b52009-08-26 09:13:16 +000017117
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000017118THREADED_TEST(StackTrace) {
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000017119 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017120 v8::HandleScope scope(context->GetIsolate());
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000017121 v8::TryCatch try_catch;
17122 const char *source = "function foo() { FAIL.FAIL; }; foo();";
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000017123 v8::Handle<v8::String> src =
17124 v8::String::NewFromUtf8(context->GetIsolate(), source);
17125 v8::Handle<v8::String> origin =
17126 v8::String::NewFromUtf8(context->GetIsolate(), "stack-trace-test");
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000017127 v8::Script::New(src, origin)->Run();
17128 CHECK(try_catch.HasCaught());
17129 v8::String::Utf8Value stack(try_catch.StackTrace());
17130 CHECK(strstr(*stack, "at foo (stack-trace-test") != NULL);
17131}
ager@chromium.org96c75b52009-08-26 09:13:16 +000017132
17133
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017134// Checks that a StackFrame has certain expected values.
17135void checkStackFrame(const char* expected_script_name,
17136 const char* expected_func_name, int expected_line_number,
17137 int expected_column, bool is_eval, bool is_constructor,
17138 v8::Handle<v8::StackFrame> frame) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017139 v8::HandleScope scope(CcTest::isolate());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017140 v8::String::Utf8Value func_name(frame->GetFunctionName());
17141 v8::String::Utf8Value script_name(frame->GetScriptName());
17142 if (*script_name == NULL) {
17143 // The situation where there is no associated script, like for evals.
17144 CHECK(expected_script_name == NULL);
17145 } else {
17146 CHECK(strstr(*script_name, expected_script_name) != NULL);
17147 }
17148 CHECK(strstr(*func_name, expected_func_name) != NULL);
17149 CHECK_EQ(expected_line_number, frame->GetLineNumber());
17150 CHECK_EQ(expected_column, frame->GetColumn());
17151 CHECK_EQ(is_eval, frame->IsEval());
17152 CHECK_EQ(is_constructor, frame->IsConstructor());
17153}
17154
17155
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000017156void AnalyzeStackInNativeCode(const v8::FunctionCallbackInfo<v8::Value>& args) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017157 v8::HandleScope scope(args.GetIsolate());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017158 const char* origin = "capture-stack-trace-test";
17159 const int kOverviewTest = 1;
17160 const int kDetailedTest = 2;
17161
17162 ASSERT(args.Length() == 1);
17163
17164 int testGroup = args[0]->Int32Value();
17165 if (testGroup == kOverviewTest) {
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000017166 v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
17167 args.GetIsolate(), 10, v8::StackTrace::kOverview);
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017168 CHECK_EQ(4, stackTrace->GetFrameCount());
17169 checkStackFrame(origin, "bar", 2, 10, false, false,
17170 stackTrace->GetFrame(0));
17171 checkStackFrame(origin, "foo", 6, 3, false, false,
17172 stackTrace->GetFrame(1));
whesse@chromium.org030d38e2011-07-13 13:23:34 +000017173 // This is the source string inside the eval which has the call to foo.
17174 checkStackFrame(NULL, "", 1, 5, false, false,
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017175 stackTrace->GetFrame(2));
whesse@chromium.org030d38e2011-07-13 13:23:34 +000017176 // The last frame is an anonymous function which has the initial eval call.
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017177 checkStackFrame(origin, "", 8, 7, false, false,
17178 stackTrace->GetFrame(3));
17179
17180 CHECK(stackTrace->AsArray()->IsArray());
17181 } else if (testGroup == kDetailedTest) {
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000017182 v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
17183 args.GetIsolate(), 10, v8::StackTrace::kDetailed);
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017184 CHECK_EQ(4, stackTrace->GetFrameCount());
17185 checkStackFrame(origin, "bat", 4, 22, false, false,
17186 stackTrace->GetFrame(0));
17187 checkStackFrame(origin, "baz", 8, 3, false, true,
17188 stackTrace->GetFrame(1));
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +000017189#ifdef ENABLE_DEBUGGER_SUPPORT
17190 bool is_eval = true;
17191#else // ENABLE_DEBUGGER_SUPPORT
17192 bool is_eval = false;
17193#endif // ENABLE_DEBUGGER_SUPPORT
17194
whesse@chromium.org030d38e2011-07-13 13:23:34 +000017195 // This is the source string inside the eval which has the call to baz.
17196 checkStackFrame(NULL, "", 1, 5, is_eval, false,
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017197 stackTrace->GetFrame(2));
whesse@chromium.org030d38e2011-07-13 13:23:34 +000017198 // The last frame is an anonymous function which has the initial eval call.
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017199 checkStackFrame(origin, "", 10, 1, false, false,
17200 stackTrace->GetFrame(3));
17201
17202 CHECK(stackTrace->AsArray()->IsArray());
17203 }
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017204}
17205
17206
17207// Tests the C++ StackTrace API.
kasperl@chromium.orga5551262010-12-07 12:49:48 +000017208// TODO(3074796): Reenable this as a THREADED_TEST once it passes.
17209// THREADED_TEST(CaptureStackTrace) {
17210TEST(CaptureStackTrace) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017211 v8::Isolate* isolate = CcTest::isolate();
17212 v8::HandleScope scope(isolate);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000017213 v8::Handle<v8::String> origin =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017214 v8::String::NewFromUtf8(isolate, "capture-stack-trace-test");
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000017215 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017216 templ->Set(v8_str("AnalyzeStackInNativeCode"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017217 v8::FunctionTemplate::New(isolate, AnalyzeStackInNativeCode));
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017218 LocalContext context(0, templ);
17219
17220 // Test getting OVERVIEW information. Should ignore information that is not
17221 // script name, function name, line number, and column offset.
17222 const char *overview_source =
17223 "function bar() {\n"
17224 " var y; AnalyzeStackInNativeCode(1);\n"
17225 "}\n"
17226 "function foo() {\n"
17227 "\n"
17228 " bar();\n"
17229 "}\n"
17230 "var x;eval('new foo();');";
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000017231 v8::Handle<v8::String> overview_src =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017232 v8::String::NewFromUtf8(isolate, overview_source);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000017233 v8::Handle<Value> overview_result(
17234 v8::Script::New(overview_src, origin)->Run());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000017235 CHECK(!overview_result.IsEmpty());
17236 CHECK(overview_result->IsObject());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017237
17238 // Test getting DETAILED information.
17239 const char *detailed_source =
17240 "function bat() {AnalyzeStackInNativeCode(2);\n"
17241 "}\n"
17242 "\n"
17243 "function baz() {\n"
17244 " bat();\n"
17245 "}\n"
17246 "eval('new baz();');";
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000017247 v8::Handle<v8::String> detailed_src =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017248 v8::String::NewFromUtf8(isolate, detailed_source);
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017249 // Make the script using a non-zero line and column offset.
ulan@chromium.org0f13e742014-01-03 15:51:11 +000017250 v8::Handle<v8::Integer> line_offset = v8::Integer::New(isolate, 3);
17251 v8::Handle<v8::Integer> column_offset = v8::Integer::New(isolate, 5);
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017252 v8::ScriptOrigin detailed_origin(origin, line_offset, column_offset);
17253 v8::Handle<v8::Script> detailed_script(
17254 v8::Script::New(detailed_src, &detailed_origin));
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000017255 v8::Handle<Value> detailed_result(detailed_script->Run());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000017256 CHECK(!detailed_result.IsEmpty());
17257 CHECK(detailed_result->IsObject());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017258}
17259
17260
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000017261static void StackTraceForUncaughtExceptionListener(
17262 v8::Handle<v8::Message> message,
17263 v8::Handle<Value>) {
17264 v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
17265 CHECK_EQ(2, stack_trace->GetFrameCount());
17266 checkStackFrame("origin", "foo", 2, 3, false, false,
17267 stack_trace->GetFrame(0));
17268 checkStackFrame("origin", "bar", 5, 3, false, false,
17269 stack_trace->GetFrame(1));
17270}
17271
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000017272
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000017273TEST(CaptureStackTraceForUncaughtException) {
17274 report_count = 0;
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000017275 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017276 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000017277 v8::V8::AddMessageListener(StackTraceForUncaughtExceptionListener);
17278 v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
17279
17280 Script::Compile(v8_str("function foo() {\n"
17281 " throw 1;\n"
17282 "};\n"
17283 "function bar() {\n"
17284 " foo();\n"
17285 "};"),
17286 v8_str("origin"))->Run();
17287 v8::Local<v8::Object> global = env->Global();
17288 Local<Value> trouble = global->Get(v8_str("bar"));
17289 CHECK(trouble->IsFunction());
17290 Function::Cast(*trouble)->Call(global, 0, NULL);
17291 v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
17292 v8::V8::RemoveMessageListeners(StackTraceForUncaughtExceptionListener);
17293}
17294
17295
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000017296TEST(CaptureStackTraceForUncaughtExceptionAndSetters) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000017297 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017298 v8::HandleScope scope(env->GetIsolate());
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000017299 v8::V8::SetCaptureStackTraceForUncaughtExceptions(true,
17300 1024,
17301 v8::StackTrace::kDetailed);
17302
17303 CompileRun(
17304 "var setters = ['column', 'lineNumber', 'scriptName',\n"
17305 " 'scriptNameOrSourceURL', 'functionName', 'isEval',\n"
17306 " 'isConstructor'];\n"
17307 "for (var i = 0; i < setters.length; i++) {\n"
17308 " var prop = setters[i];\n"
17309 " Object.prototype.__defineSetter__(prop, function() { throw prop; });\n"
17310 "}\n");
17311 CompileRun("throw 'exception';");
17312 v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
17313}
17314
17315
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000017316static void RethrowStackTraceHandler(v8::Handle<v8::Message> message,
17317 v8::Handle<v8::Value> data) {
17318 // Use the frame where JavaScript is called from.
17319 v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
17320 CHECK(!stack_trace.IsEmpty());
17321 int frame_count = stack_trace->GetFrameCount();
17322 CHECK_EQ(3, frame_count);
17323 int line_number[] = {1, 2, 5};
17324 for (int i = 0; i < frame_count; i++) {
17325 CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber());
17326 }
17327}
17328
17329
17330// Test that we only return the stack trace at the site where the exception
17331// is first thrown (not where it is rethrown).
17332TEST(RethrowStackTrace) {
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000017333 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017334 v8::HandleScope scope(env->GetIsolate());
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000017335 // We make sure that
17336 // - the stack trace of the ReferenceError in g() is reported.
17337 // - the stack trace is not overwritten when e1 is rethrown by t().
17338 // - the stack trace of e2 does not overwrite that of e1.
17339 const char* source =
17340 "function g() { error; } \n"
17341 "function f() { g(); } \n"
17342 "function t(e) { throw e; } \n"
17343 "try { \n"
17344 " f(); \n"
17345 "} catch (e1) { \n"
17346 " try { \n"
17347 " error; \n"
17348 " } catch (e2) { \n"
17349 " t(e1); \n"
17350 " } \n"
17351 "} \n";
17352 v8::V8::AddMessageListener(RethrowStackTraceHandler);
17353 v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
17354 CompileRun(source);
17355 v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
17356 v8::V8::RemoveMessageListeners(RethrowStackTraceHandler);
17357}
17358
17359
17360static void RethrowPrimitiveStackTraceHandler(v8::Handle<v8::Message> message,
17361 v8::Handle<v8::Value> data) {
17362 v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
17363 CHECK(!stack_trace.IsEmpty());
17364 int frame_count = stack_trace->GetFrameCount();
17365 CHECK_EQ(2, frame_count);
17366 int line_number[] = {3, 7};
17367 for (int i = 0; i < frame_count; i++) {
17368 CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber());
17369 }
17370}
17371
17372
17373// Test that we do not recognize identity for primitive exceptions.
17374TEST(RethrowPrimitiveStackTrace) {
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000017375 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017376 v8::HandleScope scope(env->GetIsolate());
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000017377 // We do not capture stack trace for non Error objects on creation time.
17378 // Instead, we capture the stack trace on last throw.
17379 const char* source =
17380 "function g() { throw 404; } \n"
17381 "function f() { g(); } \n"
17382 "function t(e) { throw e; } \n"
17383 "try { \n"
17384 " f(); \n"
17385 "} catch (e1) { \n"
17386 " t(e1) \n"
17387 "} \n";
17388 v8::V8::AddMessageListener(RethrowPrimitiveStackTraceHandler);
17389 v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
17390 CompileRun(source);
17391 v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
17392 v8::V8::RemoveMessageListeners(RethrowPrimitiveStackTraceHandler);
17393}
17394
17395
17396static void RethrowExistingStackTraceHandler(v8::Handle<v8::Message> message,
17397 v8::Handle<v8::Value> data) {
17398 // Use the frame where JavaScript is called from.
17399 v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
17400 CHECK(!stack_trace.IsEmpty());
17401 CHECK_EQ(1, stack_trace->GetFrameCount());
17402 CHECK_EQ(1, stack_trace->GetFrame(0)->GetLineNumber());
17403}
17404
17405
17406// Test that the stack trace is captured when the error object is created and
17407// not where it is thrown.
17408TEST(RethrowExistingStackTrace) {
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000017409 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017410 v8::HandleScope scope(env->GetIsolate());
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000017411 const char* source =
17412 "var e = new Error(); \n"
17413 "throw e; \n";
17414 v8::V8::AddMessageListener(RethrowExistingStackTraceHandler);
17415 v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
17416 CompileRun(source);
17417 v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
17418 v8::V8::RemoveMessageListeners(RethrowExistingStackTraceHandler);
17419}
17420
17421
17422static void RethrowBogusErrorStackTraceHandler(v8::Handle<v8::Message> message,
17423 v8::Handle<v8::Value> data) {
17424 // Use the frame where JavaScript is called from.
17425 v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
17426 CHECK(!stack_trace.IsEmpty());
17427 CHECK_EQ(1, stack_trace->GetFrameCount());
17428 CHECK_EQ(2, stack_trace->GetFrame(0)->GetLineNumber());
17429}
17430
17431
17432// Test that the stack trace is captured where the bogus Error object is thrown.
17433TEST(RethrowBogusErrorStackTrace) {
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000017434 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017435 v8::HandleScope scope(env->GetIsolate());
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000017436 const char* source =
17437 "var e = {__proto__: new Error()} \n"
17438 "throw e; \n";
17439 v8::V8::AddMessageListener(RethrowBogusErrorStackTraceHandler);
17440 v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
17441 CompileRun(source);
17442 v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
17443 v8::V8::RemoveMessageListeners(RethrowBogusErrorStackTraceHandler);
17444}
17445
17446
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000017447void AnalyzeStackOfEvalWithSourceURL(
17448 const v8::FunctionCallbackInfo<v8::Value>& args) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017449 v8::HandleScope scope(args.GetIsolate());
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000017450 v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
17451 args.GetIsolate(), 10, v8::StackTrace::kDetailed);
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000017452 CHECK_EQ(5, stackTrace->GetFrameCount());
17453 v8::Handle<v8::String> url = v8_str("eval_url");
17454 for (int i = 0; i < 3; i++) {
17455 v8::Handle<v8::String> name =
17456 stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
17457 CHECK(!name.IsEmpty());
17458 CHECK_EQ(url, name);
17459 }
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000017460}
17461
17462
17463TEST(SourceURLInStackTrace) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017464 v8::Isolate* isolate = CcTest::isolate();
17465 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000017466 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000017467 templ->Set(v8_str("AnalyzeStackOfEvalWithSourceURL"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017468 v8::FunctionTemplate::New(isolate,
17469 AnalyzeStackOfEvalWithSourceURL));
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000017470 LocalContext context(0, templ);
17471
17472 const char *source =
17473 "function outer() {\n"
17474 "function bar() {\n"
17475 " AnalyzeStackOfEvalWithSourceURL();\n"
17476 "}\n"
17477 "function foo() {\n"
17478 "\n"
17479 " bar();\n"
17480 "}\n"
17481 "foo();\n"
17482 "}\n"
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000017483 "eval('(' + outer +')()%s');";
17484
17485 i::ScopedVector<char> code(1024);
17486 i::OS::SNPrintF(code, source, "//# sourceURL=eval_url");
17487 CHECK(CompileRun(code.start())->IsUndefined());
17488 i::OS::SNPrintF(code, source, "//@ sourceURL=eval_url");
17489 CHECK(CompileRun(code.start())->IsUndefined());
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000017490}
17491
17492
jkummerow@chromium.org8fa5bd92013-09-02 11:45:09 +000017493static int scriptIdInStack[2];
17494
17495void AnalyzeScriptIdInStack(
17496 const v8::FunctionCallbackInfo<v8::Value>& args) {
17497 v8::HandleScope scope(args.GetIsolate());
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000017498 v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
17499 args.GetIsolate(), 10, v8::StackTrace::kScriptId);
jkummerow@chromium.org8fa5bd92013-09-02 11:45:09 +000017500 CHECK_EQ(2, stackTrace->GetFrameCount());
17501 for (int i = 0; i < 2; i++) {
17502 scriptIdInStack[i] = stackTrace->GetFrame(i)->GetScriptId();
17503 }
17504}
17505
17506
17507TEST(ScriptIdInStackTrace) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017508 v8::Isolate* isolate = CcTest::isolate();
17509 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000017510 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
jkummerow@chromium.org8fa5bd92013-09-02 11:45:09 +000017511 templ->Set(v8_str("AnalyzeScriptIdInStack"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017512 v8::FunctionTemplate::New(isolate, AnalyzeScriptIdInStack));
jkummerow@chromium.org8fa5bd92013-09-02 11:45:09 +000017513 LocalContext context(0, templ);
17514
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000017515 v8::Handle<v8::String> scriptSource = v8::String::NewFromUtf8(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017516 isolate,
jkummerow@chromium.org8fa5bd92013-09-02 11:45:09 +000017517 "function foo() {\n"
17518 " AnalyzeScriptIdInStack();"
17519 "}\n"
17520 "foo();\n");
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000017521 v8::ScriptOrigin origin =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017522 v8::ScriptOrigin(v8::String::NewFromUtf8(isolate, "test"));
jkummerow@chromium.org8fa5bd92013-09-02 11:45:09 +000017523 v8::Local<v8::Script> script(v8::Script::Compile(scriptSource, &origin));
17524 script->Run();
17525 for (int i = 0; i < 2; i++) {
17526 CHECK(scriptIdInStack[i] != v8::Message::kNoScriptIdInfo);
17527 CHECK_EQ(scriptIdInStack[i], script->GetId());
17528 }
17529}
17530
17531
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000017532void AnalyzeStackOfInlineScriptWithSourceURL(
17533 const v8::FunctionCallbackInfo<v8::Value>& args) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017534 v8::HandleScope scope(args.GetIsolate());
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000017535 v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
17536 args.GetIsolate(), 10, v8::StackTrace::kDetailed);
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000017537 CHECK_EQ(4, stackTrace->GetFrameCount());
17538 v8::Handle<v8::String> url = v8_str("url");
17539 for (int i = 0; i < 3; i++) {
17540 v8::Handle<v8::String> name =
17541 stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
17542 CHECK(!name.IsEmpty());
17543 CHECK_EQ(url, name);
17544 }
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000017545}
17546
17547
17548TEST(InlineScriptWithSourceURLInStackTrace) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000017549 v8::Isolate* isolate = CcTest::isolate();
17550 v8::HandleScope scope(isolate);
17551 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000017552 templ->Set(v8_str("AnalyzeStackOfInlineScriptWithSourceURL"),
17553 v8::FunctionTemplate::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017554 CcTest::isolate(), AnalyzeStackOfInlineScriptWithSourceURL));
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000017555 LocalContext context(0, templ);
17556
17557 const char *source =
17558 "function outer() {\n"
17559 "function bar() {\n"
17560 " AnalyzeStackOfInlineScriptWithSourceURL();\n"
17561 "}\n"
17562 "function foo() {\n"
17563 "\n"
17564 " bar();\n"
17565 "}\n"
17566 "foo();\n"
17567 "}\n"
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000017568 "outer()\n%s";
17569
17570 i::ScopedVector<char> code(1024);
17571 i::OS::SNPrintF(code, source, "//# sourceURL=source_url");
17572 CHECK(CompileRunWithOrigin(code.start(), "url", 0, 1)->IsUndefined());
17573 i::OS::SNPrintF(code, source, "//@ sourceURL=source_url");
17574 CHECK(CompileRunWithOrigin(code.start(), "url", 0, 1)->IsUndefined());
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000017575}
17576
17577
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000017578void AnalyzeStackOfDynamicScriptWithSourceURL(
17579 const v8::FunctionCallbackInfo<v8::Value>& args) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017580 v8::HandleScope scope(args.GetIsolate());
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000017581 v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
17582 args.GetIsolate(), 10, v8::StackTrace::kDetailed);
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000017583 CHECK_EQ(4, stackTrace->GetFrameCount());
17584 v8::Handle<v8::String> url = v8_str("source_url");
17585 for (int i = 0; i < 3; i++) {
17586 v8::Handle<v8::String> name =
17587 stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
17588 CHECK(!name.IsEmpty());
17589 CHECK_EQ(url, name);
17590 }
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000017591}
17592
17593
17594TEST(DynamicWithSourceURLInStackTrace) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000017595 v8::Isolate* isolate = CcTest::isolate();
17596 v8::HandleScope scope(isolate);
17597 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000017598 templ->Set(v8_str("AnalyzeStackOfDynamicScriptWithSourceURL"),
17599 v8::FunctionTemplate::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017600 CcTest::isolate(), AnalyzeStackOfDynamicScriptWithSourceURL));
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000017601 LocalContext context(0, templ);
17602
17603 const char *source =
17604 "function outer() {\n"
17605 "function bar() {\n"
17606 " AnalyzeStackOfDynamicScriptWithSourceURL();\n"
17607 "}\n"
17608 "function foo() {\n"
17609 "\n"
17610 " bar();\n"
17611 "}\n"
17612 "foo();\n"
17613 "}\n"
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000017614 "outer()\n%s";
17615
17616 i::ScopedVector<char> code(1024);
17617 i::OS::SNPrintF(code, source, "//# sourceURL=source_url");
17618 CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined());
17619 i::OS::SNPrintF(code, source, "//@ sourceURL=source_url");
17620 CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined());
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000017621}
17622
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000017623
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017624static void CreateGarbageInOldSpace() {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017625 i::Factory* factory = CcTest::i_isolate()->factory();
17626 v8::HandleScope scope(CcTest::isolate());
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017627 i::AlwaysAllocateScope always_allocate;
17628 for (int i = 0; i < 1000; i++) {
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000017629 factory->NewFixedArray(1000, i::TENURED);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017630 }
svenpanne@chromium.orgecb9dd62011-12-01 08:22:35 +000017631}
17632
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000017633
svenpanne@chromium.orgecb9dd62011-12-01 08:22:35 +000017634// Test that idle notification can be handled and eventually returns true.
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017635TEST(IdleNotification) {
17636 const intptr_t MB = 1024 * 1024;
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017637 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017638 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017639 intptr_t initial_size = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017640 CreateGarbageInOldSpace();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017641 intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017642 CHECK_GT(size_with_garbage, initial_size + MB);
17643 bool finished = false;
17644 for (int i = 0; i < 200 && !finished; i++) {
17645 finished = v8::V8::IdleNotification();
17646 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017647 intptr_t final_size = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017648 CHECK(finished);
17649 CHECK_LT(final_size, initial_size + 1);
17650}
17651
17652
17653// Test that idle notification can be handled and eventually collects garbage.
yangguo@chromium.org56454712012-02-16 15:33:53 +000017654TEST(IdleNotificationWithSmallHint) {
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017655 const intptr_t MB = 1024 * 1024;
17656 const int IdlePauseInMs = 900;
svenpanne@chromium.orgecb9dd62011-12-01 08:22:35 +000017657 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017658 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017659 intptr_t initial_size = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017660 CreateGarbageInOldSpace();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017661 intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017662 CHECK_GT(size_with_garbage, initial_size + MB);
17663 bool finished = false;
17664 for (int i = 0; i < 200 && !finished; i++) {
17665 finished = v8::V8::IdleNotification(IdlePauseInMs);
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017666 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017667 intptr_t final_size = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017668 CHECK(finished);
17669 CHECK_LT(final_size, initial_size + 1);
yangguo@chromium.org56454712012-02-16 15:33:53 +000017670}
17671
17672
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017673// Test that idle notification can be handled and eventually collects garbage.
yangguo@chromium.org56454712012-02-16 15:33:53 +000017674TEST(IdleNotificationWithLargeHint) {
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017675 const intptr_t MB = 1024 * 1024;
17676 const int IdlePauseInMs = 900;
yangguo@chromium.org56454712012-02-16 15:33:53 +000017677 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017678 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017679 intptr_t initial_size = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017680 CreateGarbageInOldSpace();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017681 intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017682 CHECK_GT(size_with_garbage, initial_size + MB);
17683 bool finished = false;
17684 for (int i = 0; i < 200 && !finished; i++) {
17685 finished = v8::V8::IdleNotification(IdlePauseInMs);
yangguo@chromium.org56454712012-02-16 15:33:53 +000017686 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017687 intptr_t final_size = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017688 CHECK(finished);
17689 CHECK_LT(final_size, initial_size + 1);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017690}
17691
17692
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017693TEST(Regress2107) {
17694 const intptr_t MB = 1024 * 1024;
17695 const int kShortIdlePauseInMs = 100;
17696 const int kLongIdlePauseInMs = 1000;
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017697 LocalContext env;
ulan@chromium.org57ff8812013-05-10 08:16:55 +000017698 v8::Isolate* isolate = env->GetIsolate();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017699 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017700 intptr_t initial_size = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017701 // Send idle notification to start a round of incremental GCs.
17702 v8::V8::IdleNotification(kShortIdlePauseInMs);
17703 // Emulate 7 page reloads.
17704 for (int i = 0; i < 7; i++) {
ulan@chromium.org57ff8812013-05-10 08:16:55 +000017705 {
17706 v8::HandleScope inner_scope(env->GetIsolate());
17707 v8::Local<v8::Context> ctx = v8::Context::New(isolate);
17708 ctx->Enter();
17709 CreateGarbageInOldSpace();
17710 ctx->Exit();
17711 }
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017712 v8::V8::ContextDisposedNotification();
17713 v8::V8::IdleNotification(kLongIdlePauseInMs);
17714 }
17715 // Create garbage and check that idle notification still collects it.
17716 CreateGarbageInOldSpace();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017717 intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017718 CHECK_GT(size_with_garbage, initial_size + MB);
17719 bool finished = false;
17720 for (int i = 0; i < 200 && !finished; i++) {
17721 finished = v8::V8::IdleNotification(kShortIdlePauseInMs);
17722 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017723 intptr_t final_size = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017724 CHECK_LT(final_size, initial_size + 1);
17725}
17726
machenbach@chromium.orgb5be0a92013-11-15 10:32:41 +000017727
17728TEST(Regress2333) {
17729 LocalContext env;
17730 for (int i = 0; i < 3; i++) {
17731 CcTest::heap()->PerformScavenge();
17732 }
17733}
17734
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017735static uint32_t* stack_limit;
17736
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000017737static void GetStackLimitCallback(
17738 const v8::FunctionCallbackInfo<v8::Value>& args) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000017739 stack_limit = reinterpret_cast<uint32_t*>(
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017740 CcTest::i_isolate()->stack_guard()->real_climit());
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017741}
17742
17743
17744// Uses the address of a local variable to determine the stack top now.
17745// Given a size, returns an address that is that far from the current
17746// top of stack.
17747static uint32_t* ComputeStackLimit(uint32_t size) {
17748 uint32_t* answer = &size - (size / sizeof(size));
17749 // If the size is very large and the stack is very near the bottom of
17750 // memory then the calculation above may wrap around and give an address
17751 // that is above the (downwards-growing) stack. In that case we return
17752 // a very low address.
17753 if (answer > &size) return reinterpret_cast<uint32_t*>(sizeof(size));
17754 return answer;
17755}
17756
17757
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +000017758// We need at least 165kB for an x64 debug build with clang and ASAN.
17759static const int stack_breathing_room = 256 * i::KB;
17760
17761
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017762TEST(SetResourceConstraints) {
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +000017763 uint32_t* set_limit = ComputeStackLimit(stack_breathing_room);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017764
17765 // Set stack limit.
17766 v8::ResourceConstraints constraints;
17767 constraints.set_stack_limit(set_limit);
machenbach@chromium.org7ff76072013-11-21 09:47:43 +000017768 CHECK(v8::SetResourceConstraints(CcTest::isolate(), &constraints));
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017769
17770 // Execute a script.
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017771 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017772 v8::HandleScope scope(env->GetIsolate());
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017773 Local<v8::FunctionTemplate> fun_templ =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017774 v8::FunctionTemplate::New(env->GetIsolate(), GetStackLimitCallback);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017775 Local<Function> fun = fun_templ->GetFunction();
17776 env->Global()->Set(v8_str("get_stack_limit"), fun);
17777 CompileRun("get_stack_limit();");
17778
17779 CHECK(stack_limit == set_limit);
17780}
17781
17782
17783TEST(SetResourceConstraintsInThread) {
17784 uint32_t* set_limit;
17785 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017786 v8::Locker locker(CcTest::isolate());
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +000017787 set_limit = ComputeStackLimit(stack_breathing_room);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017788
17789 // Set stack limit.
17790 v8::ResourceConstraints constraints;
17791 constraints.set_stack_limit(set_limit);
machenbach@chromium.org7ff76072013-11-21 09:47:43 +000017792 CHECK(v8::SetResourceConstraints(CcTest::isolate(), &constraints));
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017793
17794 // Execute a script.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017795 v8::HandleScope scope(CcTest::isolate());
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017796 LocalContext env;
17797 Local<v8::FunctionTemplate> fun_templ =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017798 v8::FunctionTemplate::New(CcTest::isolate(), GetStackLimitCallback);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017799 Local<Function> fun = fun_templ->GetFunction();
17800 env->Global()->Set(v8_str("get_stack_limit"), fun);
17801 CompileRun("get_stack_limit();");
17802
17803 CHECK(stack_limit == set_limit);
17804 }
17805 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017806 v8::Locker locker(CcTest::isolate());
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017807 CHECK(stack_limit == set_limit);
17808 }
ager@chromium.org96c75b52009-08-26 09:13:16 +000017809}
ager@chromium.org3811b432009-10-28 14:53:37 +000017810
17811
17812THREADED_TEST(GetHeapStatistics) {
ager@chromium.org3811b432009-10-28 14:53:37 +000017813 LocalContext c1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017814 v8::HandleScope scope(c1->GetIsolate());
ager@chromium.org3811b432009-10-28 14:53:37 +000017815 v8::HeapStatistics heap_statistics;
ager@chromium.orgc4c92722009-11-18 14:12:51 +000017816 CHECK_EQ(static_cast<int>(heap_statistics.total_heap_size()), 0);
17817 CHECK_EQ(static_cast<int>(heap_statistics.used_heap_size()), 0);
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +000017818 c1->GetIsolate()->GetHeapStatistics(&heap_statistics);
ager@chromium.orgc4c92722009-11-18 14:12:51 +000017819 CHECK_NE(static_cast<int>(heap_statistics.total_heap_size()), 0);
17820 CHECK_NE(static_cast<int>(heap_statistics.used_heap_size()), 0);
ager@chromium.org3811b432009-10-28 14:53:37 +000017821}
17822
17823
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017824class VisitorImpl : public v8::ExternalResourceVisitor {
17825 public:
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017826 explicit VisitorImpl(TestResource** resource) {
17827 for (int i = 0; i < 4; i++) {
17828 resource_[i] = resource[i];
17829 found_resource_[i] = false;
17830 }
17831 }
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017832 virtual ~VisitorImpl() {}
17833 virtual void VisitExternalString(v8::Handle<v8::String> string) {
17834 if (!string->IsExternal()) {
17835 CHECK(string->IsExternalAscii());
17836 return;
17837 }
17838 v8::String::ExternalStringResource* resource =
17839 string->GetExternalStringResource();
17840 CHECK(resource);
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017841 for (int i = 0; i < 4; i++) {
17842 if (resource_[i] == resource) {
17843 CHECK(!found_resource_[i]);
17844 found_resource_[i] = true;
17845 }
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017846 }
17847 }
17848 void CheckVisitedResources() {
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017849 for (int i = 0; i < 4; i++) {
17850 CHECK(found_resource_[i]);
17851 }
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017852 }
17853
17854 private:
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017855 v8::String::ExternalStringResource* resource_[4];
17856 bool found_resource_[4];
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017857};
17858
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000017859
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017860TEST(VisitExternalStrings) {
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017861 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017862 v8::HandleScope scope(env->GetIsolate());
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017863 const char* string = "Some string";
17864 uint16_t* two_byte_string = AsciiToTwoByteString(string);
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017865 TestResource* resource[4];
17866 resource[0] = new TestResource(two_byte_string);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000017867 v8::Local<v8::String> string0 =
17868 v8::String::NewExternal(env->GetIsolate(), resource[0]);
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017869 resource[1] = new TestResource(two_byte_string);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000017870 v8::Local<v8::String> string1 =
17871 v8::String::NewExternal(env->GetIsolate(), resource[1]);
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017872
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017873 // Externalized symbol.
17874 resource[2] = new TestResource(two_byte_string);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000017875 v8::Local<v8::String> string2 = v8::String::NewFromUtf8(
17876 env->GetIsolate(), string, v8::String::kInternalizedString);
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017877 CHECK(string2->MakeExternal(resource[2]));
17878
17879 // Symbolized External.
17880 resource[3] = new TestResource(AsciiToTwoByteString("Some other string"));
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000017881 v8::Local<v8::String> string3 =
17882 v8::String::NewExternal(env->GetIsolate(), resource[3]);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017883 CcTest::heap()->CollectAllAvailableGarbage(); // Tenure string.
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017884 // Turn into a symbol.
17885 i::Handle<i::String> string3_i = v8::Utils::OpenHandle(*string3);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017886 CHECK(!CcTest::heap()->InternalizeString(*string3_i)->IsFailure());
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +000017887 CHECK(string3_i->IsInternalizedString());
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017888
17889 // We need to add usages for string* to avoid warnings in GCC 4.7
17890 CHECK(string0->IsExternal());
ulan@chromium.org2efb9002012-01-19 15:36:35 +000017891 CHECK(string1->IsExternal());
17892 CHECK(string2->IsExternal());
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017893 CHECK(string3->IsExternal());
ulan@chromium.org2efb9002012-01-19 15:36:35 +000017894
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017895 VisitorImpl visitor(resource);
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017896 v8::V8::VisitExternalResources(&visitor);
17897 visitor.CheckVisitedResources();
17898}
17899
17900
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000017901TEST(ExternalStringCollectedAtTearDown) {
17902 int destroyed = 0;
17903 v8::Isolate* isolate = v8::Isolate::New();
17904 { v8::Isolate::Scope isolate_scope(isolate);
17905 v8::HandleScope handle_scope(isolate);
17906 const char* s = "One string to test them all, one string to find them.";
17907 TestAsciiResource* inscription =
17908 new TestAsciiResource(i::StrDup(s), &destroyed);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000017909 v8::Local<v8::String> ring = v8::String::NewExternal(isolate, inscription);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000017910 // Ring is still alive. Orcs are roaming freely across our lands.
17911 CHECK_EQ(0, destroyed);
17912 USE(ring);
17913 }
17914
17915 isolate->Dispose();
17916 // Ring has been destroyed. Free Peoples of Middle-earth Rejoice.
17917 CHECK_EQ(1, destroyed);
17918}
17919
17920
jkummerow@chromium.org113035e2013-12-13 15:13:40 +000017921TEST(ExternalInternalizedStringCollectedAtTearDown) {
17922 int destroyed = 0;
17923 v8::Isolate* isolate = v8::Isolate::New();
17924 { v8::Isolate::Scope isolate_scope(isolate);
17925 LocalContext env(isolate);
17926 v8::HandleScope handle_scope(isolate);
17927 CompileRun("var ring = 'One string to test them all';");
17928 const char* s = "One string to test them all";
17929 TestAsciiResource* inscription =
17930 new TestAsciiResource(i::StrDup(s), &destroyed);
17931 v8::Local<v8::String> ring = CompileRun("ring")->ToString();
17932 CHECK(v8::Utils::OpenHandle(*ring)->IsInternalizedString());
17933 ring->MakeExternal(inscription);
17934 // Ring is still alive. Orcs are roaming freely across our lands.
17935 CHECK_EQ(0, destroyed);
17936 USE(ring);
17937 }
17938
17939 isolate->Dispose();
17940 // Ring has been destroyed. Free Peoples of Middle-earth Rejoice.
17941 CHECK_EQ(1, destroyed);
17942}
17943
17944
17945TEST(ExternalInternalizedStringCollectedAtGC) {
17946 int destroyed = 0;
17947 { LocalContext env;
17948 v8::HandleScope handle_scope(env->GetIsolate());
17949 CompileRun("var ring = 'One string to test them all';");
17950 const char* s = "One string to test them all";
17951 TestAsciiResource* inscription =
17952 new TestAsciiResource(i::StrDup(s), &destroyed);
17953 v8::Local<v8::String> ring = CompileRun("ring")->ToString();
17954 CHECK(v8::Utils::OpenHandle(*ring)->IsInternalizedString());
17955 ring->MakeExternal(inscription);
17956 // Ring is still alive. Orcs are roaming freely across our lands.
17957 CHECK_EQ(0, destroyed);
17958 USE(ring);
17959 }
17960
17961 // Garbage collector deals swift blows to evil.
17962 CcTest::i_isolate()->compilation_cache()->Clear();
17963 CcTest::heap()->CollectAllAvailableGarbage();
17964
17965 // Ring has been destroyed. Free Peoples of Middle-earth Rejoice.
17966 CHECK_EQ(1, destroyed);
17967}
17968
17969
ager@chromium.org3811b432009-10-28 14:53:37 +000017970static double DoubleFromBits(uint64_t value) {
17971 double target;
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +000017972 i::OS::MemCopy(&target, &value, sizeof(target));
ager@chromium.org3811b432009-10-28 14:53:37 +000017973 return target;
17974}
17975
17976
17977static uint64_t DoubleToBits(double value) {
17978 uint64_t target;
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +000017979 i::OS::MemCopy(&target, &value, sizeof(target));
ager@chromium.org3811b432009-10-28 14:53:37 +000017980 return target;
17981}
17982
17983
17984static double DoubleToDateTime(double input) {
17985 double date_limit = 864e13;
ulan@chromium.org77ca49a2013-04-22 09:43:56 +000017986 if (std::isnan(input) || input < -date_limit || input > date_limit) {
ager@chromium.org3811b432009-10-28 14:53:37 +000017987 return i::OS::nan_value();
17988 }
machenbach@chromium.orge31286d2014-01-15 10:29:52 +000017989 return (input < 0) ? -(std::floor(-input)) : std::floor(input);
ager@chromium.org3811b432009-10-28 14:53:37 +000017990}
17991
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000017992
ager@chromium.org3811b432009-10-28 14:53:37 +000017993// We don't have a consistent way to write 64-bit constants syntactically, so we
17994// split them into two 32-bit constants and combine them programmatically.
17995static double DoubleFromBits(uint32_t high_bits, uint32_t low_bits) {
17996 return DoubleFromBits((static_cast<uint64_t>(high_bits) << 32) | low_bits);
17997}
17998
17999
18000THREADED_TEST(QuietSignalingNaNs) {
ager@chromium.org3811b432009-10-28 14:53:37 +000018001 LocalContext context;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018002 v8::Isolate* isolate = context->GetIsolate();
18003 v8::HandleScope scope(isolate);
ager@chromium.org3811b432009-10-28 14:53:37 +000018004 v8::TryCatch try_catch;
18005
18006 // Special double values.
18007 double snan = DoubleFromBits(0x7ff00000, 0x00000001);
18008 double qnan = DoubleFromBits(0x7ff80000, 0x00000000);
18009 double infinity = DoubleFromBits(0x7ff00000, 0x00000000);
18010 double max_normal = DoubleFromBits(0x7fefffff, 0xffffffffu);
18011 double min_normal = DoubleFromBits(0x00100000, 0x00000000);
18012 double max_denormal = DoubleFromBits(0x000fffff, 0xffffffffu);
18013 double min_denormal = DoubleFromBits(0x00000000, 0x00000001);
18014
18015 // Date values are capped at +/-100000000 days (times 864e5 ms per day)
18016 // on either side of the epoch.
18017 double date_limit = 864e13;
18018
18019 double test_values[] = {
18020 snan,
18021 qnan,
18022 infinity,
18023 max_normal,
18024 date_limit + 1,
18025 date_limit,
18026 min_normal,
18027 max_denormal,
18028 min_denormal,
18029 0,
18030 -0,
18031 -min_denormal,
18032 -max_denormal,
18033 -min_normal,
18034 -date_limit,
18035 -date_limit - 1,
18036 -max_normal,
18037 -infinity,
18038 -qnan,
18039 -snan
18040 };
18041 int num_test_values = 20;
18042
18043 for (int i = 0; i < num_test_values; i++) {
18044 double test_value = test_values[i];
18045
18046 // Check that Number::New preserves non-NaNs and quiets SNaNs.
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018047 v8::Handle<v8::Value> number = v8::Number::New(isolate, test_value);
ager@chromium.org3811b432009-10-28 14:53:37 +000018048 double stored_number = number->NumberValue();
ulan@chromium.org77ca49a2013-04-22 09:43:56 +000018049 if (!std::isnan(test_value)) {
ager@chromium.org3811b432009-10-28 14:53:37 +000018050 CHECK_EQ(test_value, stored_number);
18051 } else {
18052 uint64_t stored_bits = DoubleToBits(stored_number);
18053 // Check if quiet nan (bits 51..62 all set).
danno@chromium.orgc612e022011-11-10 11:38:15 +000018054#if defined(V8_TARGET_ARCH_MIPS) && !defined(USE_SIMULATOR)
18055 // Most significant fraction bit for quiet nan is set to 0
18056 // on MIPS architecture. Allowed by IEEE-754.
18057 CHECK_EQ(0xffe, static_cast<int>((stored_bits >> 51) & 0xfff));
18058#else
ager@chromium.org3811b432009-10-28 14:53:37 +000018059 CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff));
danno@chromium.orgc612e022011-11-10 11:38:15 +000018060#endif
ager@chromium.org3811b432009-10-28 14:53:37 +000018061 }
18062
18063 // Check that Date::New preserves non-NaNs in the date range and
18064 // quiets SNaNs.
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000018065 v8::Handle<v8::Value> date =
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018066 v8::Date::New(isolate, test_value);
ager@chromium.org3811b432009-10-28 14:53:37 +000018067 double expected_stored_date = DoubleToDateTime(test_value);
18068 double stored_date = date->NumberValue();
ulan@chromium.org77ca49a2013-04-22 09:43:56 +000018069 if (!std::isnan(expected_stored_date)) {
ager@chromium.org3811b432009-10-28 14:53:37 +000018070 CHECK_EQ(expected_stored_date, stored_date);
18071 } else {
18072 uint64_t stored_bits = DoubleToBits(stored_date);
18073 // Check if quiet nan (bits 51..62 all set).
danno@chromium.orgc612e022011-11-10 11:38:15 +000018074#if defined(V8_TARGET_ARCH_MIPS) && !defined(USE_SIMULATOR)
18075 // Most significant fraction bit for quiet nan is set to 0
18076 // on MIPS architecture. Allowed by IEEE-754.
18077 CHECK_EQ(0xffe, static_cast<int>((stored_bits >> 51) & 0xfff));
18078#else
ager@chromium.org3811b432009-10-28 14:53:37 +000018079 CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff));
danno@chromium.orgc612e022011-11-10 11:38:15 +000018080#endif
ager@chromium.org3811b432009-10-28 14:53:37 +000018081 }
18082 }
18083}
christian.plesner.hansen@gmail.comb9ce6372009-11-03 11:38:18 +000018084
18085
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018086static void SpaghettiIncident(
18087 const v8::FunctionCallbackInfo<v8::Value>& args) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018088 v8::HandleScope scope(args.GetIsolate());
christian.plesner.hansen@gmail.comb9ce6372009-11-03 11:38:18 +000018089 v8::TryCatch tc;
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000018090 v8::Handle<v8::String> str(args[0]->ToString());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000018091 USE(str);
christian.plesner.hansen@gmail.comb9ce6372009-11-03 11:38:18 +000018092 if (tc.HasCaught())
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018093 tc.ReThrow();
christian.plesner.hansen@gmail.comb9ce6372009-11-03 11:38:18 +000018094}
18095
18096
18097// Test that an exception can be propagated down through a spaghetti
18098// stack using ReThrow.
18099THREADED_TEST(SpaghettiStackReThrow) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000018100 v8::Isolate* isolate = CcTest::isolate();
18101 v8::HandleScope scope(isolate);
christian.plesner.hansen@gmail.comb9ce6372009-11-03 11:38:18 +000018102 LocalContext context;
18103 context->Global()->Set(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000018104 v8::String::NewFromUtf8(isolate, "s"),
18105 v8::FunctionTemplate::New(isolate, SpaghettiIncident)->GetFunction());
christian.plesner.hansen@gmail.comb9ce6372009-11-03 11:38:18 +000018106 v8::TryCatch try_catch;
18107 CompileRun(
18108 "var i = 0;"
18109 "var o = {"
18110 " toString: function () {"
18111 " if (i == 10) {"
18112 " throw 'Hey!';"
18113 " } else {"
18114 " i++;"
18115 " return s(o);"
18116 " }"
18117 " }"
18118 "};"
18119 "s(o);");
18120 CHECK(try_catch.HasCaught());
18121 v8::String::Utf8Value value(try_catch.Exception());
18122 CHECK_EQ(0, strcmp(*value, "Hey!"));
18123}
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018124
18125
sgjesse@chromium.org98180592009-12-02 08:17:28 +000018126TEST(Regress528) {
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018127 v8::V8::Initialize();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018128 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000018129 v8::HandleScope scope(isolate);
18130 v8::Local<Context> other_context;
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018131 int gc_count;
18132
ager@chromium.org60121232009-12-03 11:25:37 +000018133 // Create a context used to keep the code from aging in the compilation
18134 // cache.
ulan@chromium.org57ff8812013-05-10 08:16:55 +000018135 other_context = Context::New(isolate);
ager@chromium.org60121232009-12-03 11:25:37 +000018136
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018137 // Context-dependent context data creates reference from the compilation
18138 // cache to the global object.
ager@chromium.org60121232009-12-03 11:25:37 +000018139 const char* source_simple = "1";
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018140 {
ulan@chromium.org57ff8812013-05-10 08:16:55 +000018141 v8::HandleScope scope(isolate);
18142 v8::Local<Context> context = Context::New(isolate);
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018143
18144 context->Enter();
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018145 Local<v8::String> obj = v8::String::NewFromUtf8(isolate, "");
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000018146 context->SetEmbedderData(0, obj);
ager@chromium.org60121232009-12-03 11:25:37 +000018147 CompileRun(source_simple);
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018148 context->Exit();
18149 }
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000018150 v8::V8::ContextDisposedNotification();
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018151 for (gc_count = 1; gc_count < 10; gc_count++) {
ager@chromium.org60121232009-12-03 11:25:37 +000018152 other_context->Enter();
18153 CompileRun(source_simple);
18154 other_context->Exit();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018155 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org60121232009-12-03 11:25:37 +000018156 if (GetGlobalObjectsCount() == 1) break;
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018157 }
ager@chromium.org60121232009-12-03 11:25:37 +000018158 CHECK_GE(2, gc_count);
18159 CHECK_EQ(1, GetGlobalObjectsCount());
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018160
18161 // Eval in a function creates reference from the compilation cache to the
18162 // global object.
ager@chromium.org60121232009-12-03 11:25:37 +000018163 const char* source_eval = "function f(){eval('1')}; f()";
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018164 {
ulan@chromium.org57ff8812013-05-10 08:16:55 +000018165 v8::HandleScope scope(isolate);
18166 v8::Local<Context> context = Context::New(isolate);
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018167
18168 context->Enter();
ager@chromium.org60121232009-12-03 11:25:37 +000018169 CompileRun(source_eval);
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018170 context->Exit();
18171 }
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000018172 v8::V8::ContextDisposedNotification();
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018173 for (gc_count = 1; gc_count < 10; gc_count++) {
ager@chromium.org60121232009-12-03 11:25:37 +000018174 other_context->Enter();
18175 CompileRun(source_eval);
18176 other_context->Exit();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018177 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org60121232009-12-03 11:25:37 +000018178 if (GetGlobalObjectsCount() == 1) break;
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018179 }
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +000018180 CHECK_GE(2, gc_count);
sgjesse@chromium.org98180592009-12-02 08:17:28 +000018181 CHECK_EQ(1, GetGlobalObjectsCount());
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018182
18183 // Looking up the line number for an exception creates reference from the
18184 // compilation cache to the global object.
ager@chromium.org60121232009-12-03 11:25:37 +000018185 const char* source_exception = "function f(){throw 1;} f()";
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018186 {
ulan@chromium.org57ff8812013-05-10 08:16:55 +000018187 v8::HandleScope scope(isolate);
18188 v8::Local<Context> context = Context::New(isolate);
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018189
18190 context->Enter();
18191 v8::TryCatch try_catch;
ager@chromium.org60121232009-12-03 11:25:37 +000018192 CompileRun(source_exception);
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018193 CHECK(try_catch.HasCaught());
18194 v8::Handle<v8::Message> message = try_catch.Message();
18195 CHECK(!message.IsEmpty());
18196 CHECK_EQ(1, message->GetLineNumber());
18197 context->Exit();
18198 }
svenpanne@chromium.orgc859c4f2012-10-15 11:51:39 +000018199 v8::V8::ContextDisposedNotification();
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018200 for (gc_count = 1; gc_count < 10; gc_count++) {
ager@chromium.org60121232009-12-03 11:25:37 +000018201 other_context->Enter();
18202 CompileRun(source_exception);
18203 other_context->Exit();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018204 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org60121232009-12-03 11:25:37 +000018205 if (GetGlobalObjectsCount() == 1) break;
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018206 }
ager@chromium.org60121232009-12-03 11:25:37 +000018207 CHECK_GE(2, gc_count);
18208 CHECK_EQ(1, GetGlobalObjectsCount());
18209
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000018210 v8::V8::ContextDisposedNotification();
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018211}
ager@chromium.org5c838252010-02-19 08:53:10 +000018212
18213
18214THREADED_TEST(ScriptOrigin) {
ager@chromium.org5c838252010-02-19 08:53:10 +000018215 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018216 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018217 v8::ScriptOrigin origin =
18218 v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
18219 v8::Handle<v8::String> script = v8::String::NewFromUtf8(
18220 env->GetIsolate(), "function f() {}\n\nfunction g() {}");
ager@chromium.org5c838252010-02-19 08:53:10 +000018221 v8::Script::Compile(script, &origin)->Run();
18222 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018223 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
ager@chromium.org5c838252010-02-19 08:53:10 +000018224 v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018225 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
ager@chromium.org5c838252010-02-19 08:53:10 +000018226
18227 v8::ScriptOrigin script_origin_f = f->GetScriptOrigin();
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000018228 CHECK_EQ("test", *v8::String::Utf8Value(script_origin_f.ResourceName()));
ager@chromium.org5c838252010-02-19 08:53:10 +000018229 CHECK_EQ(0, script_origin_f.ResourceLineOffset()->Int32Value());
18230
18231 v8::ScriptOrigin script_origin_g = g->GetScriptOrigin();
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000018232 CHECK_EQ("test", *v8::String::Utf8Value(script_origin_g.ResourceName()));
ager@chromium.org5c838252010-02-19 08:53:10 +000018233 CHECK_EQ(0, script_origin_g.ResourceLineOffset()->Int32Value());
18234}
18235
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000018236
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000018237THREADED_TEST(FunctionGetInferredName) {
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000018238 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018239 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018240 v8::ScriptOrigin origin =
18241 v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
18242 v8::Handle<v8::String> script = v8::String::NewFromUtf8(
18243 env->GetIsolate(),
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000018244 "var foo = { bar : { baz : function() {}}}; var f = foo.bar.baz;");
18245 v8::Script::Compile(script, &origin)->Run();
18246 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018247 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000018248 CHECK_EQ("foo.bar.baz", *v8::String::Utf8Value(f->GetInferredName()));
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000018249}
ager@chromium.org5c838252010-02-19 08:53:10 +000018250
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000018251
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +000018252THREADED_TEST(FunctionGetDisplayName) {
18253 LocalContext env;
18254 v8::HandleScope scope(env->GetIsolate());
18255 const char* code = "var error = false;"
18256 "function a() { this.x = 1; };"
18257 "a.displayName = 'display_a';"
18258 "var b = (function() {"
18259 " var f = function() { this.x = 2; };"
18260 " f.displayName = 'display_b';"
18261 " return f;"
18262 "})();"
18263 "var c = function() {};"
18264 "c.__defineGetter__('displayName', function() {"
18265 " error = true;"
18266 " throw new Error();"
18267 "});"
18268 "function d() {};"
18269 "d.__defineGetter__('displayName', function() {"
18270 " error = true;"
18271 " return 'wrong_display_name';"
18272 "});"
18273 "function e() {};"
18274 "e.displayName = 'wrong_display_name';"
18275 "e.__defineSetter__('displayName', function() {"
18276 " error = true;"
18277 " throw new Error();"
18278 "});"
18279 "function f() {};"
18280 "f.displayName = { 'foo': 6, toString: function() {"
18281 " error = true;"
18282 " return 'wrong_display_name';"
18283 "}};"
18284 "var g = function() {"
18285 " arguments.callee.displayName = 'set_in_runtime';"
18286 "}; g();"
18287 ;
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018288 v8::ScriptOrigin origin =
18289 v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
18290 v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(), code), &origin)
18291 ->Run();
18292 v8::Local<v8::Value> error =
18293 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "error"));
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +000018294 v8::Local<v8::Function> a = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018295 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "a")));
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +000018296 v8::Local<v8::Function> b = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018297 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "b")));
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +000018298 v8::Local<v8::Function> c = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018299 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "c")));
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +000018300 v8::Local<v8::Function> d = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018301 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "d")));
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +000018302 v8::Local<v8::Function> e = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018303 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "e")));
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +000018304 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018305 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +000018306 v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018307 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +000018308 CHECK_EQ(false, error->BooleanValue());
18309 CHECK_EQ("display_a", *v8::String::Utf8Value(a->GetDisplayName()));
18310 CHECK_EQ("display_b", *v8::String::Utf8Value(b->GetDisplayName()));
18311 CHECK(c->GetDisplayName()->IsUndefined());
18312 CHECK(d->GetDisplayName()->IsUndefined());
18313 CHECK(e->GetDisplayName()->IsUndefined());
18314 CHECK(f->GetDisplayName()->IsUndefined());
18315 CHECK_EQ("set_in_runtime", *v8::String::Utf8Value(g->GetDisplayName()));
18316}
18317
18318
ager@chromium.org5c838252010-02-19 08:53:10 +000018319THREADED_TEST(ScriptLineNumber) {
ager@chromium.org5c838252010-02-19 08:53:10 +000018320 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018321 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018322 v8::ScriptOrigin origin =
18323 v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
18324 v8::Handle<v8::String> script = v8::String::NewFromUtf8(
18325 env->GetIsolate(), "function f() {}\n\nfunction g() {}");
ager@chromium.org5c838252010-02-19 08:53:10 +000018326 v8::Script::Compile(script, &origin)->Run();
18327 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018328 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
ager@chromium.org5c838252010-02-19 08:53:10 +000018329 v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018330 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
ager@chromium.org5c838252010-02-19 08:53:10 +000018331 CHECK_EQ(0, f->GetScriptLineNumber());
18332 CHECK_EQ(2, g->GetScriptLineNumber());
18333}
18334
18335
danno@chromium.orgc612e022011-11-10 11:38:15 +000018336THREADED_TEST(ScriptColumnNumber) {
danno@chromium.orgc612e022011-11-10 11:38:15 +000018337 LocalContext env;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018338 v8::Isolate* isolate = env->GetIsolate();
18339 v8::HandleScope scope(isolate);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018340 v8::ScriptOrigin origin =
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018341 v8::ScriptOrigin(v8::String::NewFromUtf8(isolate, "test"),
18342 v8::Integer::New(isolate, 3),
18343 v8::Integer::New(isolate, 2));
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018344 v8::Handle<v8::String> script = v8::String::NewFromUtf8(
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018345 isolate, "function foo() {}\n\n function bar() {}");
danno@chromium.orgc612e022011-11-10 11:38:15 +000018346 v8::Script::Compile(script, &origin)->Run();
18347 v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018348 env->Global()->Get(v8::String::NewFromUtf8(isolate, "foo")));
danno@chromium.orgc612e022011-11-10 11:38:15 +000018349 v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018350 env->Global()->Get(v8::String::NewFromUtf8(isolate, "bar")));
danno@chromium.orgc612e022011-11-10 11:38:15 +000018351 CHECK_EQ(14, foo->GetScriptColumnNumber());
18352 CHECK_EQ(17, bar->GetScriptColumnNumber());
18353}
18354
18355
bmeurer@chromium.orgdb783292013-10-23 06:51:00 +000018356THREADED_TEST(FunctionIsBuiltin) {
18357 LocalContext env;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018358 v8::Isolate* isolate = env->GetIsolate();
18359 v8::HandleScope scope(isolate);
bmeurer@chromium.orgdb783292013-10-23 06:51:00 +000018360 v8::Local<v8::Function> f;
18361 f = v8::Local<v8::Function>::Cast(CompileRun("Math.floor"));
18362 CHECK(f->IsBuiltin());
18363 f = v8::Local<v8::Function>::Cast(CompileRun("Object"));
18364 CHECK(f->IsBuiltin());
18365 f = v8::Local<v8::Function>::Cast(CompileRun("Object.__defineSetter__"));
18366 CHECK(f->IsBuiltin());
18367 f = v8::Local<v8::Function>::Cast(CompileRun("Array.prototype.toString"));
18368 CHECK(f->IsBuiltin());
18369 f = v8::Local<v8::Function>::Cast(CompileRun("function a() {}; a;"));
18370 CHECK(!f->IsBuiltin());
18371}
18372
18373
danno@chromium.orgc612e022011-11-10 11:38:15 +000018374THREADED_TEST(FunctionGetScriptId) {
danno@chromium.orgc612e022011-11-10 11:38:15 +000018375 LocalContext env;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018376 v8::Isolate* isolate = env->GetIsolate();
18377 v8::HandleScope scope(isolate);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018378 v8::ScriptOrigin origin =
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018379 v8::ScriptOrigin(v8::String::NewFromUtf8(isolate, "test"),
18380 v8::Integer::New(isolate, 3),
18381 v8::Integer::New(isolate, 2));
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018382 v8::Handle<v8::String> scriptSource = v8::String::NewFromUtf8(
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018383 isolate, "function foo() {}\n\n function bar() {}");
danno@chromium.orgc612e022011-11-10 11:38:15 +000018384 v8::Local<v8::Script> script(v8::Script::Compile(scriptSource, &origin));
18385 script->Run();
18386 v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018387 env->Global()->Get(v8::String::NewFromUtf8(isolate, "foo")));
danno@chromium.orgc612e022011-11-10 11:38:15 +000018388 v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018389 env->Global()->Get(v8::String::NewFromUtf8(isolate, "bar")));
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018390 CHECK_EQ(script->GetId(), foo->ScriptId());
18391 CHECK_EQ(script->GetId(), bar->ScriptId());
danno@chromium.orgc612e022011-11-10 11:38:15 +000018392}
18393
18394
yangguo@chromium.org49546742013-12-23 16:17:49 +000018395THREADED_TEST(FunctionGetBoundFunction) {
18396 LocalContext env;
18397 v8::HandleScope scope(env->GetIsolate());
18398 v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::NewFromUtf8(
18399 env->GetIsolate(), "test"));
18400 v8::Handle<v8::String> script = v8::String::NewFromUtf8(
18401 env->GetIsolate(),
18402 "var a = new Object();\n"
18403 "a.x = 1;\n"
18404 "function f () { return this.x };\n"
18405 "var g = f.bind(a);\n"
18406 "var b = g();");
18407 v8::Script::Compile(script, &origin)->Run();
18408 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
18409 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
18410 v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
18411 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
18412 CHECK(g->GetBoundFunction()->IsFunction());
18413 Local<v8::Function> original_function = Local<v8::Function>::Cast(
18414 g->GetBoundFunction());
18415 CHECK_EQ(f->GetName(), original_function->GetName());
18416 CHECK_EQ(f->GetScriptLineNumber(), original_function->GetScriptLineNumber());
18417 CHECK_EQ(f->GetScriptColumnNumber(),
18418 original_function->GetScriptColumnNumber());
18419}
18420
18421
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018422static void GetterWhichReturns42(
18423 Local<String> name,
18424 const v8::PropertyCallbackInfo<v8::Value>& info) {
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000018425 CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
18426 CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018427 info.GetReturnValue().Set(v8_num(42));
ager@chromium.org5c838252010-02-19 08:53:10 +000018428}
18429
18430
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018431static void SetterWhichSetsYOnThisTo23(
18432 Local<String> name,
18433 Local<Value> value,
18434 const v8::PropertyCallbackInfo<void>& info) {
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000018435 CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
18436 CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
ager@chromium.org5c838252010-02-19 08:53:10 +000018437 info.This()->Set(v8_str("y"), v8_num(23));
18438}
18439
18440
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018441void FooGetInterceptor(Local<String> name,
18442 const v8::PropertyCallbackInfo<v8::Value>& info) {
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000018443 CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
18444 CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018445 if (!name->Equals(v8_str("foo"))) return;
18446 info.GetReturnValue().Set(v8_num(42));
erik.corry@gmail.com88767242012-08-08 14:43:45 +000018447}
18448
18449
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018450void FooSetInterceptor(Local<String> name,
18451 Local<Value> value,
18452 const v8::PropertyCallbackInfo<v8::Value>& info) {
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000018453 CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
18454 CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018455 if (!name->Equals(v8_str("foo"))) return;
erik.corry@gmail.com88767242012-08-08 14:43:45 +000018456 info.This()->Set(v8_str("y"), v8_num(23));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018457 info.GetReturnValue().Set(v8_num(23));
erik.corry@gmail.com88767242012-08-08 14:43:45 +000018458}
18459
18460
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000018461TEST(SetterOnConstructorPrototype) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000018462 v8::Isolate* isolate = CcTest::isolate();
18463 v8::HandleScope scope(isolate);
18464 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +000018465 templ->SetAccessor(v8_str("x"),
18466 GetterWhichReturns42,
18467 SetterWhichSetsYOnThisTo23);
18468 LocalContext context;
18469 context->Global()->Set(v8_str("P"), templ->NewInstance());
18470 CompileRun("function C1() {"
18471 " this.x = 23;"
18472 "};"
18473 "C1.prototype = P;"
18474 "function C2() {"
18475 " this.x = 23"
18476 "};"
18477 "C2.prototype = { };"
18478 "C2.prototype.__proto__ = P;");
18479
18480 v8::Local<v8::Script> script;
18481 script = v8::Script::Compile(v8_str("new C1();"));
18482 for (int i = 0; i < 10; i++) {
18483 v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
18484 CHECK_EQ(42, c1->Get(v8_str("x"))->Int32Value());
18485 CHECK_EQ(23, c1->Get(v8_str("y"))->Int32Value());
18486 }
18487
18488 script = v8::Script::Compile(v8_str("new C2();"));
18489 for (int i = 0; i < 10; i++) {
18490 v8::Handle<v8::Object> c2 = v8::Handle<v8::Object>::Cast(script->Run());
18491 CHECK_EQ(42, c2->Get(v8_str("x"))->Int32Value());
18492 CHECK_EQ(23, c2->Get(v8_str("y"))->Int32Value());
18493 }
18494}
18495
18496
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018497static void NamedPropertyGetterWhichReturns42(
18498 Local<String> name,
18499 const v8::PropertyCallbackInfo<v8::Value>& info) {
18500 info.GetReturnValue().Set(v8_num(42));
ager@chromium.org5c838252010-02-19 08:53:10 +000018501}
18502
18503
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018504static void NamedPropertySetterWhichSetsYOnThisTo23(
18505 Local<String> name,
18506 Local<Value> value,
18507 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.org5c838252010-02-19 08:53:10 +000018508 if (name->Equals(v8_str("x"))) {
18509 info.This()->Set(v8_str("y"), v8_num(23));
18510 }
ager@chromium.org5c838252010-02-19 08:53:10 +000018511}
18512
18513
18514THREADED_TEST(InterceptorOnConstructorPrototype) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000018515 v8::Isolate* isolate = CcTest::isolate();
18516 v8::HandleScope scope(isolate);
18517 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +000018518 templ->SetNamedPropertyHandler(NamedPropertyGetterWhichReturns42,
18519 NamedPropertySetterWhichSetsYOnThisTo23);
18520 LocalContext context;
18521 context->Global()->Set(v8_str("P"), templ->NewInstance());
18522 CompileRun("function C1() {"
18523 " this.x = 23;"
18524 "};"
18525 "C1.prototype = P;"
18526 "function C2() {"
18527 " this.x = 23"
18528 "};"
18529 "C2.prototype = { };"
18530 "C2.prototype.__proto__ = P;");
18531
18532 v8::Local<v8::Script> script;
18533 script = v8::Script::Compile(v8_str("new C1();"));
18534 for (int i = 0; i < 10; i++) {
18535 v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
18536 CHECK_EQ(23, c1->Get(v8_str("x"))->Int32Value());
18537 CHECK_EQ(42, c1->Get(v8_str("y"))->Int32Value());
18538 }
18539
18540 script = v8::Script::Compile(v8_str("new C2();"));
18541 for (int i = 0; i < 10; i++) {
18542 v8::Handle<v8::Object> c2 = v8::Handle<v8::Object>::Cast(script->Run());
18543 CHECK_EQ(23, c2->Get(v8_str("x"))->Int32Value());
18544 CHECK_EQ(42, c2->Get(v8_str("y"))->Int32Value());
18545 }
18546}
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000018547
18548
danno@chromium.orgf005df62013-04-30 16:36:45 +000018549TEST(Regress618) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000018550 const char* source = "function C1() {"
18551 " this.x = 23;"
18552 "};"
18553 "C1.prototype = P;";
18554
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000018555 LocalContext context;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000018556 v8::Isolate* isolate = context->GetIsolate();
18557 v8::HandleScope scope(isolate);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000018558 v8::Local<v8::Script> script;
18559
18560 // Use a simple object as prototype.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000018561 v8::Local<v8::Object> prototype = v8::Object::New(isolate);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000018562 prototype->Set(v8_str("y"), v8_num(42));
18563 context->Global()->Set(v8_str("P"), prototype);
18564
18565 // This compile will add the code to the compilation cache.
18566 CompileRun(source);
18567
18568 script = v8::Script::Compile(v8_str("new C1();"));
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +000018569 // Allow enough iterations for the inobject slack tracking logic
18570 // to finalize instance size and install the fast construct stub.
18571 for (int i = 0; i < 256; i++) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000018572 v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
18573 CHECK_EQ(23, c1->Get(v8_str("x"))->Int32Value());
18574 CHECK_EQ(42, c1->Get(v8_str("y"))->Int32Value());
18575 }
18576
18577 // Use an API object with accessors as prototype.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000018578 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000018579 templ->SetAccessor(v8_str("x"),
18580 GetterWhichReturns42,
18581 SetterWhichSetsYOnThisTo23);
18582 context->Global()->Set(v8_str("P"), templ->NewInstance());
18583
18584 // This compile will get the code from the compilation cache.
18585 CompileRun(source);
18586
18587 script = v8::Script::Compile(v8_str("new C1();"));
18588 for (int i = 0; i < 10; i++) {
18589 v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
18590 CHECK_EQ(42, c1->Get(v8_str("x"))->Int32Value());
18591 CHECK_EQ(23, c1->Get(v8_str("y"))->Int32Value());
18592 }
18593}
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018594
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018595v8::Isolate* gc_callbacks_isolate = NULL;
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018596int prologue_call_count = 0;
18597int epilogue_call_count = 0;
18598int prologue_call_count_second = 0;
18599int epilogue_call_count_second = 0;
18600
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018601void PrologueCallback(v8::GCType, v8::GCCallbackFlags flags) {
18602 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018603 ++prologue_call_count;
18604}
18605
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000018606
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018607void PrologueCallback(v8::Isolate* isolate,
18608 v8::GCType,
18609 v8::GCCallbackFlags flags) {
18610 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
18611 CHECK_EQ(gc_callbacks_isolate, isolate);
18612 ++prologue_call_count;
18613}
18614
18615
18616void EpilogueCallback(v8::GCType, v8::GCCallbackFlags flags) {
18617 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018618 ++epilogue_call_count;
18619}
18620
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000018621
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018622void EpilogueCallback(v8::Isolate* isolate,
18623 v8::GCType,
18624 v8::GCCallbackFlags flags) {
18625 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
18626 CHECK_EQ(gc_callbacks_isolate, isolate);
18627 ++epilogue_call_count;
18628}
18629
18630
18631void PrologueCallbackSecond(v8::GCType, v8::GCCallbackFlags flags) {
18632 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018633 ++prologue_call_count_second;
18634}
18635
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000018636
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018637void PrologueCallbackSecond(v8::Isolate* isolate,
18638 v8::GCType,
18639 v8::GCCallbackFlags flags) {
18640 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
18641 CHECK_EQ(gc_callbacks_isolate, isolate);
18642 ++prologue_call_count_second;
18643}
18644
18645
18646void EpilogueCallbackSecond(v8::GCType, v8::GCCallbackFlags flags) {
18647 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018648 ++epilogue_call_count_second;
18649}
18650
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000018651
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018652void EpilogueCallbackSecond(v8::Isolate* isolate,
18653 v8::GCType,
18654 v8::GCCallbackFlags flags) {
18655 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
18656 CHECK_EQ(gc_callbacks_isolate, isolate);
18657 ++epilogue_call_count_second;
18658}
18659
18660
18661TEST(GCCallbacksOld) {
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018662 LocalContext context;
18663
18664 v8::V8::AddGCPrologueCallback(PrologueCallback);
18665 v8::V8::AddGCEpilogueCallback(EpilogueCallback);
18666 CHECK_EQ(0, prologue_call_count);
18667 CHECK_EQ(0, epilogue_call_count);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018668 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018669 CHECK_EQ(1, prologue_call_count);
18670 CHECK_EQ(1, epilogue_call_count);
18671 v8::V8::AddGCPrologueCallback(PrologueCallbackSecond);
18672 v8::V8::AddGCEpilogueCallback(EpilogueCallbackSecond);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018673 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018674 CHECK_EQ(2, prologue_call_count);
18675 CHECK_EQ(2, epilogue_call_count);
18676 CHECK_EQ(1, prologue_call_count_second);
18677 CHECK_EQ(1, epilogue_call_count_second);
18678 v8::V8::RemoveGCPrologueCallback(PrologueCallback);
18679 v8::V8::RemoveGCEpilogueCallback(EpilogueCallback);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018680 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018681 CHECK_EQ(2, prologue_call_count);
18682 CHECK_EQ(2, epilogue_call_count);
18683 CHECK_EQ(2, prologue_call_count_second);
18684 CHECK_EQ(2, epilogue_call_count_second);
18685 v8::V8::RemoveGCPrologueCallback(PrologueCallbackSecond);
18686 v8::V8::RemoveGCEpilogueCallback(EpilogueCallbackSecond);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018687 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
18688 CHECK_EQ(2, prologue_call_count);
18689 CHECK_EQ(2, epilogue_call_count);
18690 CHECK_EQ(2, prologue_call_count_second);
18691 CHECK_EQ(2, epilogue_call_count_second);
18692}
18693
18694
18695TEST(GCCallbacks) {
18696 LocalContext context;
18697 v8::Isolate* isolate = context->GetIsolate();
18698 gc_callbacks_isolate = isolate;
18699 isolate->AddGCPrologueCallback(PrologueCallback);
18700 isolate->AddGCEpilogueCallback(EpilogueCallback);
18701 CHECK_EQ(0, prologue_call_count);
18702 CHECK_EQ(0, epilogue_call_count);
18703 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
18704 CHECK_EQ(1, prologue_call_count);
18705 CHECK_EQ(1, epilogue_call_count);
18706 isolate->AddGCPrologueCallback(PrologueCallbackSecond);
18707 isolate->AddGCEpilogueCallback(EpilogueCallbackSecond);
18708 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
18709 CHECK_EQ(2, prologue_call_count);
18710 CHECK_EQ(2, epilogue_call_count);
18711 CHECK_EQ(1, prologue_call_count_second);
18712 CHECK_EQ(1, epilogue_call_count_second);
18713 isolate->RemoveGCPrologueCallback(PrologueCallback);
18714 isolate->RemoveGCEpilogueCallback(EpilogueCallback);
18715 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
18716 CHECK_EQ(2, prologue_call_count);
18717 CHECK_EQ(2, epilogue_call_count);
18718 CHECK_EQ(2, prologue_call_count_second);
18719 CHECK_EQ(2, epilogue_call_count_second);
18720 isolate->RemoveGCPrologueCallback(PrologueCallbackSecond);
18721 isolate->RemoveGCEpilogueCallback(EpilogueCallbackSecond);
18722 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018723 CHECK_EQ(2, prologue_call_count);
18724 CHECK_EQ(2, epilogue_call_count);
18725 CHECK_EQ(2, prologue_call_count_second);
18726 CHECK_EQ(2, epilogue_call_count_second);
18727}
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018728
18729
18730THREADED_TEST(AddToJSFunctionResultCache) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018731 i::FLAG_stress_compaction = false;
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018732 i::FLAG_allow_natives_syntax = true;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018733 v8::HandleScope scope(CcTest::isolate());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018734
18735 LocalContext context;
18736
18737 const char* code =
18738 "(function() {"
18739 " var key0 = 'a';"
18740 " var key1 = 'b';"
18741 " var r0 = %_GetFromCache(0, key0);"
18742 " var r1 = %_GetFromCache(0, key1);"
18743 " var r0_ = %_GetFromCache(0, key0);"
18744 " if (r0 !== r0_)"
18745 " return 'Different results for ' + key0 + ': ' + r0 + ' vs. ' + r0_;"
18746 " var r1_ = %_GetFromCache(0, key1);"
18747 " if (r1 !== r1_)"
18748 " return 'Different results for ' + key1 + ': ' + r1 + ' vs. ' + r1_;"
18749 " return 'PASSED';"
18750 "})()";
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018751 CcTest::heap()->ClearJSFunctionResultCaches();
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018752 ExpectString(code, "PASSED");
18753}
18754
18755
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018756THREADED_TEST(FillJSFunctionResultCache) {
18757 i::FLAG_allow_natives_syntax = true;
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018758 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018759 v8::HandleScope scope(context->GetIsolate());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018760
18761 const char* code =
18762 "(function() {"
18763 " var k = 'a';"
18764 " var r = %_GetFromCache(0, k);"
18765 " for (var i = 0; i < 16; i++) {"
18766 " %_GetFromCache(0, 'a' + i);"
18767 " };"
18768 " if (r === %_GetFromCache(0, k))"
18769 " return 'FAILED: k0CacheSize is too small';"
18770 " return 'PASSED';"
18771 "})()";
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018772 CcTest::heap()->ClearJSFunctionResultCaches();
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018773 ExpectString(code, "PASSED");
18774}
18775
18776
18777THREADED_TEST(RoundRobinGetFromCache) {
18778 i::FLAG_allow_natives_syntax = true;
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018779 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018780 v8::HandleScope scope(context->GetIsolate());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018781
18782 const char* code =
18783 "(function() {"
18784 " var keys = [];"
18785 " for (var i = 0; i < 16; i++) keys.push(i);"
18786 " var values = [];"
18787 " for (var i = 0; i < 16; i++) values[i] = %_GetFromCache(0, keys[i]);"
18788 " for (var i = 0; i < 16; i++) {"
18789 " var v = %_GetFromCache(0, keys[i]);"
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000018790 " if (v.toString() !== values[i].toString())"
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018791 " return 'Wrong value for ' + "
18792 " keys[i] + ': ' + v + ' vs. ' + values[i];"
18793 " };"
18794 " return 'PASSED';"
18795 "})()";
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018796 CcTest::heap()->ClearJSFunctionResultCaches();
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018797 ExpectString(code, "PASSED");
18798}
18799
18800
18801THREADED_TEST(ReverseGetFromCache) {
18802 i::FLAG_allow_natives_syntax = true;
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018803 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018804 v8::HandleScope scope(context->GetIsolate());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018805
18806 const char* code =
18807 "(function() {"
18808 " var keys = [];"
18809 " for (var i = 0; i < 16; i++) keys.push(i);"
18810 " var values = [];"
18811 " for (var i = 0; i < 16; i++) values[i] = %_GetFromCache(0, keys[i]);"
18812 " for (var i = 15; i >= 16; i--) {"
18813 " var v = %_GetFromCache(0, keys[i]);"
18814 " if (v !== values[i])"
18815 " return 'Wrong value for ' + "
18816 " keys[i] + ': ' + v + ' vs. ' + values[i];"
18817 " };"
18818 " return 'PASSED';"
18819 "})()";
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018820 CcTest::heap()->ClearJSFunctionResultCaches();
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018821 ExpectString(code, "PASSED");
18822}
18823
18824
18825THREADED_TEST(TestEviction) {
18826 i::FLAG_allow_natives_syntax = true;
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018827 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018828 v8::HandleScope scope(context->GetIsolate());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018829
18830 const char* code =
18831 "(function() {"
18832 " for (var i = 0; i < 2*16; i++) {"
18833 " %_GetFromCache(0, 'a' + i);"
18834 " };"
18835 " return 'PASSED';"
18836 "})()";
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018837 CcTest::heap()->ClearJSFunctionResultCaches();
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018838 ExpectString(code, "PASSED");
18839}
lrn@chromium.org32d961d2010-06-30 09:09:34 +000018840
18841
18842THREADED_TEST(TwoByteStringInAsciiCons) {
18843 // See Chromium issue 47824.
lrn@chromium.org32d961d2010-06-30 09:09:34 +000018844 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018845 v8::HandleScope scope(context->GetIsolate());
18846
lrn@chromium.org32d961d2010-06-30 09:09:34 +000018847 const char* init_code =
18848 "var str1 = 'abelspendabel';"
18849 "var str2 = str1 + str1 + str1;"
18850 "str2;";
18851 Local<Value> result = CompileRun(init_code);
18852
ricow@chromium.orgddd545c2011-08-24 12:02:41 +000018853 Local<Value> indexof = CompileRun("str2.indexOf('els')");
18854 Local<Value> lastindexof = CompileRun("str2.lastIndexOf('dab')");
18855
lrn@chromium.org32d961d2010-06-30 09:09:34 +000018856 CHECK(result->IsString());
18857 i::Handle<i::String> string = v8::Utils::OpenHandle(String::Cast(*result));
18858 int length = string->length();
ulan@chromium.org8e8d8822012-11-23 14:36:46 +000018859 CHECK(string->IsOneByteRepresentation());
lrn@chromium.org32d961d2010-06-30 09:09:34 +000018860
18861 FlattenString(string);
18862 i::Handle<i::String> flat_string = FlattenGetString(string);
18863
ulan@chromium.org8e8d8822012-11-23 14:36:46 +000018864 CHECK(string->IsOneByteRepresentation());
18865 CHECK(flat_string->IsOneByteRepresentation());
lrn@chromium.org32d961d2010-06-30 09:09:34 +000018866
18867 // Create external resource.
18868 uint16_t* uc16_buffer = new uint16_t[length + 1];
18869
18870 i::String::WriteToFlat(*flat_string, uc16_buffer, 0, length);
18871 uc16_buffer[length] = 0;
18872
18873 TestResource resource(uc16_buffer);
18874
18875 flat_string->MakeExternal(&resource);
18876
18877 CHECK(flat_string->IsTwoByteRepresentation());
18878
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +000018879 // If the cons string has been short-circuited, skip the following checks.
18880 if (!string.is_identical_to(flat_string)) {
18881 // At this point, we should have a Cons string which is flat and ASCII,
18882 // with a first half that is a two-byte string (although it only contains
18883 // ASCII characters). This is a valid sequence of steps, and it can happen
18884 // in real pages.
18885 CHECK(string->IsOneByteRepresentation());
18886 i::ConsString* cons = i::ConsString::cast(*string);
18887 CHECK_EQ(0, cons->second()->length());
18888 CHECK(cons->first()->IsTwoByteRepresentation());
18889 }
lrn@chromium.org32d961d2010-06-30 09:09:34 +000018890
18891 // Check that some string operations work.
18892
18893 // Atom RegExp.
18894 Local<Value> reresult = CompileRun("str2.match(/abel/g).length;");
18895 CHECK_EQ(6, reresult->Int32Value());
18896
18897 // Nonatom RegExp.
18898 reresult = CompileRun("str2.match(/abe./g).length;");
18899 CHECK_EQ(6, reresult->Int32Value());
18900
18901 reresult = CompileRun("str2.search(/bel/g);");
18902 CHECK_EQ(1, reresult->Int32Value());
18903
18904 reresult = CompileRun("str2.search(/be./g);");
18905 CHECK_EQ(1, reresult->Int32Value());
18906
18907 ExpectTrue("/bel/g.test(str2);");
18908
18909 ExpectTrue("/be./g.test(str2);");
18910
18911 reresult = CompileRun("/bel/g.exec(str2);");
18912 CHECK(!reresult->IsNull());
18913
18914 reresult = CompileRun("/be./g.exec(str2);");
18915 CHECK(!reresult->IsNull());
18916
18917 ExpectString("str2.substring(2, 10);", "elspenda");
18918
18919 ExpectString("str2.substring(2, 20);", "elspendabelabelspe");
18920
18921 ExpectString("str2.charAt(2);", "e");
18922
ricow@chromium.orgddd545c2011-08-24 12:02:41 +000018923 ExpectObject("str2.indexOf('els');", indexof);
18924
18925 ExpectObject("str2.lastIndexOf('dab');", lastindexof);
18926
lrn@chromium.org32d961d2010-06-30 09:09:34 +000018927 reresult = CompileRun("str2.charCodeAt(2);");
18928 CHECK_EQ(static_cast<int32_t>('e'), reresult->Int32Value());
18929}
ager@chromium.orgea4f62e2010-08-16 16:28:43 +000018930
18931
ulan@chromium.orgdfe53072013-06-06 14:14:51 +000018932TEST(ContainsOnlyOneByte) {
18933 v8::V8::Initialize();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018934 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.orgdfe53072013-06-06 14:14:51 +000018935 v8::HandleScope scope(isolate);
18936 // Make a buffer long enough that it won't automatically be converted.
verwaest@chromium.org8a00e822013-06-10 15:11:22 +000018937 const int length = 512;
18938 // Ensure word aligned assignment.
18939 const int aligned_length = length*sizeof(uintptr_t)/sizeof(uint16_t);
18940 i::SmartArrayPointer<uintptr_t>
18941 aligned_contents(new uintptr_t[aligned_length]);
machenbach@chromium.orgafbdadc2013-12-09 16:12:18 +000018942 uint16_t* string_contents =
18943 reinterpret_cast<uint16_t*>(aligned_contents.get());
ulan@chromium.orgdfe53072013-06-06 14:14:51 +000018944 // Set to contain only one byte.
18945 for (int i = 0; i < length-1; i++) {
18946 string_contents[i] = 0x41;
18947 }
18948 string_contents[length-1] = 0;
18949 // Simple case.
18950 Handle<String> string;
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000018951 string = String::NewExternal(isolate, new TestResource(string_contents));
ulan@chromium.orgdfe53072013-06-06 14:14:51 +000018952 CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
18953 // Counter example.
verwaest@chromium.org8a00e822013-06-10 15:11:22 +000018954 string = String::NewFromTwoByte(isolate, string_contents);
ulan@chromium.orgdfe53072013-06-06 14:14:51 +000018955 CHECK(string->IsOneByte() && string->ContainsOnlyOneByte());
18956 // Test left right and balanced cons strings.
18957 Handle<String> base = String::NewFromUtf8(isolate, "a");
18958 Handle<String> left = base;
18959 Handle<String> right = base;
18960 for (int i = 0; i < 1000; i++) {
18961 left = String::Concat(base, left);
18962 right = String::Concat(right, base);
18963 }
18964 Handle<String> balanced = String::Concat(left, base);
18965 balanced = String::Concat(balanced, right);
18966 Handle<String> cons_strings[] = {left, balanced, right};
18967 Handle<String> two_byte =
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000018968 String::NewExternal(isolate, new TestResource(string_contents));
ulan@chromium.orgdfe53072013-06-06 14:14:51 +000018969 for (size_t i = 0; i < ARRAY_SIZE(cons_strings); i++) {
18970 // Base assumptions.
18971 string = cons_strings[i];
18972 CHECK(string->IsOneByte() && string->ContainsOnlyOneByte());
18973 // Test left and right concatentation.
18974 string = String::Concat(two_byte, cons_strings[i]);
18975 CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
18976 string = String::Concat(cons_strings[i], two_byte);
18977 CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
18978 }
verwaest@chromium.org8a00e822013-06-10 15:11:22 +000018979 // Set bits in different positions
18980 // for strings of different lengths and alignments.
18981 for (int alignment = 0; alignment < 7; alignment++) {
18982 for (int size = 2; alignment + size < length; size *= 2) {
18983 int zero_offset = size + alignment;
18984 string_contents[zero_offset] = 0;
18985 for (int i = 0; i < size; i++) {
18986 int shift = 8 + (i % 7);
18987 string_contents[alignment + i] = 1 << shift;
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000018988 string = String::NewExternal(
18989 isolate, new TestResource(string_contents + alignment));
verwaest@chromium.org8a00e822013-06-10 15:11:22 +000018990 CHECK_EQ(size, string->Length());
18991 CHECK(!string->ContainsOnlyOneByte());
18992 string_contents[alignment + i] = 0x41;
18993 }
18994 string_contents[zero_offset] = 0x41;
18995 }
18996 }
ulan@chromium.orgdfe53072013-06-06 14:14:51 +000018997}
18998
18999
ager@chromium.orgea4f62e2010-08-16 16:28:43 +000019000// Failed access check callback that performs a GC on each invocation.
19001void FailedAccessCheckCallbackGC(Local<v8::Object> target,
19002 v8::AccessType type,
19003 Local<v8::Value> data) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019004 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.orgea4f62e2010-08-16 16:28:43 +000019005}
19006
19007
19008TEST(GCInFailedAccessCheckCallback) {
19009 // Install a failed access check callback that performs a GC on each
19010 // invocation. Then force the callback to be called from va
19011
19012 v8::V8::Initialize();
19013 v8::V8::SetFailedAccessCheckCallbackFunction(&FailedAccessCheckCallbackGC);
19014
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000019015 v8::Isolate* isolate = CcTest::isolate();
19016 v8::HandleScope scope(isolate);
ager@chromium.orgea4f62e2010-08-16 16:28:43 +000019017
19018 // Create an ObjectTemplate for global objects and install access
19019 // check callbacks that will block access.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000019020 v8::Handle<v8::ObjectTemplate> global_template =
19021 v8::ObjectTemplate::New(isolate);
ager@chromium.orgea4f62e2010-08-16 16:28:43 +000019022 global_template->SetAccessCheckCallbacks(NamedGetAccessBlocker,
19023 IndexedGetAccessBlocker,
19024 v8::Handle<v8::Value>(),
19025 false);
19026
19027 // Create a context and set an x property on it's global object.
19028 LocalContext context0(NULL, global_template);
19029 context0->Global()->Set(v8_str("x"), v8_num(42));
19030 v8::Handle<v8::Object> global0 = context0->Global();
19031
19032 // Create a context with a different security token so that the
19033 // failed access check callback will be called on each access.
19034 LocalContext context1(NULL, global_template);
19035 context1->Global()->Set(v8_str("other"), global0);
19036
19037 // Get property with failed access check.
19038 ExpectUndefined("other.x");
19039
19040 // Get element with failed access check.
19041 ExpectUndefined("other[0]");
19042
19043 // Set property with failed access check.
19044 v8::Handle<v8::Value> result = CompileRun("other.x = new Object()");
19045 CHECK(result->IsObject());
19046
19047 // Set element with failed access check.
19048 result = CompileRun("other[0] = new Object()");
19049 CHECK(result->IsObject());
19050
19051 // Get property attribute with failed access check.
19052 ExpectFalse("\'x\' in other");
19053
19054 // Get property attribute for element with failed access check.
19055 ExpectFalse("0 in other");
19056
19057 // Delete property.
19058 ExpectFalse("delete other.x");
19059
19060 // Delete element.
19061 CHECK_EQ(false, global0->Delete(0));
19062
19063 // DefineAccessor.
19064 CHECK_EQ(false,
19065 global0->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("x")));
19066
19067 // Define JavaScript accessor.
19068 ExpectUndefined("Object.prototype.__defineGetter__.call("
19069 " other, \'x\', function() { return 42; })");
19070
19071 // LookupAccessor.
19072 ExpectUndefined("Object.prototype.__lookupGetter__.call("
19073 " other, \'x\')");
19074
19075 // HasLocalElement.
19076 ExpectFalse("Object.prototype.hasOwnProperty.call(other, \'0\')");
19077
19078 CHECK_EQ(false, global0->HasRealIndexedProperty(0));
19079 CHECK_EQ(false, global0->HasRealNamedProperty(v8_str("x")));
19080 CHECK_EQ(false, global0->HasRealNamedCallbackProperty(v8_str("x")));
19081
19082 // Reset the failed access check callback so it does not influence
19083 // the other tests.
19084 v8::V8::SetFailedAccessCheckCallbackFunction(NULL);
19085}
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019086
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019087
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019088TEST(IsolateNewDispose) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019089 v8::Isolate* current_isolate = CcTest::isolate();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019090 v8::Isolate* isolate = v8::Isolate::New();
19091 CHECK(isolate != NULL);
19092 CHECK(!reinterpret_cast<i::Isolate*>(isolate)->IsDefaultIsolate());
19093 CHECK(current_isolate != isolate);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019094 CHECK(current_isolate == CcTest::isolate());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019095
19096 v8::V8::SetFatalErrorHandler(StoringErrorCallback);
19097 last_location = last_message = NULL;
19098 isolate->Dispose();
19099 CHECK_EQ(last_location, NULL);
19100 CHECK_EQ(last_message, NULL);
19101}
19102
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019103
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019104UNINITIALIZED_TEST(DisposeIsolateWhenInUse) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019105 v8::Isolate* isolate = v8::Isolate::New();
19106 CHECK(isolate);
19107 isolate->Enter();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019108 v8::HandleScope scope(isolate);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019109 LocalContext context(isolate);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019110 // Run something in this isolate.
19111 ExpectTrue("true");
19112 v8::V8::SetFatalErrorHandler(StoringErrorCallback);
19113 last_location = last_message = NULL;
19114 // Still entered, should fail.
19115 isolate->Dispose();
19116 CHECK_NE(last_location, NULL);
19117 CHECK_NE(last_message, NULL);
19118}
19119
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019120
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019121TEST(RunTwoIsolatesOnSingleThread) {
19122 // Run isolate 1.
19123 v8::Isolate* isolate1 = v8::Isolate::New();
19124 isolate1->Enter();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000019125 v8::Persistent<v8::Context> context1;
19126 {
19127 v8::HandleScope scope(isolate1);
19128 context1.Reset(isolate1, Context::New(isolate1));
19129 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019130
19131 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019132 v8::HandleScope scope(isolate1);
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000019133 v8::Local<v8::Context> context =
19134 v8::Local<v8::Context>::New(isolate1, context1);
19135 v8::Context::Scope context_scope(context);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019136 // Run something in new isolate.
19137 CompileRun("var foo = 'isolate 1';");
19138 ExpectString("function f() { return foo; }; f()", "isolate 1");
19139 }
19140
19141 // Run isolate 2.
19142 v8::Isolate* isolate2 = v8::Isolate::New();
19143 v8::Persistent<v8::Context> context2;
19144
19145 {
19146 v8::Isolate::Scope iscope(isolate2);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019147 v8::HandleScope scope(isolate2);
ulan@chromium.org57ff8812013-05-10 08:16:55 +000019148 context2.Reset(isolate2, Context::New(isolate2));
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000019149 v8::Local<v8::Context> context =
19150 v8::Local<v8::Context>::New(isolate2, context2);
19151 v8::Context::Scope context_scope(context);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019152
19153 // Run something in new isolate.
19154 CompileRun("var foo = 'isolate 2';");
19155 ExpectString("function f() { return foo; }; f()", "isolate 2");
19156 }
19157
19158 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019159 v8::HandleScope scope(isolate1);
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000019160 v8::Local<v8::Context> context =
19161 v8::Local<v8::Context>::New(isolate1, context1);
19162 v8::Context::Scope context_scope(context);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019163 // Now again in isolate 1
19164 ExpectString("function f() { return foo; }; f()", "isolate 1");
19165 }
19166
19167 isolate1->Exit();
19168
19169 // Run some stuff in default isolate.
ulan@chromium.org57ff8812013-05-10 08:16:55 +000019170 v8::Persistent<v8::Context> context_default;
19171 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019172 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000019173 v8::Isolate::Scope iscope(isolate);
19174 v8::HandleScope scope(isolate);
19175 context_default.Reset(isolate, Context::New(isolate));
19176 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019177
19178 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019179 v8::HandleScope scope(CcTest::isolate());
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000019180 v8::Local<v8::Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019181 v8::Local<v8::Context>::New(CcTest::isolate(), context_default);
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000019182 v8::Context::Scope context_scope(context);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019183 // Variables in other isolates should be not available, verify there
19184 // is an exception.
19185 ExpectTrue("function f() {"
19186 " try {"
19187 " foo;"
19188 " return false;"
19189 " } catch(e) {"
19190 " return true;"
19191 " }"
19192 "};"
19193 "var isDefaultIsolate = true;"
19194 "f()");
19195 }
19196
19197 isolate1->Enter();
19198
19199 {
19200 v8::Isolate::Scope iscope(isolate2);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019201 v8::HandleScope scope(isolate2);
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000019202 v8::Local<v8::Context> context =
19203 v8::Local<v8::Context>::New(isolate2, context2);
19204 v8::Context::Scope context_scope(context);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019205 ExpectString("function f() { return foo; }; f()", "isolate 2");
19206 }
19207
19208 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019209 v8::HandleScope scope(v8::Isolate::GetCurrent());
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000019210 v8::Local<v8::Context> context =
19211 v8::Local<v8::Context>::New(v8::Isolate::GetCurrent(), context1);
19212 v8::Context::Scope context_scope(context);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019213 ExpectString("function f() { return foo; }; f()", "isolate 1");
19214 }
19215
19216 {
19217 v8::Isolate::Scope iscope(isolate2);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000019218 context2.Reset();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019219 }
19220
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000019221 context1.Reset();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019222 isolate1->Exit();
19223
19224 v8::V8::SetFatalErrorHandler(StoringErrorCallback);
19225 last_location = last_message = NULL;
19226
19227 isolate1->Dispose();
19228 CHECK_EQ(last_location, NULL);
19229 CHECK_EQ(last_message, NULL);
19230
19231 isolate2->Dispose();
19232 CHECK_EQ(last_location, NULL);
19233 CHECK_EQ(last_message, NULL);
19234
19235 // Check that default isolate still runs.
19236 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019237 v8::HandleScope scope(CcTest::isolate());
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000019238 v8::Local<v8::Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019239 v8::Local<v8::Context>::New(CcTest::isolate(), context_default);
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000019240 v8::Context::Scope context_scope(context);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019241 ExpectTrue("function f() { return isDefaultIsolate; }; f()");
19242 }
19243}
19244
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019245
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019246static int CalcFibonacci(v8::Isolate* isolate, int limit) {
19247 v8::Isolate::Scope isolate_scope(isolate);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019248 v8::HandleScope scope(isolate);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019249 LocalContext context(isolate);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019250 i::ScopedVector<char> code(1024);
19251 i::OS::SNPrintF(code, "function fib(n) {"
19252 " if (n <= 2) return 1;"
19253 " return fib(n-1) + fib(n-2);"
19254 "}"
19255 "fib(%d)", limit);
19256 Local<Value> value = CompileRun(code.start());
19257 CHECK(value->IsNumber());
19258 return static_cast<int>(value->NumberValue());
19259}
19260
19261class IsolateThread : public v8::internal::Thread {
19262 public:
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000019263 IsolateThread(v8::Isolate* isolate, int fib_limit)
19264 : Thread("IsolateThread"),
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019265 isolate_(isolate),
19266 fib_limit_(fib_limit),
19267 result_(0) { }
19268
19269 void Run() {
19270 result_ = CalcFibonacci(isolate_, fib_limit_);
19271 }
19272
19273 int result() { return result_; }
19274
19275 private:
19276 v8::Isolate* isolate_;
19277 int fib_limit_;
19278 int result_;
19279};
19280
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019281
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019282TEST(MultipleIsolatesOnIndividualThreads) {
19283 v8::Isolate* isolate1 = v8::Isolate::New();
19284 v8::Isolate* isolate2 = v8::Isolate::New();
19285
19286 IsolateThread thread1(isolate1, 21);
19287 IsolateThread thread2(isolate2, 12);
19288
19289 // Compute some fibonacci numbers on 3 threads in 3 isolates.
19290 thread1.Start();
19291 thread2.Start();
19292
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019293 int result1 = CalcFibonacci(CcTest::isolate(), 21);
19294 int result2 = CalcFibonacci(CcTest::isolate(), 12);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019295
19296 thread1.Join();
19297 thread2.Join();
19298
19299 // Compare results. The actual fibonacci numbers for 12 and 21 are taken
19300 // (I'm lazy!) from http://en.wikipedia.org/wiki/Fibonacci_number
19301 CHECK_EQ(result1, 10946);
19302 CHECK_EQ(result2, 144);
19303 CHECK_EQ(result1, thread1.result());
19304 CHECK_EQ(result2, thread2.result());
19305
19306 isolate1->Dispose();
19307 isolate2->Dispose();
19308}
19309
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019310
lrn@chromium.org1c092762011-05-09 09:42:16 +000019311TEST(IsolateDifferentContexts) {
19312 v8::Isolate* isolate = v8::Isolate::New();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000019313 Local<v8::Context> context;
lrn@chromium.org1c092762011-05-09 09:42:16 +000019314 {
19315 v8::Isolate::Scope isolate_scope(isolate);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019316 v8::HandleScope handle_scope(isolate);
ulan@chromium.org57ff8812013-05-10 08:16:55 +000019317 context = v8::Context::New(isolate);
lrn@chromium.org1c092762011-05-09 09:42:16 +000019318 v8::Context::Scope context_scope(context);
19319 Local<Value> v = CompileRun("2");
19320 CHECK(v->IsNumber());
19321 CHECK_EQ(2, static_cast<int>(v->NumberValue()));
19322 }
19323 {
19324 v8::Isolate::Scope isolate_scope(isolate);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019325 v8::HandleScope handle_scope(isolate);
ulan@chromium.org57ff8812013-05-10 08:16:55 +000019326 context = v8::Context::New(isolate);
lrn@chromium.org1c092762011-05-09 09:42:16 +000019327 v8::Context::Scope context_scope(context);
19328 Local<Value> v = CompileRun("22");
19329 CHECK(v->IsNumber());
19330 CHECK_EQ(22, static_cast<int>(v->NumberValue()));
19331 }
19332}
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019333
19334class InitDefaultIsolateThread : public v8::internal::Thread {
19335 public:
sgjesse@chromium.orge0599052011-03-25 07:34:35 +000019336 enum TestCase {
19337 IgnoreOOM,
19338 SetResourceConstraints,
19339 SetFatalHandler,
19340 SetCounterFunction,
19341 SetCreateHistogramFunction,
19342 SetAddHistogramSampleFunction
19343 };
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019344
19345 explicit InitDefaultIsolateThread(TestCase testCase)
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000019346 : Thread("InitDefaultIsolateThread"),
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019347 testCase_(testCase),
19348 result_(false) { }
19349
19350 void Run() {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019351 v8::Isolate* isolate = v8::Isolate::New();
19352 isolate->Enter();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019353 switch (testCase_) {
19354 case IgnoreOOM:
19355 v8::V8::IgnoreOutOfMemoryException();
19356 break;
19357
19358 case SetResourceConstraints: {
19359 static const int K = 1024;
19360 v8::ResourceConstraints constraints;
19361 constraints.set_max_young_space_size(256 * K);
19362 constraints.set_max_old_space_size(4 * K * K);
machenbach@chromium.org7ff76072013-11-21 09:47:43 +000019363 v8::SetResourceConstraints(CcTest::isolate(), &constraints);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019364 break;
19365 }
19366
19367 case SetFatalHandler:
19368 v8::V8::SetFatalErrorHandler(NULL);
19369 break;
sgjesse@chromium.orge0599052011-03-25 07:34:35 +000019370
19371 case SetCounterFunction:
19372 v8::V8::SetCounterFunction(NULL);
19373 break;
19374
19375 case SetCreateHistogramFunction:
19376 v8::V8::SetCreateHistogramFunction(NULL);
19377 break;
19378
19379 case SetAddHistogramSampleFunction:
19380 v8::V8::SetAddHistogramSampleFunction(NULL);
19381 break;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019382 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019383 isolate->Exit();
19384 isolate->Dispose();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019385 result_ = true;
19386 }
19387
19388 bool result() { return result_; }
19389
19390 private:
19391 TestCase testCase_;
19392 bool result_;
19393};
19394
19395
19396static void InitializeTestHelper(InitDefaultIsolateThread::TestCase testCase) {
19397 InitDefaultIsolateThread thread(testCase);
19398 thread.Start();
19399 thread.Join();
19400 CHECK_EQ(thread.result(), true);
19401}
19402
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019403
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019404TEST(InitializeDefaultIsolateOnSecondaryThread1) {
19405 InitializeTestHelper(InitDefaultIsolateThread::IgnoreOOM);
19406}
19407
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019408
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019409TEST(InitializeDefaultIsolateOnSecondaryThread2) {
19410 InitializeTestHelper(InitDefaultIsolateThread::SetResourceConstraints);
19411}
19412
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019413
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019414TEST(InitializeDefaultIsolateOnSecondaryThread3) {
19415 InitializeTestHelper(InitDefaultIsolateThread::SetFatalHandler);
19416}
19417
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019418
sgjesse@chromium.orge0599052011-03-25 07:34:35 +000019419TEST(InitializeDefaultIsolateOnSecondaryThread4) {
19420 InitializeTestHelper(InitDefaultIsolateThread::SetCounterFunction);
19421}
19422
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019423
sgjesse@chromium.orge0599052011-03-25 07:34:35 +000019424TEST(InitializeDefaultIsolateOnSecondaryThread5) {
19425 InitializeTestHelper(InitDefaultIsolateThread::SetCreateHistogramFunction);
19426}
19427
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019428
sgjesse@chromium.orge0599052011-03-25 07:34:35 +000019429TEST(InitializeDefaultIsolateOnSecondaryThread6) {
19430 InitializeTestHelper(InitDefaultIsolateThread::SetAddHistogramSampleFunction);
19431}
19432
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019433
19434TEST(StringCheckMultipleContexts) {
19435 const char* code =
19436 "(function() { return \"a\".charAt(0); })()";
19437
19438 {
19439 // Run the code twice in the first context to initialize the call IC.
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019440 LocalContext context1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019441 v8::HandleScope scope(context1->GetIsolate());
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019442 ExpectString(code, "a");
19443 ExpectString(code, "a");
19444 }
19445
19446 {
19447 // Change the String.prototype in the second context and check
19448 // that the right function gets called.
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019449 LocalContext context2;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019450 v8::HandleScope scope(context2->GetIsolate());
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019451 CompileRun("String.prototype.charAt = function() { return \"not a\"; }");
19452 ExpectString(code, "not a");
19453 }
19454}
19455
19456
19457TEST(NumberCheckMultipleContexts) {
19458 const char* code =
19459 "(function() { return (42).toString(); })()";
19460
19461 {
19462 // Run the code twice in the first context to initialize the call IC.
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019463 LocalContext context1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019464 v8::HandleScope scope(context1->GetIsolate());
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019465 ExpectString(code, "42");
19466 ExpectString(code, "42");
19467 }
19468
19469 {
19470 // Change the Number.prototype in the second context and check
19471 // that the right function gets called.
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019472 LocalContext context2;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019473 v8::HandleScope scope(context2->GetIsolate());
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019474 CompileRun("Number.prototype.toString = function() { return \"not 42\"; }");
19475 ExpectString(code, "not 42");
19476 }
19477}
19478
19479
19480TEST(BooleanCheckMultipleContexts) {
19481 const char* code =
19482 "(function() { return true.toString(); })()";
19483
19484 {
19485 // Run the code twice in the first context to initialize the call IC.
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019486 LocalContext context1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019487 v8::HandleScope scope(context1->GetIsolate());
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019488 ExpectString(code, "true");
19489 ExpectString(code, "true");
19490 }
19491
19492 {
19493 // Change the Boolean.prototype in the second context and check
19494 // that the right function gets called.
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019495 LocalContext context2;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019496 v8::HandleScope scope(context2->GetIsolate());
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019497 CompileRun("Boolean.prototype.toString = function() { return \"\"; }");
19498 ExpectString(code, "");
19499 }
19500}
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000019501
19502
19503TEST(DontDeleteCellLoadIC) {
19504 const char* function_code =
19505 "function readCell() { while (true) { return cell; } }";
19506
19507 {
19508 // Run the code twice in the first context to initialize the load
19509 // IC for a don't delete cell.
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000019510 LocalContext context1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019511 v8::HandleScope scope(context1->GetIsolate());
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000019512 CompileRun("var cell = \"first\";");
19513 ExpectBoolean("delete cell", false);
19514 CompileRun(function_code);
19515 ExpectString("readCell()", "first");
19516 ExpectString("readCell()", "first");
19517 }
19518
19519 {
19520 // Use a deletable cell in the second context.
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000019521 LocalContext context2;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019522 v8::HandleScope scope(context2->GetIsolate());
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000019523 CompileRun("cell = \"second\";");
19524 CompileRun(function_code);
19525 ExpectString("readCell()", "second");
19526 ExpectBoolean("delete cell", true);
19527 ExpectString("(function() {"
19528 " try {"
19529 " return readCell();"
19530 " } catch(e) {"
19531 " return e.toString();"
19532 " }"
19533 "})()",
19534 "ReferenceError: cell is not defined");
19535 CompileRun("cell = \"new_second\";");
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019536 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000019537 ExpectString("readCell()", "new_second");
19538 ExpectString("readCell()", "new_second");
19539 }
19540}
19541
19542
19543TEST(DontDeleteCellLoadICForceDelete) {
19544 const char* function_code =
19545 "function readCell() { while (true) { return cell; } }";
19546
19547 // Run the code twice to initialize the load IC for a don't delete
19548 // cell.
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000019549 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019550 v8::HandleScope scope(context->GetIsolate());
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000019551 CompileRun("var cell = \"value\";");
19552 ExpectBoolean("delete cell", false);
19553 CompileRun(function_code);
19554 ExpectString("readCell()", "value");
19555 ExpectString("readCell()", "value");
19556
19557 // Delete the cell using the API and check the inlined code works
19558 // correctly.
19559 CHECK(context->Global()->ForceDelete(v8_str("cell")));
19560 ExpectString("(function() {"
19561 " try {"
19562 " return readCell();"
19563 " } catch(e) {"
19564 " return e.toString();"
19565 " }"
19566 "})()",
19567 "ReferenceError: cell is not defined");
19568}
19569
19570
19571TEST(DontDeleteCellLoadICAPI) {
19572 const char* function_code =
19573 "function readCell() { while (true) { return cell; } }";
19574
19575 // Run the code twice to initialize the load IC for a don't delete
19576 // cell created using the API.
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000019577 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019578 v8::HandleScope scope(context->GetIsolate());
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000019579 context->Global()->Set(v8_str("cell"), v8_str("value"), v8::DontDelete);
19580 ExpectBoolean("delete cell", false);
19581 CompileRun(function_code);
19582 ExpectString("readCell()", "value");
19583 ExpectString("readCell()", "value");
19584
19585 // Delete the cell using the API and check the inlined code works
19586 // correctly.
19587 CHECK(context->Global()->ForceDelete(v8_str("cell")));
19588 ExpectString("(function() {"
19589 " try {"
19590 " return readCell();"
19591 " } catch(e) {"
19592 " return e.toString();"
19593 " }"
19594 "})()",
19595 "ReferenceError: cell is not defined");
19596}
19597
19598
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000019599class Visitor42 : public v8::PersistentHandleVisitor {
19600 public:
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000019601 explicit Visitor42(v8::Persistent<v8::Object>* object)
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000019602 : counter_(0), object_(object) { }
19603
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000019604 virtual void VisitPersistentHandle(Persistent<Value>* value,
19605 uint16_t class_id) {
19606 if (class_id != 42) return;
19607 CHECK_EQ(42, value->WrapperClassId());
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019608 v8::Isolate* isolate = CcTest::isolate();
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000019609 v8::HandleScope handle_scope(isolate);
19610 v8::Handle<v8::Value> handle = v8::Local<v8::Value>::New(isolate, *value);
19611 v8::Handle<v8::Value> object =
19612 v8::Local<v8::Object>::New(isolate, *object_);
19613 CHECK(handle->IsObject());
19614 CHECK_EQ(Handle<Object>::Cast(handle), object);
19615 ++counter_;
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000019616 }
19617
19618 int counter_;
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000019619 v8::Persistent<v8::Object>* object_;
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000019620};
19621
19622
19623TEST(PersistentHandleVisitor) {
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000019624 LocalContext context;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000019625 v8::Isolate* isolate = context->GetIsolate();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019626 v8::HandleScope scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000019627 v8::Persistent<v8::Object> object(isolate, v8::Object::New(isolate));
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000019628 CHECK_EQ(0, object.WrapperClassId());
19629 object.SetWrapperClassId(42);
19630 CHECK_EQ(42, object.WrapperClassId());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000019631
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000019632 Visitor42 visitor(&object);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000019633 v8::V8::VisitHandlesWithClassIds(&visitor);
19634 CHECK_EQ(1, visitor.counter_);
19635
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000019636 object.Reset();
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000019637}
19638
19639
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000019640TEST(WrapperClassId) {
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000019641 LocalContext context;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000019642 v8::Isolate* isolate = context->GetIsolate();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019643 v8::HandleScope scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000019644 v8::Persistent<v8::Object> object(isolate, v8::Object::New(isolate));
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000019645 CHECK_EQ(0, object.WrapperClassId());
19646 object.SetWrapperClassId(65535);
19647 CHECK_EQ(65535, object.WrapperClassId());
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000019648 object.Reset();
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000019649}
19650
19651
yangguo@chromium.org003650e2013-01-24 16:31:08 +000019652TEST(PersistentHandleInNewSpaceVisitor) {
yangguo@chromium.org003650e2013-01-24 16:31:08 +000019653 LocalContext context;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000019654 v8::Isolate* isolate = context->GetIsolate();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019655 v8::HandleScope scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000019656 v8::Persistent<v8::Object> object1(isolate, v8::Object::New(isolate));
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000019657 CHECK_EQ(0, object1.WrapperClassId());
19658 object1.SetWrapperClassId(42);
19659 CHECK_EQ(42, object1.WrapperClassId());
yangguo@chromium.org003650e2013-01-24 16:31:08 +000019660
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019661 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
yangguo@chromium.org003650e2013-01-24 16:31:08 +000019662
ulan@chromium.org0f13e742014-01-03 15:51:11 +000019663 v8::Persistent<v8::Object> object2(isolate, v8::Object::New(isolate));
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000019664 CHECK_EQ(0, object2.WrapperClassId());
19665 object2.SetWrapperClassId(42);
19666 CHECK_EQ(42, object2.WrapperClassId());
yangguo@chromium.org003650e2013-01-24 16:31:08 +000019667
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000019668 Visitor42 visitor(&object2);
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000019669 v8::V8::VisitHandlesForPartialDependence(isolate, &visitor);
yangguo@chromium.org003650e2013-01-24 16:31:08 +000019670 CHECK_EQ(1, visitor.counter_);
19671
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000019672 object1.Reset();
19673 object2.Reset();
yangguo@chromium.org003650e2013-01-24 16:31:08 +000019674}
19675
19676
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019677TEST(RegExp) {
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019678 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019679 v8::HandleScope scope(context->GetIsolate());
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019680
19681 v8::Handle<v8::RegExp> re = v8::RegExp::New(v8_str("foo"), v8::RegExp::kNone);
19682 CHECK(re->IsRegExp());
19683 CHECK(re->GetSource()->Equals(v8_str("foo")));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000019684 CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019685
19686 re = v8::RegExp::New(v8_str("bar"),
19687 static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
19688 v8::RegExp::kGlobal));
19689 CHECK(re->IsRegExp());
19690 CHECK(re->GetSource()->Equals(v8_str("bar")));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000019691 CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kGlobal,
19692 static_cast<int>(re->GetFlags()));
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019693
19694 re = v8::RegExp::New(v8_str("baz"),
19695 static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
19696 v8::RegExp::kMultiline));
19697 CHECK(re->IsRegExp());
19698 CHECK(re->GetSource()->Equals(v8_str("baz")));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000019699 CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
19700 static_cast<int>(re->GetFlags()));
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019701
19702 re = CompileRun("/quux/").As<v8::RegExp>();
19703 CHECK(re->IsRegExp());
19704 CHECK(re->GetSource()->Equals(v8_str("quux")));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000019705 CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019706
19707 re = CompileRun("/quux/gm").As<v8::RegExp>();
19708 CHECK(re->IsRegExp());
19709 CHECK(re->GetSource()->Equals(v8_str("quux")));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000019710 CHECK_EQ(v8::RegExp::kGlobal | v8::RegExp::kMultiline,
19711 static_cast<int>(re->GetFlags()));
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019712
19713 // Override the RegExp constructor and check the API constructor
19714 // still works.
19715 CompileRun("RegExp = function() {}");
19716
19717 re = v8::RegExp::New(v8_str("foobar"), v8::RegExp::kNone);
19718 CHECK(re->IsRegExp());
19719 CHECK(re->GetSource()->Equals(v8_str("foobar")));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000019720 CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019721
19722 re = v8::RegExp::New(v8_str("foobarbaz"),
19723 static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
19724 v8::RegExp::kMultiline));
19725 CHECK(re->IsRegExp());
19726 CHECK(re->GetSource()->Equals(v8_str("foobarbaz")));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000019727 CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
19728 static_cast<int>(re->GetFlags()));
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019729
19730 context->Global()->Set(v8_str("re"), re);
19731 ExpectTrue("re.test('FoobarbaZ')");
19732
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000019733 // RegExps are objects on which you can set properties.
ulan@chromium.org0f13e742014-01-03 15:51:11 +000019734 re->Set(v8_str("property"), v8::Integer::New(context->GetIsolate(), 32));
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000019735 v8::Handle<v8::Value> value(CompileRun("re.property"));
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000019736 CHECK_EQ(32, value->Int32Value());
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000019737
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019738 v8::TryCatch try_catch;
19739 re = v8::RegExp::New(v8_str("foo["), v8::RegExp::kNone);
19740 CHECK(re.IsEmpty());
19741 CHECK(try_catch.HasCaught());
19742 context->Global()->Set(v8_str("ex"), try_catch.Exception());
19743 ExpectTrue("ex instanceof SyntaxError");
19744}
19745
19746
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000019747THREADED_TEST(Equals) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000019748 LocalContext localContext;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019749 v8::HandleScope handleScope(localContext->GetIsolate());
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000019750
19751 v8::Handle<v8::Object> globalProxy = localContext->Global();
19752 v8::Handle<Value> global = globalProxy->GetPrototype();
19753
19754 CHECK(global->StrictEquals(global));
19755 CHECK(!global->StrictEquals(globalProxy));
19756 CHECK(!globalProxy->StrictEquals(global));
19757 CHECK(globalProxy->StrictEquals(globalProxy));
19758
19759 CHECK(global->Equals(global));
19760 CHECK(!global->Equals(globalProxy));
19761 CHECK(!globalProxy->Equals(global));
19762 CHECK(globalProxy->Equals(globalProxy));
19763}
19764
19765
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000019766static void Getter(v8::Local<v8::String> property,
19767 const v8::PropertyCallbackInfo<v8::Value>& info ) {
19768 info.GetReturnValue().Set(v8_str("42!"));
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019769}
19770
19771
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000019772static void Enumerator(const v8::PropertyCallbackInfo<v8::Array>& info) {
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000019773 v8::Handle<v8::Array> result = v8::Array::New(info.GetIsolate());
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019774 result->Set(0, v8_str("universalAnswer"));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000019775 info.GetReturnValue().Set(result);
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019776}
19777
19778
19779TEST(NamedEnumeratorAndForIn) {
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019780 LocalContext context;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000019781 v8::Isolate* isolate = context->GetIsolate();
19782 v8::HandleScope handle_scope(isolate);
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019783 v8::Context::Scope context_scope(context.local());
19784
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000019785 v8::Handle<v8::ObjectTemplate> tmpl = v8::ObjectTemplate::New(isolate);
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019786 tmpl->SetNamedPropertyHandler(Getter, NULL, NULL, NULL, Enumerator);
19787 context->Global()->Set(v8_str("o"), tmpl->NewInstance());
19788 v8::Handle<v8::Array> result = v8::Handle<v8::Array>::Cast(CompileRun(
19789 "var result = []; for (var k in o) result.push(k); result"));
19790 CHECK_EQ(1, result->Length());
19791 CHECK_EQ(v8_str("universalAnswer"), result->Get(0));
19792}
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +000019793
19794
19795TEST(DefinePropertyPostDetach) {
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +000019796 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019797 v8::HandleScope scope(context->GetIsolate());
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +000019798 v8::Handle<v8::Object> proxy = context->Global();
19799 v8::Handle<v8::Function> define_property =
19800 CompileRun("(function() {"
19801 " Object.defineProperty("
19802 " this,"
19803 " 1,"
19804 " { configurable: true, enumerable: true, value: 3 });"
19805 "})").As<Function>();
19806 context->DetachGlobal();
19807 define_property->Call(proxy, 0, NULL);
19808}
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000019809
19810
19811static void InstallContextId(v8::Handle<Context> context, int id) {
19812 Context::Scope scope(context);
19813 CompileRun("Object.prototype").As<Object>()->
ulan@chromium.org0f13e742014-01-03 15:51:11 +000019814 Set(v8_str("context_id"), v8::Integer::New(context->GetIsolate(), id));
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000019815}
19816
19817
19818static void CheckContextId(v8::Handle<Object> object, int expected) {
19819 CHECK_EQ(expected, object->Get(v8_str("context_id"))->Int32Value());
19820}
19821
19822
19823THREADED_TEST(CreationContext) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000019824 v8::Isolate* isolate = CcTest::isolate();
19825 HandleScope handle_scope(isolate);
19826 Handle<Context> context1 = Context::New(isolate);
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000019827 InstallContextId(context1, 1);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000019828 Handle<Context> context2 = Context::New(isolate);
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000019829 InstallContextId(context2, 2);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000019830 Handle<Context> context3 = Context::New(isolate);
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000019831 InstallContextId(context3, 3);
19832
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000019833 Local<v8::FunctionTemplate> tmpl = v8::FunctionTemplate::New(isolate);
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000019834
19835 Local<Object> object1;
19836 Local<Function> func1;
19837 {
19838 Context::Scope scope(context1);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000019839 object1 = Object::New(isolate);
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000019840 func1 = tmpl->GetFunction();
19841 }
19842
19843 Local<Object> object2;
19844 Local<Function> func2;
19845 {
19846 Context::Scope scope(context2);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000019847 object2 = Object::New(isolate);
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000019848 func2 = tmpl->GetFunction();
19849 }
19850
19851 Local<Object> instance1;
19852 Local<Object> instance2;
19853
19854 {
19855 Context::Scope scope(context3);
19856 instance1 = func1->NewInstance();
19857 instance2 = func2->NewInstance();
19858 }
19859
19860 CHECK(object1->CreationContext() == context1);
19861 CheckContextId(object1, 1);
19862 CHECK(func1->CreationContext() == context1);
19863 CheckContextId(func1, 1);
19864 CHECK(instance1->CreationContext() == context1);
19865 CheckContextId(instance1, 1);
19866 CHECK(object2->CreationContext() == context2);
19867 CheckContextId(object2, 2);
19868 CHECK(func2->CreationContext() == context2);
19869 CheckContextId(func2, 2);
19870 CHECK(instance2->CreationContext() == context2);
19871 CheckContextId(instance2, 2);
19872
19873 {
19874 Context::Scope scope(context1);
19875 CHECK(object1->CreationContext() == context1);
19876 CheckContextId(object1, 1);
19877 CHECK(func1->CreationContext() == context1);
19878 CheckContextId(func1, 1);
19879 CHECK(instance1->CreationContext() == context1);
19880 CheckContextId(instance1, 1);
19881 CHECK(object2->CreationContext() == context2);
19882 CheckContextId(object2, 2);
19883 CHECK(func2->CreationContext() == context2);
19884 CheckContextId(func2, 2);
19885 CHECK(instance2->CreationContext() == context2);
19886 CheckContextId(instance2, 2);
19887 }
19888
19889 {
19890 Context::Scope scope(context2);
19891 CHECK(object1->CreationContext() == context1);
19892 CheckContextId(object1, 1);
19893 CHECK(func1->CreationContext() == context1);
19894 CheckContextId(func1, 1);
19895 CHECK(instance1->CreationContext() == context1);
19896 CheckContextId(instance1, 1);
19897 CHECK(object2->CreationContext() == context2);
19898 CheckContextId(object2, 2);
19899 CHECK(func2->CreationContext() == context2);
19900 CheckContextId(func2, 2);
19901 CHECK(instance2->CreationContext() == context2);
19902 CheckContextId(instance2, 2);
19903 }
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000019904}
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019905
19906
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +000019907THREADED_TEST(CreationContextOfJsFunction) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019908 HandleScope handle_scope(CcTest::isolate());
19909 Handle<Context> context = Context::New(CcTest::isolate());
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +000019910 InstallContextId(context, 1);
19911
19912 Local<Object> function;
19913 {
19914 Context::Scope scope(context);
19915 function = CompileRun("function foo() {}; foo").As<Object>();
19916 }
19917
19918 CHECK(function->CreationContext() == context);
19919 CheckContextId(function, 1);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +000019920}
19921
19922
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000019923void HasOwnPropertyIndexedPropertyGetter(
19924 uint32_t index,
19925 const v8::PropertyCallbackInfo<v8::Value>& info) {
19926 if (index == 42) info.GetReturnValue().Set(v8_str("yes"));
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019927}
19928
19929
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000019930void HasOwnPropertyNamedPropertyGetter(
19931 Local<String> property,
19932 const v8::PropertyCallbackInfo<v8::Value>& info) {
19933 if (property->Equals(v8_str("foo"))) info.GetReturnValue().Set(v8_str("yes"));
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019934}
19935
19936
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000019937void HasOwnPropertyIndexedPropertyQuery(
19938 uint32_t index, const v8::PropertyCallbackInfo<v8::Integer>& info) {
19939 if (index == 42) info.GetReturnValue().Set(1);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019940}
19941
19942
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000019943void HasOwnPropertyNamedPropertyQuery(
19944 Local<String> property,
19945 const v8::PropertyCallbackInfo<v8::Integer>& info) {
19946 if (property->Equals(v8_str("foo"))) info.GetReturnValue().Set(1);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019947}
19948
19949
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000019950void HasOwnPropertyNamedPropertyQuery2(
19951 Local<String> property,
19952 const v8::PropertyCallbackInfo<v8::Integer>& info) {
19953 if (property->Equals(v8_str("bar"))) info.GetReturnValue().Set(1);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019954}
19955
19956
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000019957void HasOwnPropertyAccessorGetter(
19958 Local<String> property,
19959 const v8::PropertyCallbackInfo<v8::Value>& info) {
19960 info.GetReturnValue().Set(v8_str("yes"));
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019961}
19962
19963
19964TEST(HasOwnProperty) {
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019965 LocalContext env;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000019966 v8::Isolate* isolate = env->GetIsolate();
19967 v8::HandleScope scope(isolate);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019968 { // Check normal properties and defined getters.
19969 Handle<Value> value = CompileRun(
19970 "function Foo() {"
19971 " this.foo = 11;"
19972 " this.__defineGetter__('baz', function() { return 1; });"
19973 "};"
19974 "function Bar() { "
19975 " this.bar = 13;"
19976 " this.__defineGetter__('bla', function() { return 2; });"
19977 "};"
19978 "Bar.prototype = new Foo();"
19979 "new Bar();");
19980 CHECK(value->IsObject());
19981 Handle<Object> object = value->ToObject();
19982 CHECK(object->Has(v8_str("foo")));
19983 CHECK(!object->HasOwnProperty(v8_str("foo")));
19984 CHECK(object->HasOwnProperty(v8_str("bar")));
19985 CHECK(object->Has(v8_str("baz")));
19986 CHECK(!object->HasOwnProperty(v8_str("baz")));
19987 CHECK(object->HasOwnProperty(v8_str("bla")));
19988 }
19989 { // Check named getter interceptors.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000019990 Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019991 templ->SetNamedPropertyHandler(HasOwnPropertyNamedPropertyGetter);
19992 Handle<Object> instance = templ->NewInstance();
19993 CHECK(!instance->HasOwnProperty(v8_str("42")));
19994 CHECK(instance->HasOwnProperty(v8_str("foo")));
19995 CHECK(!instance->HasOwnProperty(v8_str("bar")));
19996 }
19997 { // Check indexed getter interceptors.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000019998 Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019999 templ->SetIndexedPropertyHandler(HasOwnPropertyIndexedPropertyGetter);
20000 Handle<Object> instance = templ->NewInstance();
20001 CHECK(instance->HasOwnProperty(v8_str("42")));
20002 CHECK(!instance->HasOwnProperty(v8_str("43")));
20003 CHECK(!instance->HasOwnProperty(v8_str("foo")));
20004 }
20005 { // Check named query interceptors.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000020006 Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000020007 templ->SetNamedPropertyHandler(0, 0, HasOwnPropertyNamedPropertyQuery);
20008 Handle<Object> instance = templ->NewInstance();
20009 CHECK(instance->HasOwnProperty(v8_str("foo")));
20010 CHECK(!instance->HasOwnProperty(v8_str("bar")));
20011 }
20012 { // Check indexed query interceptors.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000020013 Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000020014 templ->SetIndexedPropertyHandler(0, 0, HasOwnPropertyIndexedPropertyQuery);
20015 Handle<Object> instance = templ->NewInstance();
20016 CHECK(instance->HasOwnProperty(v8_str("42")));
20017 CHECK(!instance->HasOwnProperty(v8_str("41")));
20018 }
20019 { // Check callbacks.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000020020 Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000020021 templ->SetAccessor(v8_str("foo"), HasOwnPropertyAccessorGetter);
20022 Handle<Object> instance = templ->NewInstance();
20023 CHECK(instance->HasOwnProperty(v8_str("foo")));
20024 CHECK(!instance->HasOwnProperty(v8_str("bar")));
20025 }
20026 { // Check that query wins on disagreement.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000020027 Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000020028 templ->SetNamedPropertyHandler(HasOwnPropertyNamedPropertyGetter,
20029 0,
20030 HasOwnPropertyNamedPropertyQuery2);
20031 Handle<Object> instance = templ->NewInstance();
20032 CHECK(!instance->HasOwnProperty(v8_str("foo")));
20033 CHECK(instance->HasOwnProperty(v8_str("bar")));
20034 }
20035}
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000020036
20037
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +000020038TEST(IndexedInterceptorWithStringProto) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000020039 v8::Isolate* isolate = CcTest::isolate();
20040 v8::HandleScope scope(isolate);
20041 Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +000020042 templ->SetIndexedPropertyHandler(NULL,
20043 NULL,
20044 HasOwnPropertyIndexedPropertyQuery);
20045 LocalContext context;
20046 context->Global()->Set(v8_str("obj"), templ->NewInstance());
20047 CompileRun("var s = new String('foobar'); obj.__proto__ = s;");
20048 // These should be intercepted.
20049 CHECK(CompileRun("42 in obj")->BooleanValue());
20050 CHECK(CompileRun("'42' in obj")->BooleanValue());
20051 // These should fall through to the String prototype.
20052 CHECK(CompileRun("0 in obj")->BooleanValue());
20053 CHECK(CompileRun("'0' in obj")->BooleanValue());
20054 // And these should both fail.
20055 CHECK(!CompileRun("32 in obj")->BooleanValue());
20056 CHECK(!CompileRun("'32' in obj")->BooleanValue());
20057}
20058
20059
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000020060void CheckCodeGenerationAllowed() {
20061 Handle<Value> result = CompileRun("eval('42')");
20062 CHECK_EQ(42, result->Int32Value());
20063 result = CompileRun("(function(e) { return e('42'); })(eval)");
20064 CHECK_EQ(42, result->Int32Value());
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000020065 result = CompileRun("var f = new Function('return 42'); f()");
20066 CHECK_EQ(42, result->Int32Value());
20067}
20068
20069
20070void CheckCodeGenerationDisallowed() {
20071 TryCatch try_catch;
20072
20073 Handle<Value> result = CompileRun("eval('42')");
20074 CHECK(result.IsEmpty());
20075 CHECK(try_catch.HasCaught());
20076 try_catch.Reset();
20077
20078 result = CompileRun("(function(e) { return e('42'); })(eval)");
20079 CHECK(result.IsEmpty());
20080 CHECK(try_catch.HasCaught());
20081 try_catch.Reset();
20082
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000020083 result = CompileRun("var f = new Function('return 42'); f()");
20084 CHECK(result.IsEmpty());
20085 CHECK(try_catch.HasCaught());
20086}
20087
20088
20089bool CodeGenerationAllowed(Local<Context> context) {
20090 ApiTestFuzzer::Fuzz();
20091 return true;
20092}
20093
20094
20095bool CodeGenerationDisallowed(Local<Context> context) {
20096 ApiTestFuzzer::Fuzz();
20097 return false;
20098}
20099
20100
20101THREADED_TEST(AllowCodeGenFromStrings) {
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000020102 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020103 v8::HandleScope scope(context->GetIsolate());
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000020104
ager@chromium.orgea91cc52011-05-23 06:06:11 +000020105 // eval and the Function constructor allowed by default.
jkummerow@chromium.org1145ef82012-02-02 16:21:15 +000020106 CHECK(context->IsCodeGenerationFromStringsAllowed());
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000020107 CheckCodeGenerationAllowed();
20108
ager@chromium.orgea91cc52011-05-23 06:06:11 +000020109 // Disallow eval and the Function constructor.
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000020110 context->AllowCodeGenerationFromStrings(false);
jkummerow@chromium.org1145ef82012-02-02 16:21:15 +000020111 CHECK(!context->IsCodeGenerationFromStringsAllowed());
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000020112 CheckCodeGenerationDisallowed();
20113
20114 // Allow again.
20115 context->AllowCodeGenerationFromStrings(true);
20116 CheckCodeGenerationAllowed();
20117
20118 // Disallow but setting a global callback that will allow the calls.
20119 context->AllowCodeGenerationFromStrings(false);
20120 V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationAllowed);
jkummerow@chromium.org1145ef82012-02-02 16:21:15 +000020121 CHECK(!context->IsCodeGenerationFromStringsAllowed());
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000020122 CheckCodeGenerationAllowed();
20123
20124 // Set a callback that disallows the code generation.
20125 V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationDisallowed);
jkummerow@chromium.org1145ef82012-02-02 16:21:15 +000020126 CHECK(!context->IsCodeGenerationFromStringsAllowed());
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000020127 CheckCodeGenerationDisallowed();
20128}
lrn@chromium.org1c092762011-05-09 09:42:16 +000020129
20130
ulan@chromium.org56c14af2012-09-20 12:51:09 +000020131TEST(SetErrorMessageForCodeGenFromStrings) {
ulan@chromium.org56c14af2012-09-20 12:51:09 +000020132 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020133 v8::HandleScope scope(context->GetIsolate());
ulan@chromium.org56c14af2012-09-20 12:51:09 +000020134 TryCatch try_catch;
20135
20136 Handle<String> message = v8_str("Message") ;
20137 Handle<String> expected_message = v8_str("Uncaught EvalError: Message");
20138 V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationDisallowed);
20139 context->AllowCodeGenerationFromStrings(false);
20140 context->SetErrorMessageForCodeGenerationFromStrings(message);
20141 Handle<Value> result = CompileRun("eval('42')");
20142 CHECK(result.IsEmpty());
20143 CHECK(try_catch.HasCaught());
20144 Handle<String> actual_message = try_catch.Message()->Get();
20145 CHECK(expected_message->Equals(actual_message));
20146}
20147
20148
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000020149static void NonObjectThis(const v8::FunctionCallbackInfo<v8::Value>& args) {
lrn@chromium.org1c092762011-05-09 09:42:16 +000020150}
20151
20152
20153THREADED_TEST(CallAPIFunctionOnNonObject) {
lrn@chromium.org1c092762011-05-09 09:42:16 +000020154 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000020155 v8::Isolate* isolate = context->GetIsolate();
20156 v8::HandleScope scope(isolate);
20157 Handle<FunctionTemplate> templ =
20158 v8::FunctionTemplate::New(isolate, NonObjectThis);
lrn@chromium.org1c092762011-05-09 09:42:16 +000020159 Handle<Function> function = templ->GetFunction();
20160 context->Global()->Set(v8_str("f"), function);
20161 TryCatch try_catch;
20162 CompileRun("f.call(2)");
lrn@chromium.org1c092762011-05-09 09:42:16 +000020163}
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000020164
20165
20166// Regression test for issue 1470.
20167THREADED_TEST(ReadOnlyIndexedProperties) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000020168 v8::Isolate* isolate = CcTest::isolate();
20169 v8::HandleScope scope(isolate);
20170 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000020171
20172 LocalContext context;
20173 Local<v8::Object> obj = templ->NewInstance();
20174 context->Global()->Set(v8_str("obj"), obj);
20175 obj->Set(v8_str("1"), v8_str("DONT_CHANGE"), v8::ReadOnly);
20176 obj->Set(v8_str("1"), v8_str("foobar"));
20177 CHECK_EQ(v8_str("DONT_CHANGE"), obj->Get(v8_str("1")));
20178 obj->Set(v8_num(2), v8_str("DONT_CHANGE"), v8::ReadOnly);
20179 obj->Set(v8_num(2), v8_str("foobar"));
20180 CHECK_EQ(v8_str("DONT_CHANGE"), obj->Get(v8_num(2)));
20181
20182 // Test non-smi case.
20183 obj->Set(v8_str("2000000000"), v8_str("DONT_CHANGE"), v8::ReadOnly);
20184 obj->Set(v8_str("2000000000"), v8_str("foobar"));
20185 CHECK_EQ(v8_str("DONT_CHANGE"), obj->Get(v8_str("2000000000")));
20186}
ricow@chromium.org4f693d62011-07-04 14:01:31 +000020187
20188
20189THREADED_TEST(Regress1516) {
ricow@chromium.org4f693d62011-07-04 14:01:31 +000020190 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020191 v8::HandleScope scope(context->GetIsolate());
20192
20193 { v8::HandleScope temp_scope(context->GetIsolate());
ricow@chromium.org4f693d62011-07-04 14:01:31 +000020194 CompileRun("({'a': 0})");
20195 }
20196
20197 int elements;
20198 { i::MapCache* map_cache =
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020199 i::MapCache::cast(CcTest::i_isolate()->context()->map_cache());
ricow@chromium.org4f693d62011-07-04 14:01:31 +000020200 elements = map_cache->NumberOfElements();
20201 CHECK_LE(1, elements);
20202 }
20203
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020204 CcTest::heap()->CollectAllGarbage(
yangguo@chromium.orgd2899aa2012-06-21 11:16:20 +000020205 i::Heap::kAbortIncrementalMarkingMask);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020206 { i::Object* raw_map_cache = CcTest::i_isolate()->context()->map_cache();
20207 if (raw_map_cache != CcTest::heap()->undefined_value()) {
ricow@chromium.org4f693d62011-07-04 14:01:31 +000020208 i::MapCache* map_cache = i::MapCache::cast(raw_map_cache);
20209 CHECK_GT(elements, map_cache->NumberOfElements());
20210 }
20211 }
20212}
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020213
20214
20215static bool BlockProtoNamedSecurityTestCallback(Local<v8::Object> global,
20216 Local<Value> name,
20217 v8::AccessType type,
20218 Local<Value> data) {
20219 // Only block read access to __proto__.
20220 if (type == v8::ACCESS_GET &&
20221 name->IsString() &&
20222 name->ToString()->Length() == 9 &&
20223 name->ToString()->Utf8Length() == 9) {
20224 char buffer[10];
20225 CHECK_EQ(10, name->ToString()->WriteUtf8(buffer));
20226 return strncmp(buffer, "__proto__", 9) != 0;
20227 }
20228
20229 return true;
20230}
20231
20232
20233THREADED_TEST(Regress93759) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020234 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000020235 HandleScope scope(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020236
20237 // Template for object with security check.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000020238 Local<ObjectTemplate> no_proto_template = v8::ObjectTemplate::New(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020239 // We don't do indexing, so any callback can be used for that.
20240 no_proto_template->SetAccessCheckCallbacks(
20241 BlockProtoNamedSecurityTestCallback,
20242 IndexedSecurityTestCallback);
20243
20244 // Templates for objects with hidden prototypes and possibly security check.
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000020245 Local<FunctionTemplate> hidden_proto_template =
20246 v8::FunctionTemplate::New(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020247 hidden_proto_template->SetHiddenPrototype(true);
20248
20249 Local<FunctionTemplate> protected_hidden_proto_template =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000020250 v8::FunctionTemplate::New(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020251 protected_hidden_proto_template->InstanceTemplate()->SetAccessCheckCallbacks(
20252 BlockProtoNamedSecurityTestCallback,
20253 IndexedSecurityTestCallback);
20254 protected_hidden_proto_template->SetHiddenPrototype(true);
20255
20256 // Context for "foreign" objects used in test.
ulan@chromium.org57ff8812013-05-10 08:16:55 +000020257 Local<Context> context = v8::Context::New(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020258 context->Enter();
20259
20260 // Plain object, no security check.
ulan@chromium.org0f13e742014-01-03 15:51:11 +000020261 Local<Object> simple_object = Object::New(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020262
20263 // Object with explicit security check.
20264 Local<Object> protected_object =
20265 no_proto_template->NewInstance();
20266
20267 // JSGlobalProxy object, always have security check.
20268 Local<Object> proxy_object =
20269 context->Global();
20270
20271 // Global object, the prototype of proxy_object. No security checks.
20272 Local<Object> global_object =
20273 proxy_object->GetPrototype()->ToObject();
20274
20275 // Hidden prototype without security check.
20276 Local<Object> hidden_prototype =
20277 hidden_proto_template->GetFunction()->NewInstance();
20278 Local<Object> object_with_hidden =
ulan@chromium.org0f13e742014-01-03 15:51:11 +000020279 Object::New(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020280 object_with_hidden->SetPrototype(hidden_prototype);
20281
20282 // Hidden prototype with security check on the hidden prototype.
20283 Local<Object> protected_hidden_prototype =
20284 protected_hidden_proto_template->GetFunction()->NewInstance();
20285 Local<Object> object_with_protected_hidden =
ulan@chromium.org0f13e742014-01-03 15:51:11 +000020286 Object::New(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020287 object_with_protected_hidden->SetPrototype(protected_hidden_prototype);
20288
20289 context->Exit();
20290
20291 // Template for object for second context. Values to test are put on it as
20292 // properties.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000020293 Local<ObjectTemplate> global_template = ObjectTemplate::New(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020294 global_template->Set(v8_str("simple"), simple_object);
20295 global_template->Set(v8_str("protected"), protected_object);
20296 global_template->Set(v8_str("global"), global_object);
20297 global_template->Set(v8_str("proxy"), proxy_object);
20298 global_template->Set(v8_str("hidden"), object_with_hidden);
20299 global_template->Set(v8_str("phidden"), object_with_protected_hidden);
20300
20301 LocalContext context2(NULL, global_template);
20302
20303 Local<Value> result1 = CompileRun("Object.getPrototypeOf(simple)");
20304 CHECK(result1->Equals(simple_object->GetPrototype()));
20305
20306 Local<Value> result2 = CompileRun("Object.getPrototypeOf(protected)");
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000020307 CHECK(result2->Equals(Undefined(isolate)));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020308
20309 Local<Value> result3 = CompileRun("Object.getPrototypeOf(global)");
20310 CHECK(result3->Equals(global_object->GetPrototype()));
20311
20312 Local<Value> result4 = CompileRun("Object.getPrototypeOf(proxy)");
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000020313 CHECK(result4->Equals(Undefined(isolate)));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020314
20315 Local<Value> result5 = CompileRun("Object.getPrototypeOf(hidden)");
20316 CHECK(result5->Equals(
20317 object_with_hidden->GetPrototype()->ToObject()->GetPrototype()));
20318
20319 Local<Value> result6 = CompileRun("Object.getPrototypeOf(phidden)");
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000020320 CHECK(result6->Equals(Undefined(isolate)));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020321}
20322
20323
jkummerow@chromium.org212d9642012-05-11 15:02:09 +000020324THREADED_TEST(Regress125988) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020325 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000020326 Handle<FunctionTemplate> intercept = FunctionTemplate::New(CcTest::isolate());
jkummerow@chromium.org212d9642012-05-11 15:02:09 +000020327 AddInterceptor(intercept, EmptyInterceptorGetter, EmptyInterceptorSetter);
20328 LocalContext env;
20329 env->Global()->Set(v8_str("Intercept"), intercept->GetFunction());
20330 CompileRun("var a = new Object();"
20331 "var b = new Intercept();"
20332 "var c = new Object();"
20333 "c.__proto__ = b;"
20334 "b.__proto__ = a;"
20335 "a.x = 23;"
20336 "for (var i = 0; i < 3; i++) c.x;");
20337 ExpectBoolean("c.hasOwnProperty('x')", false);
20338 ExpectInt32("c.x", 23);
20339 CompileRun("a.y = 42;"
20340 "for (var i = 0; i < 3; i++) c.x;");
20341 ExpectBoolean("c.hasOwnProperty('x')", false);
20342 ExpectInt32("c.x", 23);
20343 ExpectBoolean("c.hasOwnProperty('y')", false);
20344 ExpectInt32("c.y", 42);
20345}
20346
20347
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020348static void TestReceiver(Local<Value> expected_result,
20349 Local<Value> expected_receiver,
20350 const char* code) {
20351 Local<Value> result = CompileRun(code);
20352 CHECK(result->IsObject());
20353 CHECK(expected_receiver->Equals(result->ToObject()->Get(1)));
20354 CHECK(expected_result->Equals(result->ToObject()->Get(0)));
20355}
20356
20357
20358THREADED_TEST(ForeignFunctionReceiver) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020359 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000020360 HandleScope scope(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020361
20362 // Create two contexts with different "id" properties ('i' and 'o').
20363 // Call a function both from its own context and from a the foreign
20364 // context, and see what "this" is bound to (returning both "this"
20365 // and "this.id" for comparison).
20366
ulan@chromium.org57ff8812013-05-10 08:16:55 +000020367 Local<Context> foreign_context = v8::Context::New(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020368 foreign_context->Enter();
20369 Local<Value> foreign_function =
20370 CompileRun("function func() { return { 0: this.id, "
20371 " 1: this, "
20372 " toString: function() { "
20373 " return this[0];"
20374 " }"
20375 " };"
20376 "}"
20377 "var id = 'i';"
20378 "func;");
20379 CHECK(foreign_function->IsFunction());
20380 foreign_context->Exit();
20381
20382 LocalContext context;
20383
20384 Local<String> password = v8_str("Password");
20385 // Don't get hit by security checks when accessing foreign_context's
20386 // global receiver (aka. global proxy).
20387 context->SetSecurityToken(password);
20388 foreign_context->SetSecurityToken(password);
20389
20390 Local<String> i = v8_str("i");
20391 Local<String> o = v8_str("o");
20392 Local<String> id = v8_str("id");
20393
20394 CompileRun("function ownfunc() { return { 0: this.id, "
20395 " 1: this, "
20396 " toString: function() { "
20397 " return this[0];"
20398 " }"
20399 " };"
20400 "}"
20401 "var id = 'o';"
20402 "ownfunc");
20403 context->Global()->Set(v8_str("func"), foreign_function);
20404
20405 // Sanity check the contexts.
20406 CHECK(i->Equals(foreign_context->Global()->Get(id)));
20407 CHECK(o->Equals(context->Global()->Get(id)));
20408
20409 // Checking local function's receiver.
20410 // Calling function using its call/apply methods.
20411 TestReceiver(o, context->Global(), "ownfunc.call()");
20412 TestReceiver(o, context->Global(), "ownfunc.apply()");
20413 // Making calls through built-in functions.
20414 TestReceiver(o, context->Global(), "[1].map(ownfunc)[0]");
20415 CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/,ownfunc)[1]")));
20416 CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/g,ownfunc)[1]")));
20417 CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/g,ownfunc)[3]")));
20418 // Calling with environment record as base.
20419 TestReceiver(o, context->Global(), "ownfunc()");
20420 // Calling with no base.
20421 TestReceiver(o, context->Global(), "(1,ownfunc)()");
20422
20423 // Checking foreign function return value.
20424 // Calling function using its call/apply methods.
20425 TestReceiver(i, foreign_context->Global(), "func.call()");
20426 TestReceiver(i, foreign_context->Global(), "func.apply()");
20427 // Calling function using another context's call/apply methods.
20428 TestReceiver(i, foreign_context->Global(),
20429 "Function.prototype.call.call(func)");
20430 TestReceiver(i, foreign_context->Global(),
20431 "Function.prototype.call.apply(func)");
20432 TestReceiver(i, foreign_context->Global(),
20433 "Function.prototype.apply.call(func)");
20434 TestReceiver(i, foreign_context->Global(),
20435 "Function.prototype.apply.apply(func)");
20436 // Making calls through built-in functions.
20437 TestReceiver(i, foreign_context->Global(), "[1].map(func)[0]");
20438 // ToString(func()) is func()[0], i.e., the returned this.id.
20439 CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/,func)[1]")));
20440 CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/g,func)[1]")));
20441 CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/g,func)[3]")));
20442
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020443 // Calling with environment record as base.
rossberg@chromium.org9ed27462014-01-07 14:16:41 +000020444 TestReceiver(i, foreign_context->Global(), "func()");
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020445 // Calling with no base.
rossberg@chromium.org9ed27462014-01-07 14:16:41 +000020446 TestReceiver(i, foreign_context->Global(), "(1,func)()");
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020447}
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020448
20449
20450uint8_t callback_fired = 0;
20451
20452
20453void CallCompletedCallback1() {
20454 i::OS::Print("Firing callback 1.\n");
20455 callback_fired ^= 1; // Toggle first bit.
20456}
20457
20458
20459void CallCompletedCallback2() {
20460 i::OS::Print("Firing callback 2.\n");
20461 callback_fired ^= 2; // Toggle second bit.
20462}
20463
20464
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000020465void RecursiveCall(const v8::FunctionCallbackInfo<v8::Value>& args) {
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020466 int32_t level = args[0]->Int32Value();
20467 if (level < 3) {
20468 level++;
20469 i::OS::Print("Entering recursion level %d.\n", level);
20470 char script[64];
20471 i::Vector<char> script_vector(script, sizeof(script));
20472 i::OS::SNPrintF(script_vector, "recursion(%d)", level);
20473 CompileRun(script_vector.start());
20474 i::OS::Print("Leaving recursion level %d.\n", level);
20475 CHECK_EQ(0, callback_fired);
20476 } else {
20477 i::OS::Print("Recursion ends.\n");
20478 CHECK_EQ(0, callback_fired);
20479 }
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020480}
20481
20482
20483TEST(CallCompletedCallback) {
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020484 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020485 v8::HandleScope scope(env->GetIsolate());
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020486 v8::Handle<v8::FunctionTemplate> recursive_runtime =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000020487 v8::FunctionTemplate::New(env->GetIsolate(), RecursiveCall);
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020488 env->Global()->Set(v8_str("recursion"),
20489 recursive_runtime->GetFunction());
20490 // Adding the same callback a second time has no effect.
20491 v8::V8::AddCallCompletedCallback(CallCompletedCallback1);
20492 v8::V8::AddCallCompletedCallback(CallCompletedCallback1);
20493 v8::V8::AddCallCompletedCallback(CallCompletedCallback2);
20494 i::OS::Print("--- Script (1) ---\n");
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000020495 Local<Script> script = v8::Script::Compile(
20496 v8::String::NewFromUtf8(env->GetIsolate(), "recursion(0)"));
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020497 script->Run();
20498 CHECK_EQ(3, callback_fired);
20499
20500 i::OS::Print("\n--- Script (2) ---\n");
20501 callback_fired = 0;
20502 v8::V8::RemoveCallCompletedCallback(CallCompletedCallback1);
20503 script->Run();
20504 CHECK_EQ(2, callback_fired);
20505
20506 i::OS::Print("\n--- Function ---\n");
20507 callback_fired = 0;
20508 Local<Function> recursive_function =
20509 Local<Function>::Cast(env->Global()->Get(v8_str("recursion")));
20510 v8::Handle<Value> args[] = { v8_num(0) };
20511 recursive_function->Call(env->Global(), 1, args);
20512 CHECK_EQ(2, callback_fired);
20513}
20514
20515
20516void CallCompletedCallbackNoException() {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020517 v8::HandleScope scope(CcTest::isolate());
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020518 CompileRun("1+1;");
20519}
20520
20521
20522void CallCompletedCallbackException() {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020523 v8::HandleScope scope(CcTest::isolate());
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020524 CompileRun("throw 'second exception';");
20525}
20526
20527
20528TEST(CallCompletedCallbackOneException) {
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020529 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020530 v8::HandleScope scope(env->GetIsolate());
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020531 v8::V8::AddCallCompletedCallback(CallCompletedCallbackNoException);
20532 CompileRun("throw 'exception';");
20533}
20534
20535
20536TEST(CallCompletedCallbackTwoExceptions) {
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020537 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020538 v8::HandleScope scope(env->GetIsolate());
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020539 v8::V8::AddCallCompletedCallback(CallCompletedCallbackException);
20540 CompileRun("throw 'first exception';");
20541}
ulan@chromium.org812308e2012-02-29 15:58:45 +000020542
20543
20544static int probes_counter = 0;
20545static int misses_counter = 0;
20546static int updates_counter = 0;
20547
20548
20549static int* LookupCounter(const char* name) {
20550 if (strcmp(name, "c:V8.MegamorphicStubCacheProbes") == 0) {
20551 return &probes_counter;
20552 } else if (strcmp(name, "c:V8.MegamorphicStubCacheMisses") == 0) {
20553 return &misses_counter;
20554 } else if (strcmp(name, "c:V8.MegamorphicStubCacheUpdates") == 0) {
20555 return &updates_counter;
20556 }
20557 return NULL;
20558}
20559
20560
20561static const char* kMegamorphicTestProgram =
20562 "function ClassA() { };"
20563 "function ClassB() { };"
20564 "ClassA.prototype.foo = function() { };"
20565 "ClassB.prototype.foo = function() { };"
20566 "function fooify(obj) { obj.foo(); };"
20567 "var a = new ClassA();"
20568 "var b = new ClassB();"
20569 "for (var i = 0; i < 10000; i++) {"
20570 " fooify(a);"
20571 " fooify(b);"
20572 "}";
20573
20574
20575static void StubCacheHelper(bool primary) {
20576 V8::SetCounterFunction(LookupCounter);
20577 USE(kMegamorphicTestProgram);
20578#ifdef DEBUG
20579 i::FLAG_native_code_counters = true;
20580 if (primary) {
20581 i::FLAG_test_primary_stub_cache = true;
20582 } else {
20583 i::FLAG_test_secondary_stub_cache = true;
20584 }
20585 i::FLAG_crankshaft = false;
ulan@chromium.org812308e2012-02-29 15:58:45 +000020586 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020587 v8::HandleScope scope(env->GetIsolate());
ulan@chromium.org812308e2012-02-29 15:58:45 +000020588 int initial_probes = probes_counter;
20589 int initial_misses = misses_counter;
20590 int initial_updates = updates_counter;
20591 CompileRun(kMegamorphicTestProgram);
20592 int probes = probes_counter - initial_probes;
20593 int misses = misses_counter - initial_misses;
20594 int updates = updates_counter - initial_updates;
20595 CHECK_LT(updates, 10);
20596 CHECK_LT(misses, 10);
20597 CHECK_GE(probes, 10000);
20598#endif
20599}
20600
20601
20602TEST(SecondaryStubCache) {
20603 StubCacheHelper(true);
20604}
20605
20606
20607TEST(PrimaryStubCache) {
20608 StubCacheHelper(false);
20609}
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020610
20611
verwaest@chromium.org057bd502013-11-06 12:03:29 +000020612static int cow_arrays_created_runtime = 0;
20613
20614
20615static int* LookupCounterCOWArrays(const char* name) {
20616 if (strcmp(name, "c:V8.COWArraysCreatedRuntime") == 0) {
20617 return &cow_arrays_created_runtime;
20618 }
20619 return NULL;
20620}
20621
20622
20623TEST(CheckCOWArraysCreatedRuntimeCounter) {
20624 V8::SetCounterFunction(LookupCounterCOWArrays);
20625#ifdef DEBUG
20626 i::FLAG_native_code_counters = true;
20627 LocalContext env;
20628 v8::HandleScope scope(env->GetIsolate());
20629 int initial_cow_arrays = cow_arrays_created_runtime;
20630 CompileRun("var o = [1, 2, 3];");
20631 CHECK_EQ(1, cow_arrays_created_runtime - initial_cow_arrays);
20632 CompileRun("var o = {foo: [4, 5, 6], bar: [3, 0]};");
20633 CHECK_EQ(3, cow_arrays_created_runtime - initial_cow_arrays);
20634 CompileRun("var o = {foo: [1, 2, 3, [4, 5, 6]], bar: 'hi'};");
20635 CHECK_EQ(4, cow_arrays_created_runtime - initial_cow_arrays);
20636#endif
20637}
20638
20639
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020640TEST(StaticGetters) {
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020641 LocalContext context;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020642 i::Factory* factory = CcTest::i_isolate()->factory();
20643 v8::Isolate* isolate = CcTest::isolate();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020644 v8::HandleScope scope(isolate);
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000020645 i::Handle<i::Object> undefined_value = factory->undefined_value();
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020646 CHECK(*v8::Utils::OpenHandle(*v8::Undefined(isolate)) == *undefined_value);
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000020647 i::Handle<i::Object> null_value = factory->null_value();
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020648 CHECK(*v8::Utils::OpenHandle(*v8::Null(isolate)) == *null_value);
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000020649 i::Handle<i::Object> true_value = factory->true_value();
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020650 CHECK(*v8::Utils::OpenHandle(*v8::True(isolate)) == *true_value);
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000020651 i::Handle<i::Object> false_value = factory->false_value();
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020652 CHECK(*v8::Utils::OpenHandle(*v8::False(isolate)) == *false_value);
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020653}
20654
20655
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020656UNINITIALIZED_TEST(IsolateEmbedderData) {
20657 CcTest::DisableAutomaticDispose();
20658 v8::Isolate* isolate = v8::Isolate::New();
20659 isolate->Enter();
hpayer@chromium.orgc5d49712013-09-11 08:25:48 +000020660 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
machenbach@chromium.org7ff76072013-11-21 09:47:43 +000020661 for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
20662 CHECK_EQ(NULL, isolate->GetData(slot));
20663 CHECK_EQ(NULL, i_isolate->GetData(slot));
20664 }
20665 for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
20666 void* data = reinterpret_cast<void*>(0xacce55ed + slot);
20667 isolate->SetData(slot, data);
20668 }
20669 for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
20670 void* data = reinterpret_cast<void*>(0xacce55ed + slot);
20671 CHECK_EQ(data, isolate->GetData(slot));
20672 CHECK_EQ(data, i_isolate->GetData(slot));
20673 }
20674 for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
20675 void* data = reinterpret_cast<void*>(0xdecea5ed + slot);
20676 isolate->SetData(slot, data);
20677 }
20678 for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
20679 void* data = reinterpret_cast<void*>(0xdecea5ed + slot);
20680 CHECK_EQ(data, isolate->GetData(slot));
20681 CHECK_EQ(data, i_isolate->GetData(slot));
20682 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020683 isolate->Exit();
20684 isolate->Dispose();
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020685}
20686
20687
20688TEST(StringEmpty) {
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020689 LocalContext context;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020690 i::Factory* factory = CcTest::i_isolate()->factory();
20691 v8::Isolate* isolate = CcTest::isolate();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020692 v8::HandleScope scope(isolate);
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000020693 i::Handle<i::Object> empty_string = factory->empty_string();
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020694 CHECK(*v8::Utils::OpenHandle(*v8::String::Empty(isolate)) == *empty_string);
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020695}
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020696
20697
20698static int instance_checked_getter_count = 0;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000020699static void InstanceCheckedGetter(
20700 Local<String> name,
20701 const v8::PropertyCallbackInfo<v8::Value>& info) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020702 CHECK_EQ(name, v8_str("foo"));
20703 instance_checked_getter_count++;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000020704 info.GetReturnValue().Set(v8_num(11));
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020705}
20706
20707
20708static int instance_checked_setter_count = 0;
20709static void InstanceCheckedSetter(Local<String> name,
20710 Local<Value> value,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000020711 const v8::PropertyCallbackInfo<void>& info) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020712 CHECK_EQ(name, v8_str("foo"));
20713 CHECK_EQ(value, v8_num(23));
20714 instance_checked_setter_count++;
20715}
20716
20717
20718static void CheckInstanceCheckedResult(int getters,
20719 int setters,
20720 bool expects_callbacks,
20721 TryCatch* try_catch) {
20722 if (expects_callbacks) {
20723 CHECK(!try_catch->HasCaught());
20724 CHECK_EQ(getters, instance_checked_getter_count);
20725 CHECK_EQ(setters, instance_checked_setter_count);
20726 } else {
20727 CHECK(try_catch->HasCaught());
20728 CHECK_EQ(0, instance_checked_getter_count);
20729 CHECK_EQ(0, instance_checked_setter_count);
20730 }
20731 try_catch->Reset();
20732}
20733
20734
20735static void CheckInstanceCheckedAccessors(bool expects_callbacks) {
20736 instance_checked_getter_count = 0;
20737 instance_checked_setter_count = 0;
20738 TryCatch try_catch;
20739
20740 // Test path through generic runtime code.
20741 CompileRun("obj.foo");
20742 CheckInstanceCheckedResult(1, 0, expects_callbacks, &try_catch);
20743 CompileRun("obj.foo = 23");
20744 CheckInstanceCheckedResult(1, 1, expects_callbacks, &try_catch);
20745
20746 // Test path through generated LoadIC and StoredIC.
20747 CompileRun("function test_get(o) { o.foo; }"
20748 "test_get(obj);");
20749 CheckInstanceCheckedResult(2, 1, expects_callbacks, &try_catch);
20750 CompileRun("test_get(obj);");
20751 CheckInstanceCheckedResult(3, 1, expects_callbacks, &try_catch);
20752 CompileRun("test_get(obj);");
20753 CheckInstanceCheckedResult(4, 1, expects_callbacks, &try_catch);
20754 CompileRun("function test_set(o) { o.foo = 23; }"
20755 "test_set(obj);");
20756 CheckInstanceCheckedResult(4, 2, expects_callbacks, &try_catch);
20757 CompileRun("test_set(obj);");
20758 CheckInstanceCheckedResult(4, 3, expects_callbacks, &try_catch);
20759 CompileRun("test_set(obj);");
20760 CheckInstanceCheckedResult(4, 4, expects_callbacks, &try_catch);
20761
20762 // Test path through optimized code.
20763 CompileRun("%OptimizeFunctionOnNextCall(test_get);"
20764 "test_get(obj);");
20765 CheckInstanceCheckedResult(5, 4, expects_callbacks, &try_catch);
20766 CompileRun("%OptimizeFunctionOnNextCall(test_set);"
20767 "test_set(obj);");
20768 CheckInstanceCheckedResult(5, 5, expects_callbacks, &try_catch);
20769
20770 // Cleanup so that closures start out fresh in next check.
20771 CompileRun("%DeoptimizeFunction(test_get);"
20772 "%ClearFunctionTypeFeedback(test_get);"
20773 "%DeoptimizeFunction(test_set);"
20774 "%ClearFunctionTypeFeedback(test_set);");
20775}
20776
20777
20778THREADED_TEST(InstanceCheckOnInstanceAccessor) {
20779 v8::internal::FLAG_allow_natives_syntax = true;
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020780 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020781 v8::HandleScope scope(context->GetIsolate());
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020782
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000020783 Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020784 Local<ObjectTemplate> inst = templ->InstanceTemplate();
20785 inst->SetAccessor(v8_str("foo"),
20786 InstanceCheckedGetter, InstanceCheckedSetter,
20787 Handle<Value>(),
20788 v8::DEFAULT,
20789 v8::None,
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000020790 v8::AccessorSignature::New(context->GetIsolate(), templ));
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020791 context->Global()->Set(v8_str("f"), templ->GetFunction());
20792
20793 printf("Testing positive ...\n");
20794 CompileRun("var obj = new f();");
20795 CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
20796 CheckInstanceCheckedAccessors(true);
20797
20798 printf("Testing negative ...\n");
20799 CompileRun("var obj = {};"
20800 "obj.__proto__ = new f();");
20801 CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
20802 CheckInstanceCheckedAccessors(false);
20803}
20804
20805
20806THREADED_TEST(InstanceCheckOnInstanceAccessorWithInterceptor) {
20807 v8::internal::FLAG_allow_natives_syntax = true;
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020808 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020809 v8::HandleScope scope(context->GetIsolate());
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020810
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000020811 Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020812 Local<ObjectTemplate> inst = templ->InstanceTemplate();
20813 AddInterceptor(templ, EmptyInterceptorGetter, EmptyInterceptorSetter);
20814 inst->SetAccessor(v8_str("foo"),
20815 InstanceCheckedGetter, InstanceCheckedSetter,
20816 Handle<Value>(),
20817 v8::DEFAULT,
20818 v8::None,
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000020819 v8::AccessorSignature::New(context->GetIsolate(), templ));
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020820 context->Global()->Set(v8_str("f"), templ->GetFunction());
20821
20822 printf("Testing positive ...\n");
20823 CompileRun("var obj = new f();");
20824 CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
20825 CheckInstanceCheckedAccessors(true);
20826
20827 printf("Testing negative ...\n");
20828 CompileRun("var obj = {};"
20829 "obj.__proto__ = new f();");
20830 CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
20831 CheckInstanceCheckedAccessors(false);
20832}
20833
20834
20835THREADED_TEST(InstanceCheckOnPrototypeAccessor) {
20836 v8::internal::FLAG_allow_natives_syntax = true;
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020837 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020838 v8::HandleScope scope(context->GetIsolate());
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020839
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000020840 Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020841 Local<ObjectTemplate> proto = templ->PrototypeTemplate();
20842 proto->SetAccessor(v8_str("foo"),
20843 InstanceCheckedGetter, InstanceCheckedSetter,
20844 Handle<Value>(),
20845 v8::DEFAULT,
20846 v8::None,
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000020847 v8::AccessorSignature::New(context->GetIsolate(), templ));
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020848 context->Global()->Set(v8_str("f"), templ->GetFunction());
20849
20850 printf("Testing positive ...\n");
20851 CompileRun("var obj = new f();");
20852 CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
20853 CheckInstanceCheckedAccessors(true);
20854
20855 printf("Testing negative ...\n");
20856 CompileRun("var obj = {};"
20857 "obj.__proto__ = new f();");
20858 CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
20859 CheckInstanceCheckedAccessors(false);
20860
20861 printf("Testing positive with modified prototype chain ...\n");
20862 CompileRun("var obj = new f();"
20863 "var pro = {};"
20864 "pro.__proto__ = obj.__proto__;"
20865 "obj.__proto__ = pro;");
20866 CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
20867 CheckInstanceCheckedAccessors(true);
20868}
20869
20870
20871TEST(TryFinallyMessage) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020872 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020873 v8::HandleScope scope(context->GetIsolate());
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020874 {
20875 // Test that the original error message is not lost if there is a
20876 // recursive call into Javascript is done in the finally block, e.g. to
20877 // initialize an IC. (crbug.com/129171)
20878 TryCatch try_catch;
20879 const char* trigger_ic =
20880 "try { \n"
20881 " throw new Error('test'); \n"
20882 "} finally { \n"
20883 " var x = 0; \n"
20884 " x++; \n" // Trigger an IC initialization here.
20885 "} \n";
20886 CompileRun(trigger_ic);
20887 CHECK(try_catch.HasCaught());
20888 Local<Message> message = try_catch.Message();
20889 CHECK(!message.IsEmpty());
20890 CHECK_EQ(2, message->GetLineNumber());
20891 }
20892
20893 {
20894 // Test that the original exception message is indeed overwritten if
20895 // a new error is thrown in the finally block.
20896 TryCatch try_catch;
20897 const char* throw_again =
20898 "try { \n"
20899 " throw new Error('test'); \n"
20900 "} finally { \n"
20901 " var x = 0; \n"
20902 " x++; \n"
20903 " throw new Error('again'); \n" // This is the new uncaught error.
20904 "} \n";
20905 CompileRun(throw_again);
20906 CHECK(try_catch.HasCaught());
20907 Local<Message> message = try_catch.Message();
20908 CHECK(!message.IsEmpty());
20909 CHECK_EQ(6, message->GetLineNumber());
20910 }
20911}
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000020912
20913
erik.corry@gmail.com88767242012-08-08 14:43:45 +000020914static void Helper137002(bool do_store,
20915 bool polymorphic,
20916 bool remove_accessor,
20917 bool interceptor) {
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000020918 LocalContext context;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000020919 Local<ObjectTemplate> templ = ObjectTemplate::New(context->GetIsolate());
erik.corry@gmail.com88767242012-08-08 14:43:45 +000020920 if (interceptor) {
20921 templ->SetNamedPropertyHandler(FooGetInterceptor, FooSetInterceptor);
20922 } else {
20923 templ->SetAccessor(v8_str("foo"),
20924 GetterWhichReturns42,
20925 SetterWhichSetsYOnThisTo23);
20926 }
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000020927 context->Global()->Set(v8_str("obj"), templ->NewInstance());
20928
20929 // Turn monomorphic on slow object with native accessor, then turn
20930 // polymorphic, finally optimize to create negative lookup and fail.
erik.corry@gmail.com88767242012-08-08 14:43:45 +000020931 CompileRun(do_store ?
20932 "function f(x) { x.foo = void 0; }" :
20933 "function f(x) { return x.foo; }");
20934 CompileRun("obj.y = void 0;");
20935 if (!interceptor) {
20936 CompileRun("%OptimizeObjectForAddingMultipleProperties(obj, 1);");
20937 }
20938 CompileRun("obj.__proto__ = null;"
20939 "f(obj); f(obj); f(obj);");
20940 if (polymorphic) {
20941 CompileRun("f({});");
20942 }
20943 CompileRun("obj.y = void 0;"
20944 "%OptimizeFunctionOnNextCall(f);");
20945 if (remove_accessor) {
20946 CompileRun("delete obj.foo;");
20947 }
20948 CompileRun("var result = f(obj);");
20949 if (do_store) {
20950 CompileRun("result = obj.y;");
20951 }
20952 if (remove_accessor && !interceptor) {
20953 CHECK(context->Global()->Get(v8_str("result"))->IsUndefined());
20954 } else {
20955 CHECK_EQ(do_store ? 23 : 42,
20956 context->Global()->Get(v8_str("result"))->Int32Value());
20957 }
20958}
20959
20960
20961THREADED_TEST(Regress137002a) {
20962 i::FLAG_allow_natives_syntax = true;
20963 i::FLAG_compilation_cache = false;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020964 v8::HandleScope scope(CcTest::isolate());
erik.corry@gmail.com88767242012-08-08 14:43:45 +000020965 for (int i = 0; i < 16; i++) {
20966 Helper137002(i & 8, i & 4, i & 2, i & 1);
20967 }
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000020968}
20969
20970
20971THREADED_TEST(Regress137002b) {
20972 i::FLAG_allow_natives_syntax = true;
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000020973 LocalContext context;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000020974 v8::Isolate* isolate = context->GetIsolate();
20975 v8::HandleScope scope(isolate);
20976 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000020977 templ->SetAccessor(v8_str("foo"),
20978 GetterWhichReturns42,
20979 SetterWhichSetsYOnThisTo23);
20980 context->Global()->Set(v8_str("obj"), templ->NewInstance());
20981
20982 // Turn monomorphic on slow object with native accessor, then just
20983 // delete the property and fail.
erik.corry@gmail.com88767242012-08-08 14:43:45 +000020984 CompileRun("function load(x) { return x.foo; }"
20985 "function store(x) { x.foo = void 0; }"
20986 "function keyed_load(x, key) { return x[key]; }"
20987 // Second version of function has a different source (add void 0)
20988 // so that it does not share code with the first version. This
20989 // ensures that the ICs are monomorphic.
20990 "function load2(x) { void 0; return x.foo; }"
20991 "function store2(x) { void 0; x.foo = void 0; }"
20992 "function keyed_load2(x, key) { void 0; return x[key]; }"
20993
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000020994 "obj.y = void 0;"
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000020995 "obj.__proto__ = null;"
erik.corry@gmail.com88767242012-08-08 14:43:45 +000020996 "var subobj = {};"
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000020997 "subobj.y = void 0;"
erik.corry@gmail.com88767242012-08-08 14:43:45 +000020998 "subobj.__proto__ = obj;"
20999 "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
21000
21001 // Make the ICs monomorphic.
21002 "load(obj); load(obj);"
21003 "load2(subobj); load2(subobj);"
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000021004 "store(obj); store(obj);"
21005 "store2(subobj); store2(subobj);"
erik.corry@gmail.com88767242012-08-08 14:43:45 +000021006 "keyed_load(obj, 'foo'); keyed_load(obj, 'foo');"
21007 "keyed_load2(subobj, 'foo'); keyed_load2(subobj, 'foo');"
21008
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000021009 // Actually test the shiny new ICs and better not crash. This
21010 // serves as a regression test for issue 142088 as well.
21011 "load(obj);"
21012 "load2(subobj);"
21013 "store(obj);"
21014 "store2(subobj);"
21015 "keyed_load(obj, 'foo');"
21016 "keyed_load2(subobj, 'foo');"
21017
erik.corry@gmail.com88767242012-08-08 14:43:45 +000021018 // Delete the accessor. It better not be called any more now.
21019 "delete obj.foo;"
21020 "obj.y = void 0;"
21021 "subobj.y = void 0;"
21022
21023 "var load_result = load(obj);"
21024 "var load_result2 = load2(subobj);"
21025 "var keyed_load_result = keyed_load(obj, 'foo');"
21026 "var keyed_load_result2 = keyed_load2(subobj, 'foo');"
21027 "store(obj);"
21028 "store2(subobj);"
21029 "var y_from_obj = obj.y;"
21030 "var y_from_subobj = subobj.y;");
21031 CHECK(context->Global()->Get(v8_str("load_result"))->IsUndefined());
21032 CHECK(context->Global()->Get(v8_str("load_result2"))->IsUndefined());
21033 CHECK(context->Global()->Get(v8_str("keyed_load_result"))->IsUndefined());
21034 CHECK(context->Global()->Get(v8_str("keyed_load_result2"))->IsUndefined());
21035 CHECK(context->Global()->Get(v8_str("y_from_obj"))->IsUndefined());
21036 CHECK(context->Global()->Get(v8_str("y_from_subobj"))->IsUndefined());
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000021037}
verwaest@chromium.org753aee42012-07-17 16:15:42 +000021038
21039
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000021040THREADED_TEST(Regress142088) {
21041 i::FLAG_allow_natives_syntax = true;
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000021042 LocalContext context;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000021043 v8::Isolate* isolate = context->GetIsolate();
21044 v8::HandleScope scope(isolate);
21045 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000021046 templ->SetAccessor(v8_str("foo"),
21047 GetterWhichReturns42,
21048 SetterWhichSetsYOnThisTo23);
21049 context->Global()->Set(v8_str("obj"), templ->NewInstance());
21050
21051 CompileRun("function load(x) { return x.foo; }"
21052 "var o = Object.create(obj);"
21053 "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
21054 "load(o); load(o); load(o); load(o);");
21055}
21056
21057
verwaest@chromium.org753aee42012-07-17 16:15:42 +000021058THREADED_TEST(Regress137496) {
21059 i::FLAG_expose_gc = true;
verwaest@chromium.org753aee42012-07-17 16:15:42 +000021060 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000021061 v8::HandleScope scope(context->GetIsolate());
verwaest@chromium.org753aee42012-07-17 16:15:42 +000021062
21063 // Compile a try-finally clause where the finally block causes a GC
21064 // while there still is a message pending for external reporting.
21065 TryCatch try_catch;
21066 try_catch.SetVerbose(true);
21067 CompileRun("try { throw new Error(); } finally { gc(); }");
21068 CHECK(try_catch.HasCaught());
21069}
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000021070
21071
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000021072THREADED_TEST(Regress149912) {
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000021073 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000021074 v8::HandleScope scope(context->GetIsolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000021075 Handle<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000021076 AddInterceptor(templ, EmptyInterceptorGetter, EmptyInterceptorSetter);
21077 context->Global()->Set(v8_str("Bug"), templ->GetFunction());
21078 CompileRun("Number.prototype.__proto__ = new Bug; var x = 0; x.foo();");
21079}
21080
21081
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000021082THREADED_TEST(Regress157124) {
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000021083 LocalContext context;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000021084 v8::Isolate* isolate = context->GetIsolate();
21085 v8::HandleScope scope(isolate);
21086 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000021087 Local<Object> obj = templ->NewInstance();
21088 obj->GetIdentityHash();
21089 obj->DeleteHiddenValue(v8_str("Bug"));
21090}
21091
21092
ulan@chromium.org6e196bf2013-03-13 09:38:22 +000021093THREADED_TEST(Regress2535) {
21094 i::FLAG_harmony_collections = true;
ulan@chromium.org6e196bf2013-03-13 09:38:22 +000021095 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000021096 v8::HandleScope scope(context->GetIsolate());
ulan@chromium.org6e196bf2013-03-13 09:38:22 +000021097 Local<Value> set_value = CompileRun("new Set();");
danno@chromium.orgf95d4b92013-06-13 14:40:17 +000021098 Local<Object> set_object(Local<Object>::Cast(set_value));
ulan@chromium.org6e196bf2013-03-13 09:38:22 +000021099 CHECK_EQ(0, set_object->InternalFieldCount());
21100 Local<Value> map_value = CompileRun("new Map();");
danno@chromium.orgf95d4b92013-06-13 14:40:17 +000021101 Local<Object> map_object(Local<Object>::Cast(map_value));
ulan@chromium.org6e196bf2013-03-13 09:38:22 +000021102 CHECK_EQ(0, map_object->InternalFieldCount());
21103}
21104
21105
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000021106THREADED_TEST(Regress2746) {
21107 LocalContext context;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000021108 v8::Isolate* isolate = context->GetIsolate();
21109 v8::HandleScope scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000021110 Local<Object> obj = Object::New(isolate);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000021111 Local<String> key = String::NewFromUtf8(context->GetIsolate(), "key");
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000021112 obj->SetHiddenValue(key, v8::Undefined(isolate));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000021113 Local<Value> value = obj->GetHiddenValue(key);
21114 CHECK(!value.IsEmpty());
21115 CHECK(value->IsUndefined());
21116}
21117
21118
jkummerow@chromium.org10480472013-07-17 08:22:15 +000021119THREADED_TEST(Regress260106) {
21120 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000021121 v8::Isolate* isolate = context->GetIsolate();
21122 v8::HandleScope scope(isolate);
21123 Local<FunctionTemplate> templ = FunctionTemplate::New(isolate,
21124 DummyCallHandler);
jkummerow@chromium.org10480472013-07-17 08:22:15 +000021125 CompileRun("for (var i = 0; i < 128; i++) Object.prototype[i] = 0;");
21126 Local<Function> function = templ->GetFunction();
21127 CHECK(!function.IsEmpty());
21128 CHECK(function->IsFunction());
21129}
21130
21131
danno@chromium.org59400602013-08-13 17:09:37 +000021132THREADED_TEST(JSONParseObject) {
21133 LocalContext context;
21134 HandleScope scope(context->GetIsolate());
21135 Local<Value> obj = v8::JSON::Parse(v8_str("{\"x\":42}"));
21136 Handle<Object> global = context->Global();
21137 global->Set(v8_str("obj"), obj);
21138 ExpectString("JSON.stringify(obj)", "{\"x\":42}");
21139}
21140
21141
21142THREADED_TEST(JSONParseNumber) {
21143 LocalContext context;
21144 HandleScope scope(context->GetIsolate());
21145 Local<Value> obj = v8::JSON::Parse(v8_str("42"));
21146 Handle<Object> global = context->Global();
21147 global->Set(v8_str("obj"), obj);
21148 ExpectString("JSON.stringify(obj)", "42");
21149}
21150
21151
verwaest@chromium.org662436e2013-08-28 08:41:27 +000021152#if V8_OS_POSIX
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000021153class ThreadInterruptTest {
21154 public:
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000021155 ThreadInterruptTest() : sem_(0), sem_value_(0) { }
21156 ~ThreadInterruptTest() {}
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000021157
21158 void RunTest() {
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000021159 InterruptThread i_thread(this);
21160 i_thread.Start();
21161
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000021162 sem_.Wait();
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000021163 CHECK_EQ(kExpectedValue, sem_value_);
21164 }
21165
21166 private:
21167 static const int kExpectedValue = 1;
21168
21169 class InterruptThread : public i::Thread {
21170 public:
21171 explicit InterruptThread(ThreadInterruptTest* test)
21172 : Thread("InterruptThread"), test_(test) {}
21173
21174 virtual void Run() {
21175 struct sigaction action;
21176
21177 // Ensure that we'll enter waiting condition
21178 i::OS::Sleep(100);
21179
21180 // Setup signal handler
21181 memset(&action, 0, sizeof(action));
21182 action.sa_handler = SignalHandler;
21183 sigaction(SIGCHLD, &action, NULL);
21184
21185 // Send signal
21186 kill(getpid(), SIGCHLD);
21187
21188 // Ensure that if wait has returned because of error
21189 i::OS::Sleep(100);
21190
21191 // Set value and signal semaphore
21192 test_->sem_value_ = 1;
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000021193 test_->sem_.Signal();
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000021194 }
21195
21196 static void SignalHandler(int signal) {
21197 }
21198
21199 private:
21200 ThreadInterruptTest* test_;
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000021201 };
21202
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000021203 i::Semaphore sem_;
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000021204 volatile int sem_value_;
21205};
21206
21207
21208THREADED_TEST(SemaphoreInterruption) {
21209 ThreadInterruptTest().RunTest();
21210}
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000021211
danno@chromium.org169691d2013-07-15 08:01:13 +000021212
hpayer@chromium.orgea9b8ba2013-12-20 19:22:39 +000021213#endif // V8_OS_POSIX
21214
21215
danno@chromium.org169691d2013-07-15 08:01:13 +000021216static bool NamedAccessAlwaysBlocked(Local<v8::Object> global,
21217 Local<Value> name,
21218 v8::AccessType type,
21219 Local<Value> data) {
21220 i::PrintF("Named access blocked.\n");
21221 return false;
21222}
21223
21224
21225static bool IndexAccessAlwaysBlocked(Local<v8::Object> global,
21226 uint32_t key,
21227 v8::AccessType type,
21228 Local<Value> data) {
21229 i::PrintF("Indexed access blocked.\n");
21230 return false;
21231}
21232
21233
21234void UnreachableCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
21235 CHECK(false);
21236}
21237
21238
21239TEST(JSONStringifyAccessCheck) {
21240 v8::V8::Initialize();
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000021241 v8::Isolate* isolate = CcTest::isolate();
21242 v8::HandleScope scope(isolate);
danno@chromium.org169691d2013-07-15 08:01:13 +000021243
21244 // Create an ObjectTemplate for global objects and install access
21245 // check callbacks that will block access.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000021246 v8::Handle<v8::ObjectTemplate> global_template =
21247 v8::ObjectTemplate::New(isolate);
danno@chromium.org169691d2013-07-15 08:01:13 +000021248 global_template->SetAccessCheckCallbacks(NamedAccessAlwaysBlocked,
21249 IndexAccessAlwaysBlocked);
21250
21251 // Create a context and set an x property on it's global object.
21252 LocalContext context0(NULL, global_template);
21253 v8::Handle<v8::Object> global0 = context0->Global();
21254 global0->Set(v8_str("x"), v8_num(42));
21255 ExpectString("JSON.stringify(this)", "{\"x\":42}");
21256
21257 for (int i = 0; i < 2; i++) {
21258 if (i == 1) {
21259 // Install a toJSON function on the second run.
21260 v8::Handle<v8::FunctionTemplate> toJSON =
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000021261 v8::FunctionTemplate::New(isolate, UnreachableCallback);
danno@chromium.org169691d2013-07-15 08:01:13 +000021262
21263 global0->Set(v8_str("toJSON"), toJSON->GetFunction());
21264 }
21265 // Create a context with a different security token so that the
21266 // failed access check callback will be called on each access.
21267 LocalContext context1(NULL, global_template);
21268 context1->Global()->Set(v8_str("other"), global0);
21269
21270 ExpectString("JSON.stringify(other)", "{}");
21271 ExpectString("JSON.stringify({ 'a' : other, 'b' : ['c'] })",
21272 "{\"a\":{},\"b\":[\"c\"]}");
21273 ExpectString("JSON.stringify([other, 'b', 'c'])",
21274 "[{},\"b\",\"c\"]");
21275
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000021276 v8::Handle<v8::Array> array = v8::Array::New(isolate, 2);
danno@chromium.org169691d2013-07-15 08:01:13 +000021277 array->Set(0, v8_str("a"));
21278 array->Set(1, v8_str("b"));
21279 context1->Global()->Set(v8_str("array"), array);
21280 ExpectString("JSON.stringify(array)", "[\"a\",\"b\"]");
21281 array->TurnOnAccessCheck();
21282 ExpectString("JSON.stringify(array)", "[]");
21283 ExpectString("JSON.stringify([array])", "[[]]");
21284 ExpectString("JSON.stringify({'a' : array})", "{\"a\":[]}");
21285 }
21286}
21287
21288
21289bool access_check_fail_thrown = false;
21290bool catch_callback_called = false;
21291
21292
21293// Failed access check callback that performs a GC on each invocation.
21294void FailedAccessCheckThrows(Local<v8::Object> target,
21295 v8::AccessType type,
21296 Local<v8::Value> data) {
21297 access_check_fail_thrown = true;
21298 i::PrintF("Access check failed. Error thrown.\n");
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000021299 CcTest::isolate()->ThrowException(
21300 v8::Exception::Error(v8_str("cross context")));
danno@chromium.org169691d2013-07-15 08:01:13 +000021301}
21302
21303
21304void CatcherCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
21305 for (int i = 0; i < args.Length(); i++) {
21306 i::PrintF("%s\n", *String::Utf8Value(args[i]));
21307 }
21308 catch_callback_called = true;
21309}
21310
21311
21312void HasOwnPropertyCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
21313 args[0]->ToObject()->HasOwnProperty(args[1]->ToString());
21314}
21315
21316
21317void CheckCorrectThrow(const char* script) {
21318 // Test that the script, when wrapped into a try-catch, triggers the catch
21319 // clause due to failed access check throwing an exception.
21320 // The subsequent try-catch should run without any exception.
21321 access_check_fail_thrown = false;
21322 catch_callback_called = false;
21323 i::ScopedVector<char> source(1024);
21324 i::OS::SNPrintF(source, "try { %s; } catch (e) { catcher(e); }", script);
21325 CompileRun(source.start());
21326 CHECK(access_check_fail_thrown);
21327 CHECK(catch_callback_called);
21328
21329 access_check_fail_thrown = false;
21330 catch_callback_called = false;
21331 CompileRun("try { [1, 2, 3].sort(); } catch (e) { catcher(e) };");
21332 CHECK(!access_check_fail_thrown);
21333 CHECK(!catch_callback_called);
21334}
21335
21336
21337TEST(AccessCheckThrows) {
21338 i::FLAG_allow_natives_syntax = true;
21339 v8::V8::Initialize();
21340 v8::V8::SetFailedAccessCheckCallbackFunction(&FailedAccessCheckThrows);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000021341 v8::Isolate* isolate = CcTest::isolate();
21342 v8::HandleScope scope(isolate);
danno@chromium.org169691d2013-07-15 08:01:13 +000021343
21344 // Create an ObjectTemplate for global objects and install access
21345 // check callbacks that will block access.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000021346 v8::Handle<v8::ObjectTemplate> global_template =
21347 v8::ObjectTemplate::New(isolate);
danno@chromium.org169691d2013-07-15 08:01:13 +000021348 global_template->SetAccessCheckCallbacks(NamedAccessAlwaysBlocked,
21349 IndexAccessAlwaysBlocked);
21350
21351 // Create a context and set an x property on it's global object.
21352 LocalContext context0(NULL, global_template);
21353 context0->Global()->Set(v8_str("x"), v8_num(42));
21354 v8::Handle<v8::Object> global0 = context0->Global();
21355
21356 // Create a context with a different security token so that the
21357 // failed access check callback will be called on each access.
21358 LocalContext context1(NULL, global_template);
21359 context1->Global()->Set(v8_str("other"), global0);
21360
21361 v8::Handle<v8::FunctionTemplate> catcher_fun =
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000021362 v8::FunctionTemplate::New(isolate, CatcherCallback);
danno@chromium.org169691d2013-07-15 08:01:13 +000021363 context1->Global()->Set(v8_str("catcher"), catcher_fun->GetFunction());
21364
21365 v8::Handle<v8::FunctionTemplate> has_own_property_fun =
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000021366 v8::FunctionTemplate::New(isolate, HasOwnPropertyCallback);
danno@chromium.org169691d2013-07-15 08:01:13 +000021367 context1->Global()->Set(v8_str("has_own_property"),
21368 has_own_property_fun->GetFunction());
21369
21370 { v8::TryCatch try_catch;
21371 access_check_fail_thrown = false;
21372 CompileRun("other.x;");
21373 CHECK(access_check_fail_thrown);
21374 CHECK(try_catch.HasCaught());
21375 }
21376
21377 CheckCorrectThrow("other.x");
21378 CheckCorrectThrow("other[1]");
21379 CheckCorrectThrow("JSON.stringify(other)");
21380 CheckCorrectThrow("has_own_property(other, 'x')");
21381 CheckCorrectThrow("%GetProperty(other, 'x')");
21382 CheckCorrectThrow("%SetProperty(other, 'x', 'foo', 1, 0)");
21383 CheckCorrectThrow("%IgnoreAttributesAndSetProperty(other, 'x', 'foo')");
21384 CheckCorrectThrow("%DeleteProperty(other, 'x', 0)");
21385 CheckCorrectThrow("%DeleteProperty(other, '1', 0)");
21386 CheckCorrectThrow("%HasLocalProperty(other, 'x')");
21387 CheckCorrectThrow("%HasProperty(other, 'x')");
21388 CheckCorrectThrow("%HasElement(other, 1)");
21389 CheckCorrectThrow("%IsPropertyEnumerable(other, 'x')");
21390 CheckCorrectThrow("%GetPropertyNames(other)");
machenbach@chromium.org03453962014-01-10 14:16:31 +000021391 // PROPERTY_ATTRIBUTES_NONE = 0
21392 CheckCorrectThrow("%GetLocalPropertyNames(other, 0)");
danno@chromium.org169691d2013-07-15 08:01:13 +000021393 CheckCorrectThrow("%DefineOrRedefineAccessorProperty("
21394 "other, 'x', null, null, 1)");
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +000021395
21396 // Reset the failed access check callback so it does not influence
21397 // the other tests.
21398 v8::V8::SetFailedAccessCheckCallbackFunction(NULL);
danno@chromium.org169691d2013-07-15 08:01:13 +000021399}
21400
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000021401
21402THREADED_TEST(Regress256330) {
21403 i::FLAG_allow_natives_syntax = true;
21404 LocalContext context;
21405 v8::HandleScope scope(context->GetIsolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000021406 Handle<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000021407 AddInterceptor(templ, EmptyInterceptorGetter, EmptyInterceptorSetter);
21408 context->Global()->Set(v8_str("Bug"), templ->GetFunction());
21409 CompileRun("\"use strict\"; var o = new Bug;"
21410 "function f(o) { o.x = 10; };"
21411 "f(o); f(o); f(o);"
21412 "%OptimizeFunctionOnNextCall(f);"
21413 "f(o);");
21414 ExpectBoolean("%GetOptimizationStatus(f) != 2", true);
21415}
21416
21417
21418THREADED_TEST(CrankshaftInterceptorSetter) {
21419 i::FLAG_allow_natives_syntax = true;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000021420 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000021421 Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000021422 AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
21423 LocalContext env;
21424 env->Global()->Set(v8_str("Obj"), templ->GetFunction());
21425 CompileRun("var obj = new Obj;"
21426 // Initialize fields to avoid transitions later.
21427 "obj.age = 0;"
21428 "obj.accessor_age = 42;"
21429 "function setter(i) { this.accessor_age = i; };"
21430 "function getter() { return this.accessor_age; };"
21431 "function setAge(i) { obj.age = i; };"
21432 "Object.defineProperty(obj, 'age', { get:getter, set:setter });"
21433 "setAge(1);"
21434 "setAge(2);"
21435 "setAge(3);"
21436 "%OptimizeFunctionOnNextCall(setAge);"
21437 "setAge(4);");
21438 // All stores went through the interceptor.
21439 ExpectInt32("obj.interceptor_age", 4);
21440 ExpectInt32("obj.accessor_age", 42);
21441}
21442
21443
21444THREADED_TEST(CrankshaftInterceptorGetter) {
21445 i::FLAG_allow_natives_syntax = true;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000021446 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000021447 Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000021448 AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
21449 LocalContext env;
21450 env->Global()->Set(v8_str("Obj"), templ->GetFunction());
21451 CompileRun("var obj = new Obj;"
21452 // Initialize fields to avoid transitions later.
21453 "obj.age = 1;"
21454 "obj.accessor_age = 42;"
21455 "function getter() { return this.accessor_age; };"
21456 "function getAge() { return obj.interceptor_age; };"
21457 "Object.defineProperty(obj, 'interceptor_age', { get:getter });"
21458 "getAge();"
21459 "getAge();"
21460 "getAge();"
21461 "%OptimizeFunctionOnNextCall(getAge);");
21462 // Access through interceptor.
21463 ExpectInt32("getAge()", 1);
21464}
21465
21466
21467THREADED_TEST(CrankshaftInterceptorFieldRead) {
21468 i::FLAG_allow_natives_syntax = true;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000021469 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000021470 Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000021471 AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
21472 LocalContext env;
21473 env->Global()->Set(v8_str("Obj"), templ->GetFunction());
21474 CompileRun("var obj = new Obj;"
21475 "obj.__proto__.interceptor_age = 42;"
21476 "obj.age = 100;"
21477 "function getAge() { return obj.interceptor_age; };");
21478 ExpectInt32("getAge();", 100);
21479 ExpectInt32("getAge();", 100);
21480 ExpectInt32("getAge();", 100);
21481 CompileRun("%OptimizeFunctionOnNextCall(getAge);");
21482 // Access through interceptor.
21483 ExpectInt32("getAge();", 100);
21484}
21485
21486
21487THREADED_TEST(CrankshaftInterceptorFieldWrite) {
21488 i::FLAG_allow_natives_syntax = true;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000021489 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000021490 Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000021491 AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
21492 LocalContext env;
21493 env->Global()->Set(v8_str("Obj"), templ->GetFunction());
21494 CompileRun("var obj = new Obj;"
21495 "obj.age = 100000;"
21496 "function setAge(i) { obj.age = i };"
21497 "setAge(100);"
21498 "setAge(101);"
21499 "setAge(102);"
21500 "%OptimizeFunctionOnNextCall(setAge);"
21501 "setAge(103);");
21502 ExpectInt32("obj.age", 100000);
21503 ExpectInt32("obj.interceptor_age", 103);
21504}
21505
dslomov@chromium.org639bac02013-09-09 11:58:54 +000021506
hpayer@chromium.orgea9b8ba2013-12-20 19:22:39 +000021507class RequestInterruptTestBase {
21508 public:
21509 RequestInterruptTestBase()
21510 : env_(),
21511 isolate_(env_->GetIsolate()),
21512 sem_(0),
21513 warmup_(20000),
21514 should_continue_(true) {
21515 }
21516
21517 virtual ~RequestInterruptTestBase() { }
21518
21519 virtual void TestBody() = 0;
21520
21521 void RunTest() {
21522 InterruptThread i_thread(this);
21523 i_thread.Start();
21524
21525 v8::HandleScope handle_scope(isolate_);
21526
21527 TestBody();
21528
21529 isolate_->ClearInterrupt();
21530
21531 // Verify we arrived here because interruptor was called
21532 // not due to a bug causing us to exit the loop too early.
21533 CHECK(!should_continue());
21534 }
21535
21536 void WakeUpInterruptor() {
21537 sem_.Signal();
21538 }
21539
21540 bool should_continue() const { return should_continue_; }
21541
21542 bool ShouldContinue() {
21543 if (warmup_ > 0) {
21544 if (--warmup_ == 0) {
21545 WakeUpInterruptor();
21546 }
21547 }
21548
21549 return should_continue_;
21550 }
21551
21552 protected:
21553 static void ShouldContinueCallback(
21554 const v8::FunctionCallbackInfo<Value>& info) {
21555 RequestInterruptTestBase* test =
21556 reinterpret_cast<RequestInterruptTestBase*>(
21557 info.Data().As<v8::External>()->Value());
21558 info.GetReturnValue().Set(test->ShouldContinue());
21559 }
21560
21561 class InterruptThread : public i::Thread {
21562 public:
21563 explicit InterruptThread(RequestInterruptTestBase* test)
21564 : Thread("RequestInterruptTest"), test_(test) {}
21565
21566 virtual void Run() {
21567 test_->sem_.Wait();
21568 test_->isolate_->RequestInterrupt(&OnInterrupt, test_);
21569 }
21570
21571 static void OnInterrupt(v8::Isolate* isolate, void* data) {
21572 reinterpret_cast<RequestInterruptTestBase*>(data)->
21573 should_continue_ = false;
21574 }
21575
21576 private:
21577 RequestInterruptTestBase* test_;
21578 };
21579
21580 LocalContext env_;
21581 v8::Isolate* isolate_;
21582 i::Semaphore sem_;
21583 int warmup_;
21584 bool should_continue_;
21585};
21586
21587
21588class RequestInterruptTestWithFunctionCall : public RequestInterruptTestBase {
21589 public:
21590 virtual void TestBody() {
21591 Local<Function> func = Function::New(
21592 isolate_, ShouldContinueCallback, v8::External::New(isolate_, this));
21593 env_->Global()->Set(v8_str("ShouldContinue"), func);
21594
21595 CompileRun("while (ShouldContinue()) { }");
21596 }
21597};
21598
21599
21600class RequestInterruptTestWithMethodCall : public RequestInterruptTestBase {
21601 public:
21602 virtual void TestBody() {
21603 v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
21604 v8::Local<v8::Template> proto = t->PrototypeTemplate();
21605 proto->Set(v8_str("shouldContinue"), Function::New(
21606 isolate_, ShouldContinueCallback, v8::External::New(isolate_, this)));
21607 env_->Global()->Set(v8_str("Klass"), t->GetFunction());
21608
21609 CompileRun("var obj = new Klass; while (obj.shouldContinue()) { }");
21610 }
21611};
21612
21613
21614class RequestInterruptTestWithAccessor : public RequestInterruptTestBase {
21615 public:
21616 virtual void TestBody() {
21617 v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
21618 v8::Local<v8::Template> proto = t->PrototypeTemplate();
21619 proto->SetAccessorProperty(v8_str("shouldContinue"), FunctionTemplate::New(
21620 isolate_, ShouldContinueCallback, v8::External::New(isolate_, this)));
21621 env_->Global()->Set(v8_str("Klass"), t->GetFunction());
21622
21623 CompileRun("var obj = new Klass; while (obj.shouldContinue) { }");
21624 }
21625};
21626
21627
21628class RequestInterruptTestWithNativeAccessor : public RequestInterruptTestBase {
21629 public:
21630 virtual void TestBody() {
21631 v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
21632 t->InstanceTemplate()->SetNativeDataProperty(
21633 v8_str("shouldContinue"),
21634 &ShouldContinueNativeGetter,
21635 NULL,
21636 v8::External::New(isolate_, this));
21637 env_->Global()->Set(v8_str("Klass"), t->GetFunction());
21638
21639 CompileRun("var obj = new Klass; while (obj.shouldContinue) { }");
21640 }
21641
21642 private:
21643 static void ShouldContinueNativeGetter(
21644 Local<String> property,
21645 const v8::PropertyCallbackInfo<v8::Value>& info) {
21646 RequestInterruptTestBase* test =
21647 reinterpret_cast<RequestInterruptTestBase*>(
21648 info.Data().As<v8::External>()->Value());
21649 info.GetReturnValue().Set(test->ShouldContinue());
21650 }
21651};
21652
21653
21654class RequestInterruptTestWithMethodCallAndInterceptor
21655 : public RequestInterruptTestBase {
21656 public:
21657 virtual void TestBody() {
21658 v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
21659 v8::Local<v8::Template> proto = t->PrototypeTemplate();
21660 proto->Set(v8_str("shouldContinue"), Function::New(
21661 isolate_, ShouldContinueCallback, v8::External::New(isolate_, this)));
21662 v8::Local<v8::ObjectTemplate> instance_template = t->InstanceTemplate();
21663 instance_template->SetNamedPropertyHandler(EmptyInterceptor);
21664
21665 env_->Global()->Set(v8_str("Klass"), t->GetFunction());
21666
21667 CompileRun("var obj = new Klass; while (obj.shouldContinue()) { }");
21668 }
21669
21670 private:
21671 static void EmptyInterceptor(
21672 Local<String> property,
21673 const v8::PropertyCallbackInfo<v8::Value>& info) {
21674 }
21675};
21676
21677
21678class RequestInterruptTestWithMathAbs : public RequestInterruptTestBase {
21679 public:
21680 virtual void TestBody() {
21681 env_->Global()->Set(v8_str("WakeUpInterruptor"), Function::New(
21682 isolate_,
21683 WakeUpInterruptorCallback,
21684 v8::External::New(isolate_, this)));
21685
21686 env_->Global()->Set(v8_str("ShouldContinue"), Function::New(
21687 isolate_,
21688 ShouldContinueCallback,
21689 v8::External::New(isolate_, this)));
21690
21691 i::FLAG_allow_natives_syntax = true;
21692 CompileRun("function loopish(o) {"
21693 " var pre = 10;"
21694 " while (o.abs(1) > 0) {"
21695 " if (o.abs(1) >= 0 && !ShouldContinue()) break;"
21696 " if (pre > 0) {"
21697 " if (--pre === 0) WakeUpInterruptor(o === Math);"
21698 " }"
21699 " }"
21700 "}"
21701 "var i = 50;"
21702 "var obj = {abs: function () { return i-- }, x: null};"
21703 "delete obj.x;"
21704 "loopish(obj);"
21705 "%OptimizeFunctionOnNextCall(loopish);"
21706 "loopish(Math);");
21707
21708 i::FLAG_allow_natives_syntax = false;
21709 }
21710
21711 private:
21712 static void WakeUpInterruptorCallback(
21713 const v8::FunctionCallbackInfo<Value>& info) {
21714 if (!info[0]->BooleanValue()) return;
21715
21716 RequestInterruptTestBase* test =
21717 reinterpret_cast<RequestInterruptTestBase*>(
21718 info.Data().As<v8::External>()->Value());
21719 test->WakeUpInterruptor();
21720 }
21721
21722 static void ShouldContinueCallback(
21723 const v8::FunctionCallbackInfo<Value>& info) {
21724 RequestInterruptTestBase* test =
21725 reinterpret_cast<RequestInterruptTestBase*>(
21726 info.Data().As<v8::External>()->Value());
21727 info.GetReturnValue().Set(test->should_continue());
21728 }
21729};
21730
21731
21732TEST(RequestInterruptTestWithFunctionCall) {
21733 RequestInterruptTestWithFunctionCall().RunTest();
21734}
21735
21736
21737TEST(RequestInterruptTestWithMethodCall) {
21738 RequestInterruptTestWithMethodCall().RunTest();
21739}
21740
21741
21742TEST(RequestInterruptTestWithAccessor) {
21743 RequestInterruptTestWithAccessor().RunTest();
21744}
21745
21746
21747TEST(RequestInterruptTestWithNativeAccessor) {
21748 RequestInterruptTestWithNativeAccessor().RunTest();
21749}
21750
21751
21752TEST(RequestInterruptTestWithMethodCallAndInterceptor) {
21753 RequestInterruptTestWithMethodCallAndInterceptor().RunTest();
21754}
21755
21756
21757TEST(RequestInterruptTestWithMathAbs) {
21758 RequestInterruptTestWithMathAbs().RunTest();
21759}
dslomov@chromium.org639bac02013-09-09 11:58:54 +000021760
21761
21762static Local<Value> function_new_expected_env;
21763static void FunctionNewCallback(const v8::FunctionCallbackInfo<Value>& info) {
21764 CHECK_EQ(function_new_expected_env, info.Data());
21765 info.GetReturnValue().Set(17);
21766}
21767
21768
21769THREADED_TEST(FunctionNew) {
21770 LocalContext env;
21771 v8::Isolate* isolate = env->GetIsolate();
21772 v8::HandleScope scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000021773 Local<Object> data = v8::Object::New(isolate);
dslomov@chromium.org639bac02013-09-09 11:58:54 +000021774 function_new_expected_env = data;
21775 Local<Function> func = Function::New(isolate, FunctionNewCallback, data);
21776 env->Global()->Set(v8_str("func"), func);
21777 Local<Value> result = CompileRun("func();");
ulan@chromium.org0f13e742014-01-03 15:51:11 +000021778 CHECK_EQ(v8::Integer::New(isolate, 17), result);
dslomov@chromium.org639bac02013-09-09 11:58:54 +000021779 // Verify function not cached
21780 int serial_number =
21781 i::Smi::cast(v8::Utils::OpenHandle(*func)
21782 ->shared()->get_api_func_data()->serial_number())->value();
21783 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
21784 i::Object* elm = i_isolate->native_context()->function_cache()
21785 ->GetElementNoExceptionThrown(i_isolate, serial_number);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000021786 CHECK(elm->IsUndefined());
21787 // Verify that each Function::New creates a new function instance
ulan@chromium.org0f13e742014-01-03 15:51:11 +000021788 Local<Object> data2 = v8::Object::New(isolate);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000021789 function_new_expected_env = data2;
21790 Local<Function> func2 = Function::New(isolate, FunctionNewCallback, data2);
21791 CHECK(!func2->IsNull());
21792 CHECK_NE(func, func2);
21793 env->Global()->Set(v8_str("func2"), func2);
21794 Local<Value> result2 = CompileRun("func2();");
ulan@chromium.org0f13e742014-01-03 15:51:11 +000021795 CHECK_EQ(v8::Integer::New(isolate, 17), result2);
dslomov@chromium.org639bac02013-09-09 11:58:54 +000021796}
21797
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000021798
21799TEST(EscapeableHandleScope) {
21800 HandleScope outer_scope(CcTest::isolate());
21801 LocalContext context;
21802 const int runs = 10;
21803 Local<String> values[runs];
21804 for (int i = 0; i < runs; i++) {
21805 v8::EscapableHandleScope inner_scope(CcTest::isolate());
21806 Local<String> value;
21807 if (i != 0) value = v8_str("escape value");
21808 values[i] = inner_scope.Escape(value);
21809 }
21810 for (int i = 0; i < runs; i++) {
21811 Local<String> expected;
21812 if (i != 0) {
21813 CHECK_EQ(v8_str("escape value"), values[i]);
21814 } else {
21815 CHECK(values[i].IsEmpty());
21816 }
21817 }
21818}
machenbach@chromium.org43c51e52014-01-20 07:57:28 +000021819
21820
21821static void SetterWhichExpectsThisAndHolderToDiffer(
21822 Local<String>, Local<Value>, const v8::PropertyCallbackInfo<void>& info) {
21823 CHECK(info.Holder() != info.This());
21824}
21825
21826
21827TEST(Regress239669) {
21828 LocalContext context;
21829 v8::Isolate* isolate = context->GetIsolate();
21830 v8::HandleScope scope(isolate);
21831 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
21832 templ->SetAccessor(v8_str("x"), 0, SetterWhichExpectsThisAndHolderToDiffer);
21833 context->Global()->Set(v8_str("P"), templ->NewInstance());
21834 CompileRun(
21835 "function C1() {"
21836 " this.x = 23;"
21837 "};"
21838 "C1.prototype = P;"
21839 "for (var i = 0; i < 4; i++ ) {"
21840 " new C1();"
21841 "}");
21842}