blob: c70f9885ffcfa9b8d709908a2af80c5dc3f3543b [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());
91 v8::Local<v8::String> profile_name = v8::String::New("my_profile1");
92 v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler();
93
94 cpu_profiler->StartCpuProfiling(profile_name);
95 (*test)();
96 cpu_profiler->DeleteAllCpuProfiles();
97}
98
99
kasperl@chromium.orgeac059f2010-01-25 11:02:06 +0000100static void ExpectString(const char* code, const char* expected) {
101 Local<Value> result = CompileRun(code);
102 CHECK(result->IsString());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +0000103 String::Utf8Value utf8(result);
104 CHECK_EQ(expected, *utf8);
kasperl@chromium.orgeac059f2010-01-25 11:02:06 +0000105}
106
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000107
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000108static void ExpectInt32(const char* code, int expected) {
109 Local<Value> result = CompileRun(code);
110 CHECK(result->IsInt32());
111 CHECK_EQ(expected, result->Int32Value());
112}
kasperl@chromium.orgeac059f2010-01-25 11:02:06 +0000113
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000114
kasperl@chromium.orgeac059f2010-01-25 11:02:06 +0000115static void ExpectBoolean(const char* code, bool expected) {
116 Local<Value> result = CompileRun(code);
117 CHECK(result->IsBoolean());
118 CHECK_EQ(expected, result->BooleanValue());
119}
120
121
kmillikin@chromium.org9155e252010-05-26 13:27:57 +0000122static void ExpectTrue(const char* code) {
123 ExpectBoolean(code, true);
124}
125
126
ager@chromium.orgea4f62e2010-08-16 16:28:43 +0000127static void ExpectFalse(const char* code) {
128 ExpectBoolean(code, false);
129}
130
131
kasperl@chromium.orgeac059f2010-01-25 11:02:06 +0000132static void ExpectObject(const char* code, Local<Value> expected) {
133 Local<Value> result = CompileRun(code);
134 CHECK(result->Equals(expected));
135}
136
137
ager@chromium.orgea4f62e2010-08-16 16:28:43 +0000138static void ExpectUndefined(const char* code) {
139 Local<Value> result = CompileRun(code);
140 CHECK(result->IsUndefined());
141}
142
143
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000144static int signature_callback_count;
jkummerow@chromium.org2c9426b2013-09-05 16:31:13 +0000145static Local<Value> signature_expected_receiver;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000146static void IncrementingSignatureCallback(
147 const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000148 ApiTestFuzzer::Fuzz();
149 signature_callback_count++;
jkummerow@chromium.org2c9426b2013-09-05 16:31:13 +0000150 CHECK_EQ(signature_expected_receiver, args.Holder());
151 CHECK_EQ(signature_expected_receiver, args.This());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000152 v8::Handle<v8::Array> result = v8::Array::New(args.Length());
153 for (int i = 0; i < args.Length(); i++)
154 result->Set(v8::Integer::New(i), args[i]);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000155 args.GetReturnValue().Set(result);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000156}
157
158
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000159static void SignatureCallback(
160 const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000161 ApiTestFuzzer::Fuzz();
162 v8::Handle<v8::Array> result = v8::Array::New(args.Length());
163 for (int i = 0; i < args.Length(); i++) {
164 result->Set(v8::Integer::New(i), args[i]);
165 }
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000166 args.GetReturnValue().Set(result);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000167}
168
169
dslomov@chromium.org639bac02013-09-09 11:58:54 +0000170// Tests that call v8::V8::Dispose() cannot be threaded.
171TEST(InitializeAndDisposeOnce) {
172 CHECK(v8::V8::Initialize());
173 CHECK(v8::V8::Dispose());
174}
175
176
177// Tests that call v8::V8::Dispose() cannot be threaded.
178TEST(InitializeAndDisposeMultiple) {
179 for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
180 for (int i = 0; i < 3; ++i) CHECK(v8::V8::Initialize());
181 for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
182 // TODO(mstarzinger): This should fail gracefully instead of asserting.
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}
186
187
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000188THREADED_TEST(Handles) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000189 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000190 Local<Context> local_env;
191 {
192 LocalContext env;
193 local_env = env.local();
194 }
195
196 // Local context should still be live.
197 CHECK(!local_env.IsEmpty());
198 local_env->Enter();
199
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +0000200 v8::Handle<v8::Primitive> undef = v8::Undefined(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000201 CHECK(!undef.IsEmpty());
202 CHECK(undef->IsUndefined());
203
204 const char* c_source = "1 + 2 + 3";
205 Local<String> source = String::New(c_source);
206 Local<Script> script = Script::Compile(source);
207 CHECK_EQ(6, script->Run()->Int32Value());
208
209 local_env->Exit();
210}
211
212
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000213THREADED_TEST(IsolateOfContext) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000214 v8::HandleScope scope(CcTest::isolate());
215 v8::Handle<Context> env = Context::New(CcTest::isolate());
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000216
217 CHECK(!env->InContext());
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000218 CHECK(env->GetIsolate() == CcTest::isolate());
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000219 env->Enter();
220 CHECK(env->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->Exit();
223 CHECK(!env->InContext());
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000224 CHECK(env->GetIsolate() == CcTest::isolate());
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000225}
226
227
dslomov@chromium.org639bac02013-09-09 11:58:54 +0000228static void TestSignature(const char* loop_js, Local<Value> receiver) {
229 i::ScopedVector<char> source(200);
230 i::OS::SNPrintF(source,
231 "for (var i = 0; i < 10; i++) {"
232 " %s"
233 "}",
234 loop_js);
235 signature_callback_count = 0;
236 signature_expected_receiver = receiver;
237 bool expected_to_throw = receiver.IsEmpty();
238 v8::TryCatch try_catch;
239 CompileRun(source.start());
240 CHECK_EQ(expected_to_throw, try_catch.HasCaught());
241 if (!expected_to_throw) {
242 CHECK_EQ(10, signature_callback_count);
243 } else {
244 CHECK_EQ(v8_str("TypeError: Illegal invocation"),
245 try_catch.Exception()->ToString());
246 }
247}
248
249
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000250THREADED_TEST(ReceiverSignature) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000251 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000252 v8::HandleScope scope(env->GetIsolate());
dslomov@chromium.org639bac02013-09-09 11:58:54 +0000253 // Setup templates.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000254 v8::Handle<v8::FunctionTemplate> fun = v8::FunctionTemplate::New();
255 v8::Handle<v8::Signature> sig = v8::Signature::New(fun);
dslomov@chromium.org639bac02013-09-09 11:58:54 +0000256 v8::Handle<v8::FunctionTemplate> callback_sig =
257 v8::FunctionTemplate::New(
258 IncrementingSignatureCallback, Local<Value>(), sig);
259 v8::Handle<v8::FunctionTemplate> callback =
260 v8::FunctionTemplate::New(IncrementingSignatureCallback);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000261 v8::Handle<v8::FunctionTemplate> sub_fun = v8::FunctionTemplate::New();
262 sub_fun->Inherit(fun);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000263 v8::Handle<v8::FunctionTemplate> unrel_fun = v8::FunctionTemplate::New();
dslomov@chromium.org639bac02013-09-09 11:58:54 +0000264 // Install properties.
265 v8::Handle<v8::ObjectTemplate> fun_proto = fun->PrototypeTemplate();
266 fun_proto->Set(v8_str("prop_sig"), callback_sig);
267 fun_proto->Set(v8_str("prop"), callback);
268 fun_proto->SetAccessorProperty(
269 v8_str("accessor_sig"), callback_sig, callback_sig);
270 fun_proto->SetAccessorProperty(v8_str("accessor"), callback, callback);
271 // Instantiate templates.
272 Local<Value> fun_instance = fun->InstanceTemplate()->NewInstance();
273 Local<Value> sub_fun_instance = sub_fun->InstanceTemplate()->NewInstance();
274 // Setup global variables.
275 env->Global()->Set(v8_str("Fun"), fun->GetFunction());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000276 env->Global()->Set(v8_str("UnrelFun"), unrel_fun->GetFunction());
dslomov@chromium.org639bac02013-09-09 11:58:54 +0000277 env->Global()->Set(v8_str("fun_instance"), fun_instance);
278 env->Global()->Set(v8_str("sub_fun_instance"), sub_fun_instance);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000279 CompileRun(
dslomov@chromium.org639bac02013-09-09 11:58:54 +0000280 "var accessor_sig_key = 'accessor_sig';"
281 "var accessor_key = 'accessor';"
282 "var prop_sig_key = 'prop_sig';"
283 "var prop_key = 'prop';"
284 ""
285 "function copy_props(obj) {"
286 " var keys = [accessor_sig_key, accessor_key, prop_sig_key, prop_key];"
287 " var source = Fun.prototype;"
288 " for (var i in keys) {"
289 " var key = keys[i];"
290 " var desc = Object.getOwnPropertyDescriptor(source, key);"
291 " Object.defineProperty(obj, key, desc);"
292 " }"
293 "}"
294 ""
295 "var obj = {};"
296 "copy_props(obj);"
297 "var unrel = new UnrelFun();"
298 "copy_props(unrel);");
299 // Test with and without ICs
300 const char* test_objects[] = {
301 "fun_instance", "sub_fun_instance", "obj", "unrel" };
302 unsigned bad_signature_start_offset = 2;
303 for (unsigned i = 0; i < ARRAY_SIZE(test_objects); i++) {
304 i::ScopedVector<char> source(200);
305 i::OS::SNPrintF(
306 source, "var test_object = %s; test_object", test_objects[i]);
307 Local<Value> test_object = CompileRun(source.start());
308 TestSignature("test_object.prop();", test_object);
309 TestSignature("test_object.accessor;", test_object);
310 TestSignature("test_object[accessor_key];", test_object);
311 TestSignature("test_object.accessor = 1;", test_object);
312 TestSignature("test_object[accessor_key] = 1;", test_object);
313 if (i >= bad_signature_start_offset) test_object = Local<Value>();
314 TestSignature("test_object.prop_sig();", test_object);
315 TestSignature("test_object.accessor_sig;", test_object);
316 TestSignature("test_object[accessor_sig_key];", test_object);
317 TestSignature("test_object.accessor_sig = 1;", test_object);
318 TestSignature("test_object[accessor_sig_key] = 1;", test_object);
319 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000320}
321
322
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000323THREADED_TEST(ArgumentSignature) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000324 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000325 v8::HandleScope scope(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000326 v8::Handle<v8::FunctionTemplate> cons = v8::FunctionTemplate::New();
327 cons->SetClassName(v8_str("Cons"));
328 v8::Handle<v8::Signature> sig =
329 v8::Signature::New(v8::Handle<v8::FunctionTemplate>(), 1, &cons);
330 v8::Handle<v8::FunctionTemplate> fun =
331 v8::FunctionTemplate::New(SignatureCallback, v8::Handle<Value>(), sig);
332 env->Global()->Set(v8_str("Cons"), cons->GetFunction());
333 env->Global()->Set(v8_str("Fun1"), fun->GetFunction());
334
335 v8::Handle<Value> value1 = CompileRun("Fun1(4) == '';");
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000336 CHECK(value1->IsTrue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000337
338 v8::Handle<Value> value2 = CompileRun("Fun1(new Cons()) == '[object Cons]';");
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000339 CHECK(value2->IsTrue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000340
341 v8::Handle<Value> value3 = CompileRun("Fun1() == '';");
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000342 CHECK(value3->IsTrue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000343
344 v8::Handle<v8::FunctionTemplate> cons1 = v8::FunctionTemplate::New();
345 cons1->SetClassName(v8_str("Cons1"));
346 v8::Handle<v8::FunctionTemplate> cons2 = v8::FunctionTemplate::New();
347 cons2->SetClassName(v8_str("Cons2"));
348 v8::Handle<v8::FunctionTemplate> cons3 = v8::FunctionTemplate::New();
349 cons3->SetClassName(v8_str("Cons3"));
350
351 v8::Handle<v8::FunctionTemplate> args[3] = { cons1, cons2, cons3 };
352 v8::Handle<v8::Signature> wsig =
353 v8::Signature::New(v8::Handle<v8::FunctionTemplate>(), 3, args);
354 v8::Handle<v8::FunctionTemplate> fun2 =
355 v8::FunctionTemplate::New(SignatureCallback, v8::Handle<Value>(), wsig);
356
357 env->Global()->Set(v8_str("Cons1"), cons1->GetFunction());
358 env->Global()->Set(v8_str("Cons2"), cons2->GetFunction());
359 env->Global()->Set(v8_str("Cons3"), cons3->GetFunction());
360 env->Global()->Set(v8_str("Fun2"), fun2->GetFunction());
361 v8::Handle<Value> value4 = CompileRun(
362 "Fun2(new Cons1(), new Cons2(), new Cons3()) =="
363 "'[object Cons1],[object Cons2],[object Cons3]'");
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000364 CHECK(value4->IsTrue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000365
366 v8::Handle<Value> value5 = CompileRun(
367 "Fun2(new Cons1(), new Cons2(), 5) == '[object Cons1],[object Cons2],'");
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000368 CHECK(value5->IsTrue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000369
370 v8::Handle<Value> value6 = CompileRun(
371 "Fun2(new Cons3(), new Cons2(), new Cons1()) == ',[object Cons2],'");
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000372 CHECK(value6->IsTrue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000373
374 v8::Handle<Value> value7 = CompileRun(
375 "Fun2(new Cons1(), new Cons2(), new Cons3(), 'd') == "
376 "'[object Cons1],[object Cons2],[object Cons3],d';");
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000377 CHECK(value7->IsTrue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000378
379 v8::Handle<Value> value8 = CompileRun(
380 "Fun2(new Cons1(), new Cons2()) == '[object Cons1],[object Cons2]'");
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000381 CHECK(value8->IsTrue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000382}
383
384
385THREADED_TEST(HulIgennem) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000386 LocalContext env;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +0000387 v8::Isolate* isolate = env->GetIsolate();
388 v8::HandleScope scope(isolate);
389 v8::Handle<v8::Primitive> undef = v8::Undefined(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000390 Local<String> undef_str = undef->ToString();
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000391 char* value = i::NewArray<char>(undef_str->Utf8Length() + 1);
392 undef_str->WriteUtf8(value);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000393 CHECK_EQ(0, strcmp(value, "undefined"));
394 i::DeleteArray(value);
395}
396
397
398THREADED_TEST(Access) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000399 LocalContext env;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +0000400 v8::Isolate* isolate = env->GetIsolate();
401 v8::HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000402 Local<v8::Object> obj = v8::Object::New();
403 Local<Value> foo_before = obj->Get(v8_str("foo"));
404 CHECK(foo_before->IsUndefined());
405 Local<String> bar_str = v8_str("bar");
406 obj->Set(v8_str("foo"), bar_str);
407 Local<Value> foo_after = obj->Get(v8_str("foo"));
408 CHECK(!foo_after->IsUndefined());
409 CHECK(foo_after->IsString());
410 CHECK_EQ(bar_str, foo_after);
411}
412
413
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000414THREADED_TEST(AccessElement) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000415 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000416 v8::HandleScope scope(env->GetIsolate());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000417 Local<v8::Object> obj = v8::Object::New();
418 Local<Value> before = obj->Get(1);
419 CHECK(before->IsUndefined());
420 Local<String> bar_str = v8_str("bar");
421 obj->Set(1, bar_str);
422 Local<Value> after = obj->Get(1);
423 CHECK(!after->IsUndefined());
424 CHECK(after->IsString());
425 CHECK_EQ(bar_str, after);
426
427 Local<v8::Array> value = CompileRun("[\"a\", \"b\"]").As<v8::Array>();
428 CHECK_EQ(v8_str("a"), value->Get(0));
429 CHECK_EQ(v8_str("b"), value->Get(1));
430}
431
432
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000433THREADED_TEST(Script) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000434 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000435 v8::HandleScope scope(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000436 const char* c_source = "1 + 2 + 3";
437 Local<String> source = String::New(c_source);
438 Local<Script> script = Script::Compile(source);
439 CHECK_EQ(6, script->Run()->Int32Value());
440}
441
442
443static uint16_t* AsciiToTwoByteString(const char* source) {
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000444 int array_length = i::StrLength(source) + 1;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000445 uint16_t* converted = i::NewArray<uint16_t>(array_length);
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000446 for (int i = 0; i < array_length; i++) converted[i] = source[i];
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000447 return converted;
448}
449
450
451class TestResource: public String::ExternalStringResource {
452 public:
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000453 explicit TestResource(uint16_t* data, int* counter = NULL)
454 : data_(data), length_(0), counter_(counter) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000455 while (data[length_]) ++length_;
456 }
457
458 ~TestResource() {
459 i::DeleteArray(data_);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000460 if (counter_ != NULL) ++*counter_;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000461 }
462
463 const uint16_t* data() const {
464 return data_;
465 }
466
467 size_t length() const {
468 return length_;
469 }
470 private:
471 uint16_t* data_;
472 size_t length_;
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000473 int* counter_;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000474};
475
476
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000477class TestAsciiResource: public String::ExternalAsciiStringResource {
478 public:
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000479 explicit TestAsciiResource(const char* data, int* counter = NULL)
480 : data_(data), length_(strlen(data)), counter_(counter) { }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000481
482 ~TestAsciiResource() {
483 i::DeleteArray(data_);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000484 if (counter_ != NULL) ++*counter_;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000485 }
486
487 const char* data() const {
488 return data_;
489 }
490
491 size_t length() const {
492 return length_;
493 }
494 private:
ager@chromium.org5ec48922009-05-05 07:25:34 +0000495 const char* data_;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000496 size_t length_;
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000497 int* counter_;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000498};
499
500
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000501THREADED_TEST(ScriptUsingStringResource) {
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000502 int dispose_count = 0;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000503 const char* c_source = "1 + 2 * 3";
504 uint16_t* two_byte_source = AsciiToTwoByteString(c_source);
505 {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000506 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000507 v8::HandleScope scope(env->GetIsolate());
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000508 TestResource* resource = new TestResource(two_byte_source, &dispose_count);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000509 Local<String> source = String::NewExternal(resource);
510 Local<Script> script = Script::Compile(source);
511 Local<Value> value = script->Run();
512 CHECK(value->IsNumber());
513 CHECK_EQ(7, value->Int32Value());
514 CHECK(source->IsExternal());
515 CHECK_EQ(resource,
516 static_cast<TestResource*>(source->GetExternalStringResource()));
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000517 String::Encoding encoding = String::UNKNOWN_ENCODING;
518 CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
519 source->GetExternalStringResourceBase(&encoding));
520 CHECK_EQ(String::TWO_BYTE_ENCODING, encoding);
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000521 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000522 CHECK_EQ(0, dispose_count);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000523 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000524 CcTest::i_isolate()->compilation_cache()->Clear();
525 CcTest::heap()->CollectAllAvailableGarbage();
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000526 CHECK_EQ(1, dispose_count);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000527}
528
529
530THREADED_TEST(ScriptUsingAsciiStringResource) {
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000531 int dispose_count = 0;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000532 const char* c_source = "1 + 2 * 3";
533 {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000534 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000535 v8::HandleScope scope(env->GetIsolate());
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000536 TestAsciiResource* resource = new TestAsciiResource(i::StrDup(c_source),
537 &dispose_count);
538 Local<String> source = String::NewExternal(resource);
539 CHECK(source->IsExternalAscii());
540 CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
541 source->GetExternalAsciiStringResource());
542 String::Encoding encoding = String::UNKNOWN_ENCODING;
543 CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
544 source->GetExternalStringResourceBase(&encoding));
545 CHECK_EQ(String::ASCII_ENCODING, encoding);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000546 Local<Script> script = Script::Compile(source);
547 Local<Value> value = script->Run();
548 CHECK(value->IsNumber());
549 CHECK_EQ(7, value->Int32Value());
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000550 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000551 CHECK_EQ(0, dispose_count);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000552 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000553 CcTest::i_isolate()->compilation_cache()->Clear();
554 CcTest::heap()->CollectAllAvailableGarbage();
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000555 CHECK_EQ(1, dispose_count);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000556}
557
558
ager@chromium.org6f10e412009-02-13 10:11:16 +0000559THREADED_TEST(ScriptMakingExternalString) {
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000560 int dispose_count = 0;
ager@chromium.org6f10e412009-02-13 10:11:16 +0000561 uint16_t* two_byte_source = AsciiToTwoByteString("1 + 2 * 3");
562 {
ager@chromium.org6f10e412009-02-13 10:11:16 +0000563 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000564 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org6f10e412009-02-13 10:11:16 +0000565 Local<String> source = String::New(two_byte_source);
ager@chromium.org5c838252010-02-19 08:53:10 +0000566 // Trigger GCs so that the newly allocated string moves to old gen.
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000567 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
568 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000569 CHECK_EQ(source->IsExternal(), false);
570 CHECK_EQ(source->IsExternalAscii(), false);
571 String::Encoding encoding = String::UNKNOWN_ENCODING;
572 CHECK_EQ(NULL, source->GetExternalStringResourceBase(&encoding));
573 CHECK_EQ(String::ASCII_ENCODING, encoding);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000574 bool success = source->MakeExternal(new TestResource(two_byte_source,
575 &dispose_count));
ager@chromium.org6f10e412009-02-13 10:11:16 +0000576 CHECK(success);
577 Local<Script> script = Script::Compile(source);
578 Local<Value> value = script->Run();
579 CHECK(value->IsNumber());
580 CHECK_EQ(7, value->Int32Value());
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000581 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000582 CHECK_EQ(0, dispose_count);
ager@chromium.org6f10e412009-02-13 10:11:16 +0000583 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000584 CcTest::i_isolate()->compilation_cache()->Clear();
585 CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000586 CHECK_EQ(1, dispose_count);
ager@chromium.org6f10e412009-02-13 10:11:16 +0000587}
588
589
590THREADED_TEST(ScriptMakingExternalAsciiString) {
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000591 int dispose_count = 0;
ager@chromium.org6f10e412009-02-13 10:11:16 +0000592 const char* c_source = "1 + 2 * 3";
593 {
ager@chromium.org6f10e412009-02-13 10:11:16 +0000594 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000595 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org6f10e412009-02-13 10:11:16 +0000596 Local<String> source = v8_str(c_source);
ager@chromium.org5c838252010-02-19 08:53:10 +0000597 // Trigger GCs so that the newly allocated string moves to old gen.
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000598 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
599 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
ager@chromium.org6f10e412009-02-13 10:11:16 +0000600 bool success = source->MakeExternal(
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000601 new TestAsciiResource(i::StrDup(c_source), &dispose_count));
ager@chromium.org6f10e412009-02-13 10:11:16 +0000602 CHECK(success);
603 Local<Script> script = Script::Compile(source);
604 Local<Value> value = script->Run();
605 CHECK(value->IsNumber());
606 CHECK_EQ(7, value->Int32Value());
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000607 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000608 CHECK_EQ(0, dispose_count);
ager@chromium.org6f10e412009-02-13 10:11:16 +0000609 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000610 CcTest::i_isolate()->compilation_cache()->Clear();
611 CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000612 CHECK_EQ(1, dispose_count);
ager@chromium.org6f10e412009-02-13 10:11:16 +0000613}
614
615
ager@chromium.org5c838252010-02-19 08:53:10 +0000616TEST(MakingExternalStringConditions) {
ager@chromium.org5c838252010-02-19 08:53:10 +0000617 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000618 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org5c838252010-02-19 08:53:10 +0000619
620 // Free some space in the new space so that we can check freshness.
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000621 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
622 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
ager@chromium.org5c838252010-02-19 08:53:10 +0000623
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000624 uint16_t* two_byte_string = AsciiToTwoByteString("s1");
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000625 Local<String> small_string = String::New(two_byte_string);
626 i::DeleteArray(two_byte_string);
627
ager@chromium.org5c838252010-02-19 08:53:10 +0000628 // We should refuse to externalize newly created small string.
629 CHECK(!small_string->CanMakeExternal());
630 // Trigger GCs so that the newly allocated string moves to old gen.
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000631 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
632 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
ager@chromium.org5c838252010-02-19 08:53:10 +0000633 // Old space strings should be accepted.
634 CHECK(small_string->CanMakeExternal());
635
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000636 two_byte_string = AsciiToTwoByteString("small string 2");
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000637 small_string = String::New(two_byte_string);
638 i::DeleteArray(two_byte_string);
639
ager@chromium.org5c838252010-02-19 08:53:10 +0000640 // We should refuse externalizing newly created small string.
641 CHECK(!small_string->CanMakeExternal());
642 for (int i = 0; i < 100; i++) {
643 String::Value value(small_string);
644 }
645 // Frequently used strings should be accepted.
646 CHECK(small_string->CanMakeExternal());
647
648 const int buf_size = 10 * 1024;
649 char* buf = i::NewArray<char>(buf_size);
650 memset(buf, 'a', buf_size);
651 buf[buf_size - 1] = '\0';
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000652
653 two_byte_string = AsciiToTwoByteString(buf);
654 Local<String> large_string = String::New(two_byte_string);
ager@chromium.org5c838252010-02-19 08:53:10 +0000655 i::DeleteArray(buf);
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000656 i::DeleteArray(two_byte_string);
ager@chromium.org5c838252010-02-19 08:53:10 +0000657 // Large strings should be immediately accepted.
658 CHECK(large_string->CanMakeExternal());
659}
660
661
662TEST(MakingExternalAsciiStringConditions) {
ager@chromium.org5c838252010-02-19 08:53:10 +0000663 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000664 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org5c838252010-02-19 08:53:10 +0000665
666 // Free some space in the new space so that we can check freshness.
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000667 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
668 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
ager@chromium.org5c838252010-02-19 08:53:10 +0000669
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000670 Local<String> small_string = String::New("s1");
ager@chromium.org5c838252010-02-19 08:53:10 +0000671 // We should refuse to externalize newly created small string.
672 CHECK(!small_string->CanMakeExternal());
673 // Trigger GCs so that the newly allocated string moves to old gen.
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000674 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
675 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
ager@chromium.org5c838252010-02-19 08:53:10 +0000676 // Old space strings should be accepted.
677 CHECK(small_string->CanMakeExternal());
678
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000679 small_string = String::New("small string 2");
ager@chromium.org5c838252010-02-19 08:53:10 +0000680 // We should refuse externalizing newly created small string.
681 CHECK(!small_string->CanMakeExternal());
682 for (int i = 0; i < 100; i++) {
683 String::Value value(small_string);
684 }
685 // Frequently used strings should be accepted.
686 CHECK(small_string->CanMakeExternal());
687
688 const int buf_size = 10 * 1024;
689 char* buf = i::NewArray<char>(buf_size);
690 memset(buf, 'a', buf_size);
691 buf[buf_size - 1] = '\0';
692 Local<String> large_string = String::New(buf);
693 i::DeleteArray(buf);
694 // Large strings should be immediately accepted.
695 CHECK(large_string->CanMakeExternal());
696}
697
698
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000699TEST(MakingExternalUnalignedAsciiString) {
700 LocalContext env;
701 v8::HandleScope scope(env->GetIsolate());
702
703 CompileRun("function cons(a, b) { return a + b; }"
704 "function slice(a) { return a.substring(1); }");
705 // Create a cons string that will land in old pointer space.
706 Local<String> cons = Local<String>::Cast(CompileRun(
707 "cons('abcdefghijklm', 'nopqrstuvwxyz');"));
708 // Create a sliced string that will land in old pointer space.
709 Local<String> slice = Local<String>::Cast(CompileRun(
710 "slice('abcdefghijklmnopqrstuvwxyz');"));
711
712 // Trigger GCs so that the newly allocated string moves to old gen.
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000713 SimulateFullSpace(CcTest::heap()->old_pointer_space());
714 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
715 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000716
717 // Turn into external string with unaligned resource data.
718 int dispose_count = 0;
719 const char* c_cons = "_abcdefghijklmnopqrstuvwxyz";
720 bool success = cons->MakeExternal(
721 new TestAsciiResource(i::StrDup(c_cons) + 1, &dispose_count));
722 CHECK(success);
723 const char* c_slice = "_bcdefghijklmnopqrstuvwxyz";
724 success = slice->MakeExternal(
725 new TestAsciiResource(i::StrDup(c_slice) + 1, &dispose_count));
726 CHECK(success);
727
728 // Trigger GCs and force evacuation.
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000729 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
730 CcTest::heap()->CollectAllGarbage(i::Heap::kReduceMemoryFootprintMask);
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000731}
732
733
ager@chromium.org6f10e412009-02-13 10:11:16 +0000734THREADED_TEST(UsingExternalString) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000735 i::Factory* factory = CcTest::i_isolate()->factory();
ager@chromium.orge2902be2009-06-08 12:21:35 +0000736 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000737 v8::HandleScope scope(CcTest::isolate());
ager@chromium.orge2902be2009-06-08 12:21:35 +0000738 uint16_t* two_byte_string = AsciiToTwoByteString("test string");
739 Local<String> string =
740 String::NewExternal(new TestResource(two_byte_string));
741 i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
742 // Trigger GCs so that the newly allocated string moves to old gen.
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000743 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
744 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000745 i::Handle<i::String> isymbol =
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000746 factory->InternalizedStringFromString(istring);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000747 CHECK(isymbol->IsInternalizedString());
ager@chromium.orge2902be2009-06-08 12:21:35 +0000748 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000749 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
750 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org6f10e412009-02-13 10:11:16 +0000751}
752
753
754THREADED_TEST(UsingExternalAsciiString) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000755 i::Factory* factory = CcTest::i_isolate()->factory();
ager@chromium.orge2902be2009-06-08 12:21:35 +0000756 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000757 v8::HandleScope scope(CcTest::isolate());
ager@chromium.orge2902be2009-06-08 12:21:35 +0000758 const char* one_byte_string = "test string";
759 Local<String> string = String::NewExternal(
760 new TestAsciiResource(i::StrDup(one_byte_string)));
761 i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
762 // Trigger GCs so that the newly allocated string moves to old gen.
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000763 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
764 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000765 i::Handle<i::String> isymbol =
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000766 factory->InternalizedStringFromString(istring);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000767 CHECK(isymbol->IsInternalizedString());
ager@chromium.orge2902be2009-06-08 12:21:35 +0000768 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000769 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
770 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org6f10e412009-02-13 10:11:16 +0000771}
772
773
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000774THREADED_TEST(ScavengeExternalString) {
svenpanne@chromium.org83130cf2012-11-30 10:13:25 +0000775 i::FLAG_stress_compaction = false;
776 i::FLAG_gc_global = false;
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000777 int dispose_count = 0;
lrn@chromium.orgc34f5802010-04-28 12:53:43 +0000778 bool in_new_space = false;
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000779 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000780 v8::HandleScope scope(CcTest::isolate());
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000781 uint16_t* two_byte_string = AsciiToTwoByteString("test string");
782 Local<String> string =
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000783 String::NewExternal(new TestResource(two_byte_string,
784 &dispose_count));
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000785 i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000786 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
787 in_new_space = CcTest::heap()->InNewSpace(*istring);
788 CHECK(in_new_space || CcTest::heap()->old_data_space()->Contains(*istring));
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000789 CHECK_EQ(0, dispose_count);
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000790 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000791 CcTest::heap()->CollectGarbage(
792 in_new_space ? i::NEW_SPACE : i::OLD_DATA_SPACE);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000793 CHECK_EQ(1, dispose_count);
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000794}
795
796
797THREADED_TEST(ScavengeExternalAsciiString) {
svenpanne@chromium.org83130cf2012-11-30 10:13:25 +0000798 i::FLAG_stress_compaction = false;
799 i::FLAG_gc_global = false;
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000800 int dispose_count = 0;
lrn@chromium.orgc34f5802010-04-28 12:53:43 +0000801 bool in_new_space = false;
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000802 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000803 v8::HandleScope scope(CcTest::isolate());
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000804 const char* one_byte_string = "test string";
805 Local<String> string = String::NewExternal(
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000806 new TestAsciiResource(i::StrDup(one_byte_string), &dispose_count));
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000807 i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000808 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
809 in_new_space = CcTest::heap()->InNewSpace(*istring);
810 CHECK(in_new_space || CcTest::heap()->old_data_space()->Contains(*istring));
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000811 CHECK_EQ(0, dispose_count);
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000812 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000813 CcTest::heap()->CollectGarbage(
814 in_new_space ? i::NEW_SPACE : i::OLD_DATA_SPACE);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000815 CHECK_EQ(1, dispose_count);
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000816}
817
818
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000819class TestAsciiResourceWithDisposeControl: public TestAsciiResource {
820 public:
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000821 // Only used by non-threaded tests, so it can use static fields.
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000822 static int dispose_calls;
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000823 static int dispose_count;
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000824
825 TestAsciiResourceWithDisposeControl(const char* data, bool dispose)
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000826 : TestAsciiResource(data, &dispose_count),
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000827 dispose_(dispose) { }
828
829 void Dispose() {
830 ++dispose_calls;
831 if (dispose_) delete this;
832 }
833 private:
834 bool dispose_;
835};
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000836
837
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000838int TestAsciiResourceWithDisposeControl::dispose_count = 0;
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000839int TestAsciiResourceWithDisposeControl::dispose_calls = 0;
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000840
841
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000842TEST(ExternalStringWithDisposeHandling) {
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000843 const char* c_source = "1 + 2 * 3";
844
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000845 // Use a stack allocated external string resource allocated object.
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000846 TestAsciiResourceWithDisposeControl::dispose_count = 0;
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000847 TestAsciiResourceWithDisposeControl::dispose_calls = 0;
848 TestAsciiResourceWithDisposeControl res_stack(i::StrDup(c_source), false);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000849 {
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000850 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000851 v8::HandleScope scope(env->GetIsolate());
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000852 Local<String> source = String::NewExternal(&res_stack);
853 Local<Script> script = Script::Compile(source);
854 Local<Value> value = script->Run();
855 CHECK(value->IsNumber());
856 CHECK_EQ(7, value->Int32Value());
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000857 CcTest::heap()->CollectAllAvailableGarbage();
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000858 CHECK_EQ(0, TestAsciiResourceWithDisposeControl::dispose_count);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000859 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000860 CcTest::i_isolate()->compilation_cache()->Clear();
861 CcTest::heap()->CollectAllAvailableGarbage();
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000862 CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_calls);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000863 CHECK_EQ(0, TestAsciiResourceWithDisposeControl::dispose_count);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000864
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000865 // Use a heap allocated external string resource allocated object.
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000866 TestAsciiResourceWithDisposeControl::dispose_count = 0;
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000867 TestAsciiResourceWithDisposeControl::dispose_calls = 0;
868 TestAsciiResource* res_heap =
869 new TestAsciiResourceWithDisposeControl(i::StrDup(c_source), true);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000870 {
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000871 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000872 v8::HandleScope scope(env->GetIsolate());
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000873 Local<String> source = String::NewExternal(res_heap);
874 Local<Script> script = Script::Compile(source);
875 Local<Value> value = script->Run();
876 CHECK(value->IsNumber());
877 CHECK_EQ(7, value->Int32Value());
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000878 CcTest::heap()->CollectAllAvailableGarbage();
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000879 CHECK_EQ(0, TestAsciiResourceWithDisposeControl::dispose_count);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000880 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000881 CcTest::i_isolate()->compilation_cache()->Clear();
882 CcTest::heap()->CollectAllAvailableGarbage();
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000883 CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_calls);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000884 CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_count);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000885}
886
887
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000888THREADED_TEST(StringConcat) {
889 {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000890 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000891 v8::HandleScope scope(env->GetIsolate());
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000892 const char* one_byte_string_1 = "function a_times_t";
893 const char* two_byte_string_1 = "wo_plus_b(a, b) {return ";
894 const char* one_byte_extern_1 = "a * 2 + b;} a_times_two_plus_b(4, 8) + ";
895 const char* two_byte_extern_1 = "a_times_two_plus_b(4, 8) + ";
896 const char* one_byte_string_2 = "a_times_two_plus_b(4, 8) + ";
897 const char* two_byte_string_2 = "a_times_two_plus_b(4, 8) + ";
898 const char* two_byte_extern_2 = "a_times_two_plus_b(1, 2);";
899 Local<String> left = v8_str(one_byte_string_1);
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000900
901 uint16_t* two_byte_source = AsciiToTwoByteString(two_byte_string_1);
902 Local<String> right = String::New(two_byte_source);
903 i::DeleteArray(two_byte_source);
904
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000905 Local<String> source = String::Concat(left, right);
906 right = String::NewExternal(
907 new TestAsciiResource(i::StrDup(one_byte_extern_1)));
908 source = String::Concat(source, right);
909 right = String::NewExternal(
910 new TestResource(AsciiToTwoByteString(two_byte_extern_1)));
911 source = String::Concat(source, right);
912 right = v8_str(one_byte_string_2);
913 source = String::Concat(source, right);
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000914
915 two_byte_source = AsciiToTwoByteString(two_byte_string_2);
916 right = String::New(two_byte_source);
917 i::DeleteArray(two_byte_source);
918
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000919 source = String::Concat(source, right);
920 right = String::NewExternal(
921 new TestResource(AsciiToTwoByteString(two_byte_extern_2)));
922 source = String::Concat(source, right);
923 Local<Script> script = Script::Compile(source);
924 Local<Value> value = script->Run();
925 CHECK(value->IsNumber());
926 CHECK_EQ(68, value->Int32Value());
927 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000928 CcTest::i_isolate()->compilation_cache()->Clear();
929 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
930 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000931}
932
933
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000934THREADED_TEST(GlobalProperties) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000935 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000936 v8::HandleScope scope(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000937 v8::Handle<v8::Object> global = env->Global();
938 global->Set(v8_str("pi"), v8_num(3.1415926));
939 Local<Value> pi = global->Get(v8_str("pi"));
940 CHECK_EQ(3.1415926, pi->NumberValue());
941}
942
943
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +0000944template<typename T>
dslomov@chromium.orgb752d402013-06-18 11:54:54 +0000945static void CheckReturnValue(const T& t, i::Address callback) {
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +0000946 v8::ReturnValue<v8::Value> rv = t.GetReturnValue();
947 i::Object** o = *reinterpret_cast<i::Object***>(&rv);
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000948 CHECK_EQ(CcTest::isolate(), t.GetIsolate());
svenpanne@chromium.org53ad1752013-05-27 12:20:38 +0000949 CHECK_EQ(t.GetIsolate(), rv.GetIsolate());
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +0000950 CHECK((*o)->IsTheHole() || (*o)->IsUndefined());
verwaest@chromium.org8a00e822013-06-10 15:11:22 +0000951 // Verify reset
952 bool is_runtime = (*o)->IsTheHole();
953 rv.Set(true);
954 CHECK(!(*o)->IsTheHole() && !(*o)->IsUndefined());
955 rv.Set(v8::Handle<v8::Object>());
956 CHECK((*o)->IsTheHole() || (*o)->IsUndefined());
957 CHECK_EQ(is_runtime, (*o)->IsTheHole());
dslomov@chromium.orgb752d402013-06-18 11:54:54 +0000958
959 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(t.GetIsolate());
960 // If CPU profiler is active check that when API callback is invoked
961 // VMState is set to EXTERNAL.
962 if (isolate->cpu_profiler()->is_profiling()) {
963 CHECK_EQ(i::EXTERNAL, isolate->current_vm_state());
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +0000964 CHECK(isolate->external_callback_scope());
965 CHECK_EQ(callback, isolate->external_callback_scope()->callback());
dslomov@chromium.orgb752d402013-06-18 11:54:54 +0000966 }
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +0000967}
968
dslomov@chromium.orgb752d402013-06-18 11:54:54 +0000969
970static void handle_callback_impl(const v8::FunctionCallbackInfo<Value>& info,
971 i::Address callback) {
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +0000972 ApiTestFuzzer::Fuzz();
dslomov@chromium.orgb752d402013-06-18 11:54:54 +0000973 CheckReturnValue(info, callback);
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +0000974 info.GetReturnValue().Set(v8_str("bad value"));
975 info.GetReturnValue().Set(v8_num(102));
976}
977
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000978
dslomov@chromium.orgb752d402013-06-18 11:54:54 +0000979static void handle_callback(const v8::FunctionCallbackInfo<Value>& info) {
980 return handle_callback_impl(info, FUNCTION_ADDR(handle_callback));
981}
982
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000983
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +0000984static void handle_callback_2(const v8::FunctionCallbackInfo<Value>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +0000985 return handle_callback_impl(info, FUNCTION_ADDR(handle_callback_2));
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +0000986}
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000987
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +0000988static void construct_callback(
989 const v8::FunctionCallbackInfo<Value>& info) {
990 ApiTestFuzzer::Fuzz();
dslomov@chromium.orgb752d402013-06-18 11:54:54 +0000991 CheckReturnValue(info, FUNCTION_ADDR(construct_callback));
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +0000992 info.This()->Set(v8_str("x"), v8_num(1));
993 info.This()->Set(v8_str("y"), v8_num(2));
994 info.GetReturnValue().Set(v8_str("bad value"));
995 info.GetReturnValue().Set(info.This());
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000996}
997
998
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +0000999static void Return239Callback(
1000 Local<String> name, const v8::PropertyCallbackInfo<Value>& info) {
1001 ApiTestFuzzer::Fuzz();
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001002 CheckReturnValue(info, FUNCTION_ADDR(Return239Callback));
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001003 info.GetReturnValue().Set(v8_str("bad value"));
1004 info.GetReturnValue().Set(v8_num(239));
1005}
1006
1007
1008template<typename Handler>
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00001009static void TestFunctionTemplateInitializer(Handler handler,
1010 Handler handler_2) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001011 // Test constructor calls.
1012 {
1013 LocalContext env;
1014 v8::HandleScope scope(env->GetIsolate());
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001015
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001016 Local<v8::FunctionTemplate> fun_templ =
1017 v8::FunctionTemplate::New(handler);
1018 Local<Function> fun = fun_templ->GetFunction();
1019 env->Global()->Set(v8_str("obj"), fun);
1020 Local<Script> script = v8_compile("obj()");
1021 for (int i = 0; i < 30; i++) {
1022 CHECK_EQ(102, script->Run()->Int32Value());
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001023 }
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001024 }
1025 // Use SetCallHandler to initialize a function template, should work like
1026 // the previous one.
1027 {
1028 LocalContext env;
1029 v8::HandleScope scope(env->GetIsolate());
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001030
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001031 Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
1032 fun_templ->SetCallHandler(handler_2);
1033 Local<Function> fun = fun_templ->GetFunction();
1034 env->Global()->Set(v8_str("obj"), fun);
1035 Local<Script> script = v8_compile("obj()");
1036 for (int i = 0; i < 30; i++) {
1037 CHECK_EQ(102, script->Run()->Int32Value());
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001038 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001039 }
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001040}
1041
1042
1043template<typename Constructor, typename Accessor>
1044static void TestFunctionTemplateAccessor(Constructor constructor,
1045 Accessor accessor) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001046 LocalContext env;
1047 v8::HandleScope scope(env->GetIsolate());
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001048
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001049 Local<v8::FunctionTemplate> fun_templ =
1050 v8::FunctionTemplate::New(constructor);
1051 fun_templ->SetClassName(v8_str("funky"));
1052 fun_templ->InstanceTemplate()->SetAccessor(v8_str("m"), accessor);
1053 Local<Function> fun = fun_templ->GetFunction();
1054 env->Global()->Set(v8_str("obj"), fun);
1055 Local<Value> result = v8_compile("(new obj()).toString()")->Run();
1056 CHECK_EQ(v8_str("[object funky]"), result);
1057 CompileRun("var obj_instance = new obj();");
1058 Local<Script> script;
1059 script = v8_compile("obj_instance.x");
1060 for (int i = 0; i < 30; i++) {
1061 CHECK_EQ(1, script->Run()->Int32Value());
1062 }
1063 script = v8_compile("obj_instance.m");
1064 for (int i = 0; i < 30; i++) {
1065 CHECK_EQ(239, script->Run()->Int32Value());
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001066 }
1067}
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001068
ager@chromium.orgb61a0d12010-10-13 08:35:23 +00001069
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001070THREADED_PROFILED_TEST(FunctionTemplate) {
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00001071 TestFunctionTemplateInitializer(handle_callback, handle_callback_2);
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001072 TestFunctionTemplateAccessor(construct_callback, Return239Callback);
1073}
1074
1075
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001076static void SimpleCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
1077 ApiTestFuzzer::Fuzz();
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001078 CheckReturnValue(info, FUNCTION_ADDR(SimpleCallback));
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001079 info.GetReturnValue().Set(v8_num(51423 + info.Length()));
1080}
1081
1082
1083template<typename Callback>
1084static void TestSimpleCallback(Callback callback) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001085 LocalContext env;
1086 v8::HandleScope scope(env->GetIsolate());
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001087
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001088 v8::Handle<v8::ObjectTemplate> object_template = v8::ObjectTemplate::New();
1089 object_template->Set("callback", v8::FunctionTemplate::New(callback));
1090 v8::Local<v8::Object> object = object_template->NewInstance();
1091 (*env)->Global()->Set(v8_str("callback_object"), object);
1092 v8::Handle<v8::Script> script;
1093 script = v8_compile("callback_object.callback(17)");
1094 for (int i = 0; i < 30; i++) {
1095 CHECK_EQ(51424, script->Run()->Int32Value());
1096 }
1097 script = v8_compile("callback_object.callback(17, 24)");
1098 for (int i = 0; i < 30; i++) {
1099 CHECK_EQ(51425, script->Run()->Int32Value());
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001100 }
1101}
1102
1103
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001104THREADED_PROFILED_TEST(SimpleCallback) {
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001105 TestSimpleCallback(SimpleCallback);
1106}
1107
1108
1109template<typename T>
1110void FastReturnValueCallback(const v8::FunctionCallbackInfo<v8::Value>& info);
1111
1112// constant return values
danno@chromium.org1fd77d52013-06-07 16:01:45 +00001113static int32_t fast_return_value_int32 = 471;
1114static uint32_t fast_return_value_uint32 = 571;
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001115static const double kFastReturnValueDouble = 2.7;
1116// variable return values
1117static bool fast_return_value_bool = false;
ulan@chromium.org837a67e2013-06-11 15:39:48 +00001118enum ReturnValueOddball {
1119 kNullReturnValue,
1120 kUndefinedReturnValue,
1121 kEmptyStringReturnValue
1122};
1123static ReturnValueOddball fast_return_value_void;
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00001124static bool fast_return_value_object_is_empty = false;
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001125
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001126// Helper function to avoid compiler error: insufficient contextual information
1127// to determine type when applying FUNCTION_ADDR to a template function.
1128static i::Address address_of(v8::FunctionCallback callback) {
1129 return FUNCTION_ADDR(callback);
1130}
1131
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001132template<>
1133void FastReturnValueCallback<int32_t>(
1134 const v8::FunctionCallbackInfo<v8::Value>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001135 CheckReturnValue(info, address_of(FastReturnValueCallback<int32_t>));
danno@chromium.org1fd77d52013-06-07 16:01:45 +00001136 info.GetReturnValue().Set(fast_return_value_int32);
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001137}
1138
1139template<>
1140void FastReturnValueCallback<uint32_t>(
1141 const v8::FunctionCallbackInfo<v8::Value>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001142 CheckReturnValue(info, address_of(FastReturnValueCallback<uint32_t>));
danno@chromium.org1fd77d52013-06-07 16:01:45 +00001143 info.GetReturnValue().Set(fast_return_value_uint32);
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001144}
1145
1146template<>
1147void FastReturnValueCallback<double>(
1148 const v8::FunctionCallbackInfo<v8::Value>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001149 CheckReturnValue(info, address_of(FastReturnValueCallback<double>));
svenpanne@chromium.org53ad1752013-05-27 12:20:38 +00001150 info.GetReturnValue().Set(kFastReturnValueDouble);
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001151}
1152
1153template<>
1154void FastReturnValueCallback<bool>(
1155 const v8::FunctionCallbackInfo<v8::Value>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001156 CheckReturnValue(info, address_of(FastReturnValueCallback<bool>));
svenpanne@chromium.org53ad1752013-05-27 12:20:38 +00001157 info.GetReturnValue().Set(fast_return_value_bool);
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001158}
1159
1160template<>
1161void FastReturnValueCallback<void>(
1162 const v8::FunctionCallbackInfo<v8::Value>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001163 CheckReturnValue(info, address_of(FastReturnValueCallback<void>));
ulan@chromium.org837a67e2013-06-11 15:39:48 +00001164 switch (fast_return_value_void) {
1165 case kNullReturnValue:
1166 info.GetReturnValue().SetNull();
1167 break;
1168 case kUndefinedReturnValue:
1169 info.GetReturnValue().SetUndefined();
1170 break;
1171 case kEmptyStringReturnValue:
1172 info.GetReturnValue().SetEmptyString();
1173 break;
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001174 }
1175}
1176
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +00001177template<>
1178void FastReturnValueCallback<Object>(
1179 const v8::FunctionCallbackInfo<v8::Value>& info) {
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00001180 v8::Handle<v8::Object> object;
1181 if (!fast_return_value_object_is_empty) object = Object::New();
1182 info.GetReturnValue().Set(object);
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +00001183}
1184
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001185template<typename T>
1186Handle<Value> TestFastReturnValues() {
1187 LocalContext env;
1188 v8::HandleScope scope(env->GetIsolate());
1189 v8::Handle<v8::ObjectTemplate> object_template = v8::ObjectTemplate::New();
1190 v8::FunctionCallback callback = &FastReturnValueCallback<T>;
1191 object_template->Set("callback", v8::FunctionTemplate::New(callback));
1192 v8::Local<v8::Object> object = object_template->NewInstance();
1193 (*env)->Global()->Set(v8_str("callback_object"), object);
1194 return scope.Close(CompileRun("callback_object.callback()"));
1195}
1196
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001197
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001198THREADED_PROFILED_TEST(FastReturnValues) {
danno@chromium.org1fd77d52013-06-07 16:01:45 +00001199 LocalContext env;
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001200 v8::HandleScope scope(CcTest::isolate());
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001201 v8::Handle<v8::Value> value;
danno@chromium.org1fd77d52013-06-07 16:01:45 +00001202 // check int32_t and uint32_t
1203 int32_t int_values[] = {
1204 0, 234, -723,
1205 i::Smi::kMinValue, i::Smi::kMaxValue
1206 };
1207 for (size_t i = 0; i < ARRAY_SIZE(int_values); i++) {
1208 for (int modifier = -1; modifier <= 1; modifier++) {
1209 int int_value = int_values[i] + modifier;
1210 // check int32_t
1211 fast_return_value_int32 = int_value;
1212 value = TestFastReturnValues<int32_t>();
1213 CHECK(value->IsInt32());
1214 CHECK(fast_return_value_int32 == value->Int32Value());
1215 // check uint32_t
1216 fast_return_value_uint32 = static_cast<uint32_t>(int_value);
1217 value = TestFastReturnValues<uint32_t>();
1218 CHECK(value->IsUint32());
1219 CHECK(fast_return_value_uint32 == value->Uint32Value());
1220 }
1221 }
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001222 // check double
1223 value = TestFastReturnValues<double>();
1224 CHECK(value->IsNumber());
1225 CHECK_EQ(kFastReturnValueDouble, value->ToNumber()->Value());
1226 // check bool values
1227 for (int i = 0; i < 2; i++) {
1228 fast_return_value_bool = i == 0;
1229 value = TestFastReturnValues<bool>();
1230 CHECK(value->IsBoolean());
1231 CHECK_EQ(fast_return_value_bool, value->ToBoolean()->Value());
1232 }
1233 // check oddballs
ulan@chromium.org837a67e2013-06-11 15:39:48 +00001234 ReturnValueOddball oddballs[] = {
1235 kNullReturnValue,
1236 kUndefinedReturnValue,
1237 kEmptyStringReturnValue
1238 };
1239 for (size_t i = 0; i < ARRAY_SIZE(oddballs); i++) {
1240 fast_return_value_void = oddballs[i];
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001241 value = TestFastReturnValues<void>();
ulan@chromium.org837a67e2013-06-11 15:39:48 +00001242 switch (fast_return_value_void) {
1243 case kNullReturnValue:
1244 CHECK(value->IsNull());
1245 break;
1246 case kUndefinedReturnValue:
1247 CHECK(value->IsUndefined());
1248 break;
1249 case kEmptyStringReturnValue:
1250 CHECK(value->IsString());
1251 CHECK_EQ(0, v8::String::Cast(*value)->Length());
1252 break;
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001253 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001254 }
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00001255 // check handles
1256 fast_return_value_object_is_empty = false;
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +00001257 value = TestFastReturnValues<Object>();
1258 CHECK(value->IsObject());
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00001259 fast_return_value_object_is_empty = true;
1260 value = TestFastReturnValues<Object>();
1261 CHECK(value->IsUndefined());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001262}
1263
1264
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001265THREADED_TEST(FunctionTemplateSetLength) {
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001266 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001267 v8::HandleScope scope(env->GetIsolate());
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001268 {
1269 Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001270 handle_callback, Handle<v8::Value>(), Handle<v8::Signature>(), 23);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001271 Local<Function> fun = fun_templ->GetFunction();
1272 env->Global()->Set(v8_str("obj"), fun);
1273 Local<Script> script = v8_compile("obj.length");
1274 CHECK_EQ(23, script->Run()->Int32Value());
1275 }
1276 {
1277 Local<v8::FunctionTemplate> fun_templ =
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001278 v8::FunctionTemplate::New(handle_callback);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001279 fun_templ->SetLength(22);
1280 Local<Function> fun = fun_templ->GetFunction();
1281 env->Global()->Set(v8_str("obj"), fun);
1282 Local<Script> script = v8_compile("obj.length");
1283 CHECK_EQ(22, script->Run()->Int32Value());
1284 }
1285 {
1286 // Without setting length it defaults to 0.
1287 Local<v8::FunctionTemplate> fun_templ =
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001288 v8::FunctionTemplate::New(handle_callback);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001289 Local<Function> fun = fun_templ->GetFunction();
1290 env->Global()->Set(v8_str("obj"), fun);
1291 Local<Script> script = v8_compile("obj.length");
1292 CHECK_EQ(0, script->Run()->Int32Value());
1293 }
1294}
1295
1296
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001297static void* expected_ptr;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001298static void callback(const v8::FunctionCallbackInfo<v8::Value>& args) {
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00001299 void* ptr = v8::External::Cast(*args.Data())->Value();
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001300 CHECK_EQ(expected_ptr, ptr);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001301 args.GetReturnValue().Set(true);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001302}
1303
1304
1305static void TestExternalPointerWrapping() {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001306 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001307 v8::HandleScope scope(env->GetIsolate());
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001308
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00001309 v8::Handle<v8::Value> data = v8::External::New(expected_ptr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001310
1311 v8::Handle<v8::Object> obj = v8::Object::New();
1312 obj->Set(v8_str("func"),
1313 v8::FunctionTemplate::New(callback, data)->GetFunction());
1314 env->Global()->Set(v8_str("obj"), obj);
1315
1316 CHECK(CompileRun(
1317 "function foo() {\n"
1318 " for (var i = 0; i < 13; i++) obj.func();\n"
1319 "}\n"
1320 "foo(), true")->BooleanValue());
1321}
1322
1323
1324THREADED_TEST(ExternalWrap) {
1325 // Check heap allocated object.
1326 int* ptr = new int;
1327 expected_ptr = ptr;
1328 TestExternalPointerWrapping();
1329 delete ptr;
1330
1331 // Check stack allocated object.
1332 int foo;
1333 expected_ptr = &foo;
1334 TestExternalPointerWrapping();
1335
1336 // Check not aligned addresses.
1337 const int n = 100;
1338 char* s = new char[n];
1339 for (int i = 0; i < n; i++) {
1340 expected_ptr = s + i;
1341 TestExternalPointerWrapping();
1342 }
1343
1344 delete[] s;
1345
1346 // Check several invalid addresses.
1347 expected_ptr = reinterpret_cast<void*>(1);
1348 TestExternalPointerWrapping();
1349
1350 expected_ptr = reinterpret_cast<void*>(0xdeadbeef);
1351 TestExternalPointerWrapping();
1352
1353 expected_ptr = reinterpret_cast<void*>(0xdeadbeef + 1);
1354 TestExternalPointerWrapping();
1355
1356#if defined(V8_HOST_ARCH_X64)
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001357 // Check a value with a leading 1 bit in x64 Smi encoding.
1358 expected_ptr = reinterpret_cast<void*>(0x400000000);
1359 TestExternalPointerWrapping();
1360
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001361 expected_ptr = reinterpret_cast<void*>(0xdeadbeefdeadbeef);
1362 TestExternalPointerWrapping();
1363
1364 expected_ptr = reinterpret_cast<void*>(0xdeadbeefdeadbeef + 1);
1365 TestExternalPointerWrapping();
1366#endif
1367}
1368
1369
sgjesse@chromium.org900d3b72009-08-07 11:24:25 +00001370THREADED_TEST(FindInstanceInPrototypeChain) {
sgjesse@chromium.org900d3b72009-08-07 11:24:25 +00001371 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001372 v8::HandleScope scope(env->GetIsolate());
sgjesse@chromium.org900d3b72009-08-07 11:24:25 +00001373
1374 Local<v8::FunctionTemplate> base = v8::FunctionTemplate::New();
1375 Local<v8::FunctionTemplate> derived = v8::FunctionTemplate::New();
1376 Local<v8::FunctionTemplate> other = v8::FunctionTemplate::New();
1377 derived->Inherit(base);
1378
1379 Local<v8::Function> base_function = base->GetFunction();
1380 Local<v8::Function> derived_function = derived->GetFunction();
1381 Local<v8::Function> other_function = other->GetFunction();
1382
1383 Local<v8::Object> base_instance = base_function->NewInstance();
1384 Local<v8::Object> derived_instance = derived_function->NewInstance();
1385 Local<v8::Object> derived_instance2 = derived_function->NewInstance();
1386 Local<v8::Object> other_instance = other_function->NewInstance();
1387 derived_instance2->Set(v8_str("__proto__"), derived_instance);
1388 other_instance->Set(v8_str("__proto__"), derived_instance2);
1389
1390 // base_instance is only an instance of base.
1391 CHECK_EQ(base_instance,
1392 base_instance->FindInstanceInPrototypeChain(base));
1393 CHECK(base_instance->FindInstanceInPrototypeChain(derived).IsEmpty());
1394 CHECK(base_instance->FindInstanceInPrototypeChain(other).IsEmpty());
1395
1396 // derived_instance is an instance of base and derived.
1397 CHECK_EQ(derived_instance,
1398 derived_instance->FindInstanceInPrototypeChain(base));
1399 CHECK_EQ(derived_instance,
1400 derived_instance->FindInstanceInPrototypeChain(derived));
1401 CHECK(derived_instance->FindInstanceInPrototypeChain(other).IsEmpty());
1402
1403 // other_instance is an instance of other and its immediate
1404 // prototype derived_instance2 is an instance of base and derived.
1405 // Note, derived_instance is an instance of base and derived too,
1406 // but it comes after derived_instance2 in the prototype chain of
1407 // other_instance.
1408 CHECK_EQ(derived_instance2,
1409 other_instance->FindInstanceInPrototypeChain(base));
1410 CHECK_EQ(derived_instance2,
1411 other_instance->FindInstanceInPrototypeChain(derived));
1412 CHECK_EQ(other_instance,
1413 other_instance->FindInstanceInPrototypeChain(other));
1414}
1415
1416
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001417THREADED_TEST(TinyInteger) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001418 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001419 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001420 v8::Isolate* isolate = CcTest::isolate();
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001421
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001422 int32_t value = 239;
1423 Local<v8::Integer> value_obj = v8::Integer::New(value);
1424 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001425
1426 value_obj = v8::Integer::New(value, isolate);
1427 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001428}
1429
1430
1431THREADED_TEST(BigSmiInteger) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001432 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001433 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001434 v8::Isolate* isolate = CcTest::isolate();
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001435
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001436 int32_t value = i::Smi::kMaxValue;
1437 // We cannot add one to a Smi::kMaxValue without wrapping.
verwaest@chromium.org662436e2013-08-28 08:41:27 +00001438 if (i::SmiValuesAre31Bits()) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001439 CHECK(i::Smi::IsValid(value));
1440 CHECK(!i::Smi::IsValid(value + 1));
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001441
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001442 Local<v8::Integer> value_obj = v8::Integer::New(value);
1443 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001444
1445 value_obj = v8::Integer::New(value, isolate);
1446 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001447 }
1448}
1449
1450
1451THREADED_TEST(BigInteger) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001452 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001453 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001454 v8::Isolate* isolate = CcTest::isolate();
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001455
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001456 // We cannot add one to a Smi::kMaxValue without wrapping.
verwaest@chromium.org662436e2013-08-28 08:41:27 +00001457 if (i::SmiValuesAre31Bits()) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001458 // The casts allow this to compile, even if Smi::kMaxValue is 2^31-1.
1459 // The code will not be run in that case, due to the "if" guard.
1460 int32_t value =
1461 static_cast<int32_t>(static_cast<uint32_t>(i::Smi::kMaxValue) + 1);
1462 CHECK(value > i::Smi::kMaxValue);
1463 CHECK(!i::Smi::IsValid(value));
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001464
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001465 Local<v8::Integer> value_obj = v8::Integer::New(value);
1466 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001467
1468 value_obj = v8::Integer::New(value, isolate);
1469 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001470 }
1471}
1472
1473
1474THREADED_TEST(TinyUnsignedInteger) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001475 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001476 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001477 v8::Isolate* isolate = CcTest::isolate();
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001478
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001479 uint32_t value = 239;
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001480
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001481 Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(value);
1482 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001483
1484 value_obj = v8::Integer::NewFromUnsigned(value, isolate);
1485 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001486}
1487
1488
1489THREADED_TEST(BigUnsignedSmiInteger) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001490 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001491 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001492 v8::Isolate* isolate = CcTest::isolate();
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001493
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001494 uint32_t value = static_cast<uint32_t>(i::Smi::kMaxValue);
1495 CHECK(i::Smi::IsValid(value));
1496 CHECK(!i::Smi::IsValid(value + 1));
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001497
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001498 Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(value);
1499 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001500
1501 value_obj = v8::Integer::NewFromUnsigned(value, isolate);
1502 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001503}
1504
1505
1506THREADED_TEST(BigUnsignedInteger) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001507 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001508 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001509 v8::Isolate* isolate = CcTest::isolate();
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001510
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001511 uint32_t value = static_cast<uint32_t>(i::Smi::kMaxValue) + 1;
1512 CHECK(value > static_cast<uint32_t>(i::Smi::kMaxValue));
1513 CHECK(!i::Smi::IsValid(value));
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001514
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001515 Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(value);
1516 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001517
1518 value_obj = v8::Integer::NewFromUnsigned(value, isolate);
1519 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001520}
1521
1522
1523THREADED_TEST(OutOfSignedRangeUnsignedInteger) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001524 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001525 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001526 v8::Isolate* isolate = CcTest::isolate();
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001527
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001528 uint32_t INT32_MAX_AS_UINT = (1U << 31) - 1;
1529 uint32_t value = INT32_MAX_AS_UINT + 1;
1530 CHECK(value > INT32_MAX_AS_UINT); // No overflow.
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001531
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001532 Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(value);
1533 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001534
1535 value_obj = v8::Integer::NewFromUnsigned(value, isolate);
1536 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001537}
1538
1539
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001540THREADED_TEST(IsNativeError) {
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001541 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001542 v8::HandleScope scope(env->GetIsolate());
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001543 v8::Handle<Value> syntax_error = CompileRun(
1544 "var out = 0; try { eval(\"#\"); } catch(x) { out = x; } out; ");
1545 CHECK(syntax_error->IsNativeError());
1546 v8::Handle<Value> not_error = CompileRun("{a:42}");
1547 CHECK(!not_error->IsNativeError());
1548 v8::Handle<Value> not_object = CompileRun("42");
1549 CHECK(!not_object->IsNativeError());
1550}
1551
1552
1553THREADED_TEST(StringObject) {
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001554 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001555 v8::HandleScope scope(env->GetIsolate());
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001556 v8::Handle<Value> boxed_string = CompileRun("new String(\"test\")");
1557 CHECK(boxed_string->IsStringObject());
1558 v8::Handle<Value> unboxed_string = CompileRun("\"test\"");
1559 CHECK(!unboxed_string->IsStringObject());
1560 v8::Handle<Value> boxed_not_string = CompileRun("new Number(42)");
1561 CHECK(!boxed_not_string->IsStringObject());
1562 v8::Handle<Value> not_object = CompileRun("0");
1563 CHECK(!not_object->IsStringObject());
1564 v8::Handle<v8::StringObject> as_boxed = boxed_string.As<v8::StringObject>();
1565 CHECK(!as_boxed.IsEmpty());
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001566 Local<v8::String> the_string = as_boxed->ValueOf();
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001567 CHECK(!the_string.IsEmpty());
1568 ExpectObject("\"test\"", the_string);
1569 v8::Handle<v8::Value> new_boxed_string = v8::StringObject::New(the_string);
1570 CHECK(new_boxed_string->IsStringObject());
1571 as_boxed = new_boxed_string.As<v8::StringObject>();
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001572 the_string = as_boxed->ValueOf();
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001573 CHECK(!the_string.IsEmpty());
1574 ExpectObject("\"test\"", the_string);
1575}
1576
1577
1578THREADED_TEST(NumberObject) {
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001579 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001580 v8::HandleScope scope(env->GetIsolate());
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001581 v8::Handle<Value> boxed_number = CompileRun("new Number(42)");
1582 CHECK(boxed_number->IsNumberObject());
1583 v8::Handle<Value> unboxed_number = CompileRun("42");
1584 CHECK(!unboxed_number->IsNumberObject());
1585 v8::Handle<Value> boxed_not_number = CompileRun("new Boolean(false)");
1586 CHECK(!boxed_not_number->IsNumberObject());
1587 v8::Handle<v8::NumberObject> as_boxed = boxed_number.As<v8::NumberObject>();
1588 CHECK(!as_boxed.IsEmpty());
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001589 double the_number = as_boxed->ValueOf();
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001590 CHECK_EQ(42.0, the_number);
1591 v8::Handle<v8::Value> new_boxed_number = v8::NumberObject::New(43);
1592 CHECK(new_boxed_number->IsNumberObject());
1593 as_boxed = new_boxed_number.As<v8::NumberObject>();
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001594 the_number = as_boxed->ValueOf();
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001595 CHECK_EQ(43.0, the_number);
1596}
1597
1598
1599THREADED_TEST(BooleanObject) {
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001600 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001601 v8::HandleScope scope(env->GetIsolate());
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001602 v8::Handle<Value> boxed_boolean = CompileRun("new Boolean(true)");
1603 CHECK(boxed_boolean->IsBooleanObject());
1604 v8::Handle<Value> unboxed_boolean = CompileRun("true");
1605 CHECK(!unboxed_boolean->IsBooleanObject());
1606 v8::Handle<Value> boxed_not_boolean = CompileRun("new Number(42)");
1607 CHECK(!boxed_not_boolean->IsBooleanObject());
1608 v8::Handle<v8::BooleanObject> as_boxed =
1609 boxed_boolean.As<v8::BooleanObject>();
1610 CHECK(!as_boxed.IsEmpty());
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001611 bool the_boolean = as_boxed->ValueOf();
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001612 CHECK_EQ(true, the_boolean);
1613 v8::Handle<v8::Value> boxed_true = v8::BooleanObject::New(true);
1614 v8::Handle<v8::Value> boxed_false = v8::BooleanObject::New(false);
1615 CHECK(boxed_true->IsBooleanObject());
1616 CHECK(boxed_false->IsBooleanObject());
1617 as_boxed = boxed_true.As<v8::BooleanObject>();
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001618 CHECK_EQ(true, as_boxed->ValueOf());
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001619 as_boxed = boxed_false.As<v8::BooleanObject>();
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001620 CHECK_EQ(false, as_boxed->ValueOf());
1621}
1622
1623
1624THREADED_TEST(PrimitiveAndWrappedBooleans) {
1625 LocalContext env;
1626 v8::HandleScope scope(env->GetIsolate());
1627
1628 Local<Value> primitive_false = Boolean::New(false);
1629 CHECK(primitive_false->IsBoolean());
1630 CHECK(!primitive_false->IsBooleanObject());
1631 CHECK(!primitive_false->BooleanValue());
1632 CHECK(!primitive_false->IsTrue());
1633 CHECK(primitive_false->IsFalse());
1634
1635 Local<Value> false_value = BooleanObject::New(false);
1636 CHECK(!false_value->IsBoolean());
1637 CHECK(false_value->IsBooleanObject());
1638 CHECK(false_value->BooleanValue());
1639 CHECK(!false_value->IsTrue());
1640 CHECK(!false_value->IsFalse());
1641
1642 Local<BooleanObject> false_boolean_object = false_value.As<BooleanObject>();
1643 CHECK(!false_boolean_object->IsBoolean());
1644 CHECK(false_boolean_object->IsBooleanObject());
1645 // TODO(svenpanne) Uncomment when BooleanObject::BooleanValue() is deleted.
1646 // CHECK(false_boolean_object->BooleanValue());
1647 CHECK(!false_boolean_object->ValueOf());
1648 CHECK(!false_boolean_object->IsTrue());
1649 CHECK(!false_boolean_object->IsFalse());
1650
1651 Local<Value> primitive_true = Boolean::New(true);
1652 CHECK(primitive_true->IsBoolean());
1653 CHECK(!primitive_true->IsBooleanObject());
1654 CHECK(primitive_true->BooleanValue());
1655 CHECK(primitive_true->IsTrue());
1656 CHECK(!primitive_true->IsFalse());
1657
1658 Local<Value> true_value = BooleanObject::New(true);
1659 CHECK(!true_value->IsBoolean());
1660 CHECK(true_value->IsBooleanObject());
1661 CHECK(true_value->BooleanValue());
1662 CHECK(!true_value->IsTrue());
1663 CHECK(!true_value->IsFalse());
1664
1665 Local<BooleanObject> true_boolean_object = true_value.As<BooleanObject>();
1666 CHECK(!true_boolean_object->IsBoolean());
1667 CHECK(true_boolean_object->IsBooleanObject());
1668 // TODO(svenpanne) Uncomment when BooleanObject::BooleanValue() is deleted.
1669 // CHECK(true_boolean_object->BooleanValue());
1670 CHECK(true_boolean_object->ValueOf());
1671 CHECK(!true_boolean_object->IsTrue());
1672 CHECK(!true_boolean_object->IsFalse());
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001673}
1674
1675
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001676THREADED_TEST(Number) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001677 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001678 v8::HandleScope scope(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001679 double PI = 3.1415926;
1680 Local<v8::Number> pi_obj = v8::Number::New(PI);
1681 CHECK_EQ(PI, pi_obj->NumberValue());
1682}
1683
1684
1685THREADED_TEST(ToNumber) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001686 LocalContext env;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00001687 v8::Isolate* isolate = CcTest::isolate();
1688 v8::HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001689 Local<String> str = v8_str("3.1415926");
1690 CHECK_EQ(3.1415926, str->NumberValue());
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00001691 v8::Handle<v8::Boolean> t = v8::True(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001692 CHECK_EQ(1.0, t->NumberValue());
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00001693 v8::Handle<v8::Boolean> f = v8::False(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001694 CHECK_EQ(0.0, f->NumberValue());
1695}
1696
1697
1698THREADED_TEST(Date) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001699 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001700 v8::HandleScope scope(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001701 double PI = 3.1415926;
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +00001702 Local<Value> date = v8::Date::New(PI);
1703 CHECK_EQ(3.0, date->NumberValue());
1704 date.As<v8::Date>()->Set(v8_str("property"), v8::Integer::New(42));
1705 CHECK_EQ(42, date.As<v8::Date>()->Get(v8_str("property"))->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001706}
1707
1708
1709THREADED_TEST(Boolean) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001710 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001711 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00001712 v8::Handle<v8::Boolean> t = v8::True(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001713 CHECK(t->Value());
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00001714 v8::Handle<v8::Boolean> f = v8::False(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001715 CHECK(!f->Value());
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00001716 v8::Handle<v8::Primitive> u = v8::Undefined(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001717 CHECK(!u->BooleanValue());
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00001718 v8::Handle<v8::Primitive> n = v8::Null(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001719 CHECK(!n->BooleanValue());
1720 v8::Handle<String> str1 = v8_str("");
1721 CHECK(!str1->BooleanValue());
1722 v8::Handle<String> str2 = v8_str("x");
1723 CHECK(str2->BooleanValue());
1724 CHECK(!v8::Number::New(0)->BooleanValue());
1725 CHECK(v8::Number::New(-1)->BooleanValue());
1726 CHECK(v8::Number::New(1)->BooleanValue());
1727 CHECK(v8::Number::New(42)->BooleanValue());
1728 CHECK(!v8_compile("NaN")->Run()->BooleanValue());
1729}
1730
1731
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001732static void DummyCallHandler(const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001733 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001734 args.GetReturnValue().Set(v8_num(13.4));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001735}
1736
1737
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001738static void GetM(Local<String> name,
1739 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001740 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001741 info.GetReturnValue().Set(v8_num(876));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001742}
1743
1744
1745THREADED_TEST(GlobalPrototype) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001746 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001747 v8::Handle<v8::FunctionTemplate> func_templ = v8::FunctionTemplate::New();
1748 func_templ->PrototypeTemplate()->Set(
1749 "dummy",
1750 v8::FunctionTemplate::New(DummyCallHandler));
1751 v8::Handle<ObjectTemplate> templ = func_templ->InstanceTemplate();
1752 templ->Set("x", v8_num(200));
1753 templ->SetAccessor(v8_str("m"), GetM);
1754 LocalContext env(0, templ);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001755 v8::Handle<Script> script(v8_compile("dummy()"));
1756 v8::Handle<Value> result(script->Run());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001757 CHECK_EQ(13.4, result->NumberValue());
1758 CHECK_EQ(200, v8_compile("x")->Run()->Int32Value());
1759 CHECK_EQ(876, v8_compile("m")->Run()->Int32Value());
1760}
1761
1762
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001763THREADED_TEST(ObjectTemplate) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001764 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001765 Local<ObjectTemplate> templ1 = ObjectTemplate::New();
1766 templ1->Set("x", v8_num(10));
1767 templ1->Set("y", v8_num(13));
1768 LocalContext env;
1769 Local<v8::Object> instance1 = templ1->NewInstance();
1770 env->Global()->Set(v8_str("p"), instance1);
1771 CHECK(v8_compile("(p.x == 10)")->Run()->BooleanValue());
1772 CHECK(v8_compile("(p.y == 13)")->Run()->BooleanValue());
1773 Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New();
1774 fun->PrototypeTemplate()->Set("nirk", v8_num(123));
1775 Local<ObjectTemplate> templ2 = fun->InstanceTemplate();
1776 templ2->Set("a", v8_num(12));
1777 templ2->Set("b", templ1);
1778 Local<v8::Object> instance2 = templ2->NewInstance();
1779 env->Global()->Set(v8_str("q"), instance2);
1780 CHECK(v8_compile("(q.nirk == 123)")->Run()->BooleanValue());
1781 CHECK(v8_compile("(q.a == 12)")->Run()->BooleanValue());
1782 CHECK(v8_compile("(q.b.x == 10)")->Run()->BooleanValue());
1783 CHECK(v8_compile("(q.b.y == 13)")->Run()->BooleanValue());
1784}
1785
1786
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001787static void GetFlabby(const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001788 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001789 args.GetReturnValue().Set(v8_num(17.2));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001790}
1791
1792
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001793static void GetKnurd(Local<String> property,
1794 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001795 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001796 info.GetReturnValue().Set(v8_num(15.2));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001797}
1798
1799
1800THREADED_TEST(DescriptorInheritance) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001801 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001802 v8::Handle<v8::FunctionTemplate> super = v8::FunctionTemplate::New();
1803 super->PrototypeTemplate()->Set("flabby",
1804 v8::FunctionTemplate::New(GetFlabby));
1805 super->PrototypeTemplate()->Set("PI", v8_num(3.14));
1806
1807 super->InstanceTemplate()->SetAccessor(v8_str("knurd"), GetKnurd);
1808
1809 v8::Handle<v8::FunctionTemplate> base1 = v8::FunctionTemplate::New();
1810 base1->Inherit(super);
1811 base1->PrototypeTemplate()->Set("v1", v8_num(20.1));
1812
1813 v8::Handle<v8::FunctionTemplate> base2 = v8::FunctionTemplate::New();
1814 base2->Inherit(super);
1815 base2->PrototypeTemplate()->Set("v2", v8_num(10.1));
1816
1817 LocalContext env;
1818
1819 env->Global()->Set(v8_str("s"), super->GetFunction());
1820 env->Global()->Set(v8_str("base1"), base1->GetFunction());
1821 env->Global()->Set(v8_str("base2"), base2->GetFunction());
1822
1823 // Checks right __proto__ chain.
1824 CHECK(CompileRun("base1.prototype.__proto__ == s.prototype")->BooleanValue());
1825 CHECK(CompileRun("base2.prototype.__proto__ == s.prototype")->BooleanValue());
1826
1827 CHECK(v8_compile("s.prototype.PI == 3.14")->Run()->BooleanValue());
1828
1829 // Instance accessor should not be visible on function object or its prototype
1830 CHECK(CompileRun("s.knurd == undefined")->BooleanValue());
1831 CHECK(CompileRun("s.prototype.knurd == undefined")->BooleanValue());
1832 CHECK(CompileRun("base1.prototype.knurd == undefined")->BooleanValue());
1833
1834 env->Global()->Set(v8_str("obj"),
1835 base1->GetFunction()->NewInstance());
1836 CHECK_EQ(17.2, v8_compile("obj.flabby()")->Run()->NumberValue());
1837 CHECK(v8_compile("'flabby' in obj")->Run()->BooleanValue());
1838 CHECK_EQ(15.2, v8_compile("obj.knurd")->Run()->NumberValue());
1839 CHECK(v8_compile("'knurd' in obj")->Run()->BooleanValue());
1840 CHECK_EQ(20.1, v8_compile("obj.v1")->Run()->NumberValue());
1841
1842 env->Global()->Set(v8_str("obj2"),
1843 base2->GetFunction()->NewInstance());
1844 CHECK_EQ(17.2, v8_compile("obj2.flabby()")->Run()->NumberValue());
1845 CHECK(v8_compile("'flabby' in obj2")->Run()->BooleanValue());
1846 CHECK_EQ(15.2, v8_compile("obj2.knurd")->Run()->NumberValue());
1847 CHECK(v8_compile("'knurd' in obj2")->Run()->BooleanValue());
1848 CHECK_EQ(10.1, v8_compile("obj2.v2")->Run()->NumberValue());
1849
1850 // base1 and base2 cannot cross reference to each's prototype
1851 CHECK(v8_compile("obj.v2")->Run()->IsUndefined());
1852 CHECK(v8_compile("obj2.v1")->Run()->IsUndefined());
1853}
1854
1855
1856int echo_named_call_count;
1857
1858
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001859static void EchoNamedProperty(Local<String> name,
1860 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001861 ApiTestFuzzer::Fuzz();
1862 CHECK_EQ(v8_str("data"), info.Data());
1863 echo_named_call_count++;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001864 info.GetReturnValue().Set(name);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001865}
1866
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001867
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001868// Helper functions for Interceptor/Accessor interaction tests
1869
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001870void SimpleAccessorGetter(Local<String> name,
1871 const v8::PropertyCallbackInfo<v8::Value>& info) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001872 Handle<Object> self = info.This();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001873 info.GetReturnValue().Set(
1874 self->Get(String::Concat(v8_str("accessor_"), name)));
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001875}
1876
1877void SimpleAccessorSetter(Local<String> name, Local<Value> value,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001878 const v8::PropertyCallbackInfo<void>& info) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001879 Handle<Object> self = info.This();
1880 self->Set(String::Concat(v8_str("accessor_"), name), value);
1881}
1882
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001883void EmptyInterceptorGetter(Local<String> name,
1884 const v8::PropertyCallbackInfo<v8::Value>& info) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001885}
1886
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001887void EmptyInterceptorSetter(Local<String> name,
1888 Local<Value> value,
1889 const v8::PropertyCallbackInfo<v8::Value>& info) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001890}
1891
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001892void InterceptorGetter(Local<String> name,
1893 const v8::PropertyCallbackInfo<v8::Value>& info) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001894 // Intercept names that start with 'interceptor_'.
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00001895 String::Utf8Value utf8(name);
1896 char* name_str = *utf8;
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001897 char prefix[] = "interceptor_";
1898 int i;
1899 for (i = 0; name_str[i] && prefix[i]; ++i) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001900 if (name_str[i] != prefix[i]) return;
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001901 }
1902 Handle<Object> self = info.This();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001903 info.GetReturnValue().Set(self->GetHiddenValue(v8_str(name_str + i)));
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001904}
1905
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001906void InterceptorSetter(Local<String> name,
1907 Local<Value> value,
1908 const v8::PropertyCallbackInfo<v8::Value>& info) {
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +00001909 // Intercept accesses that set certain integer values, for which the name does
1910 // not start with 'accessor_'.
1911 String::Utf8Value utf8(name);
1912 char* name_str = *utf8;
1913 char prefix[] = "accessor_";
1914 int i;
1915 for (i = 0; name_str[i] && prefix[i]; ++i) {
1916 if (name_str[i] != prefix[i]) break;
1917 }
1918 if (!prefix[i]) return;
1919
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001920 if (value->IsInt32() && value->Int32Value() < 10000) {
1921 Handle<Object> self = info.This();
1922 self->SetHiddenValue(name, value);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001923 info.GetReturnValue().Set(value);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001924 }
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001925}
1926
1927void AddAccessor(Handle<FunctionTemplate> templ,
1928 Handle<String> name,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001929 v8::AccessorGetterCallback getter,
1930 v8::AccessorSetterCallback setter) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001931 templ->PrototypeTemplate()->SetAccessor(name, getter, setter);
1932}
1933
1934void AddInterceptor(Handle<FunctionTemplate> templ,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001935 v8::NamedPropertyGetterCallback getter,
1936 v8::NamedPropertySetterCallback setter) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001937 templ->InstanceTemplate()->SetNamedPropertyHandler(getter, setter);
1938}
1939
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001940
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001941THREADED_TEST(EmptyInterceptorDoesNotShadowAccessors) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001942 v8::HandleScope scope(CcTest::isolate());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001943 Handle<FunctionTemplate> parent = FunctionTemplate::New();
1944 Handle<FunctionTemplate> child = FunctionTemplate::New();
1945 child->Inherit(parent);
1946 AddAccessor(parent, v8_str("age"),
1947 SimpleAccessorGetter, SimpleAccessorSetter);
1948 AddInterceptor(child, EmptyInterceptorGetter, EmptyInterceptorSetter);
1949 LocalContext env;
1950 env->Global()->Set(v8_str("Child"), child->GetFunction());
1951 CompileRun("var child = new Child;"
1952 "child.age = 10;");
1953 ExpectBoolean("child.hasOwnProperty('age')", false);
1954 ExpectInt32("child.age", 10);
1955 ExpectInt32("child.accessor_age", 10);
1956}
1957
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001958
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001959THREADED_TEST(EmptyInterceptorDoesNotShadowJSAccessors) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001960 v8::HandleScope scope(CcTest::isolate());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001961 Handle<FunctionTemplate> parent = FunctionTemplate::New();
1962 Handle<FunctionTemplate> child = FunctionTemplate::New();
1963 child->Inherit(parent);
1964 AddInterceptor(child, EmptyInterceptorGetter, EmptyInterceptorSetter);
1965 LocalContext env;
1966 env->Global()->Set(v8_str("Child"), child->GetFunction());
1967 CompileRun("var child = new Child;"
1968 "var parent = child.__proto__;"
1969 "Object.defineProperty(parent, 'age', "
1970 " {get: function(){ return this.accessor_age; }, "
1971 " set: function(v){ this.accessor_age = v; }, "
1972 " enumerable: true, configurable: true});"
1973 "child.age = 10;");
1974 ExpectBoolean("child.hasOwnProperty('age')", false);
1975 ExpectInt32("child.age", 10);
1976 ExpectInt32("child.accessor_age", 10);
1977}
1978
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001979
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001980THREADED_TEST(EmptyInterceptorDoesNotAffectJSProperties) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001981 v8::HandleScope scope(CcTest::isolate());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001982 Handle<FunctionTemplate> parent = FunctionTemplate::New();
1983 Handle<FunctionTemplate> child = FunctionTemplate::New();
1984 child->Inherit(parent);
1985 AddInterceptor(child, EmptyInterceptorGetter, EmptyInterceptorSetter);
1986 LocalContext env;
1987 env->Global()->Set(v8_str("Child"), child->GetFunction());
1988 CompileRun("var child = new Child;"
1989 "var parent = child.__proto__;"
1990 "parent.name = 'Alice';");
1991 ExpectBoolean("child.hasOwnProperty('name')", false);
1992 ExpectString("child.name", "Alice");
1993 CompileRun("child.name = 'Bob';");
1994 ExpectString("child.name", "Bob");
1995 ExpectBoolean("child.hasOwnProperty('name')", true);
1996 ExpectString("parent.name", "Alice");
1997}
1998
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001999
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002000THREADED_TEST(SwitchFromInterceptorToAccessor) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002001 v8::HandleScope scope(CcTest::isolate());
danno@chromium.orgbf0c8202011-12-27 10:09:42 +00002002 Handle<FunctionTemplate> templ = FunctionTemplate::New();
2003 AddAccessor(templ, v8_str("age"),
2004 SimpleAccessorGetter, SimpleAccessorSetter);
2005 AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
2006 LocalContext env;
2007 env->Global()->Set(v8_str("Obj"), templ->GetFunction());
2008 CompileRun("var obj = new Obj;"
2009 "function setAge(i){ obj.age = i; };"
2010 "for(var i = 0; i <= 10000; i++) setAge(i);");
2011 // All i < 10000 go to the interceptor.
2012 ExpectInt32("obj.interceptor_age", 9999);
2013 // The last i goes to the accessor.
2014 ExpectInt32("obj.accessor_age", 10000);
2015}
2016
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002017
danno@chromium.orgbf0c8202011-12-27 10:09:42 +00002018THREADED_TEST(SwitchFromAccessorToInterceptor) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002019 v8::HandleScope scope(CcTest::isolate());
danno@chromium.orgbf0c8202011-12-27 10:09:42 +00002020 Handle<FunctionTemplate> templ = FunctionTemplate::New();
2021 AddAccessor(templ, v8_str("age"),
2022 SimpleAccessorGetter, SimpleAccessorSetter);
2023 AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
2024 LocalContext env;
2025 env->Global()->Set(v8_str("Obj"), templ->GetFunction());
2026 CompileRun("var obj = new Obj;"
2027 "function setAge(i){ obj.age = i; };"
2028 "for(var i = 20000; i >= 9999; i--) setAge(i);");
2029 // All i >= 10000 go to the accessor.
2030 ExpectInt32("obj.accessor_age", 10000);
2031 // The last i goes to the interceptor.
2032 ExpectInt32("obj.interceptor_age", 9999);
2033}
2034
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002035
danno@chromium.orgbf0c8202011-12-27 10:09:42 +00002036THREADED_TEST(SwitchFromInterceptorToAccessorWithInheritance) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002037 v8::HandleScope scope(CcTest::isolate());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002038 Handle<FunctionTemplate> parent = FunctionTemplate::New();
2039 Handle<FunctionTemplate> child = FunctionTemplate::New();
2040 child->Inherit(parent);
2041 AddAccessor(parent, v8_str("age"),
2042 SimpleAccessorGetter, SimpleAccessorSetter);
2043 AddInterceptor(child, InterceptorGetter, InterceptorSetter);
2044 LocalContext env;
2045 env->Global()->Set(v8_str("Child"), child->GetFunction());
2046 CompileRun("var child = new Child;"
2047 "function setAge(i){ child.age = i; };"
2048 "for(var i = 0; i <= 10000; i++) setAge(i);");
2049 // All i < 10000 go to the interceptor.
2050 ExpectInt32("child.interceptor_age", 9999);
2051 // The last i goes to the accessor.
2052 ExpectInt32("child.accessor_age", 10000);
2053}
2054
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002055
danno@chromium.orgbf0c8202011-12-27 10:09:42 +00002056THREADED_TEST(SwitchFromAccessorToInterceptorWithInheritance) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002057 v8::HandleScope scope(CcTest::isolate());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002058 Handle<FunctionTemplate> parent = FunctionTemplate::New();
2059 Handle<FunctionTemplate> child = FunctionTemplate::New();
2060 child->Inherit(parent);
2061 AddAccessor(parent, v8_str("age"),
2062 SimpleAccessorGetter, SimpleAccessorSetter);
2063 AddInterceptor(child, InterceptorGetter, InterceptorSetter);
2064 LocalContext env;
2065 env->Global()->Set(v8_str("Child"), child->GetFunction());
2066 CompileRun("var child = new Child;"
2067 "function setAge(i){ child.age = i; };"
2068 "for(var i = 20000; i >= 9999; i--) setAge(i);");
2069 // All i >= 10000 go to the accessor.
2070 ExpectInt32("child.accessor_age", 10000);
2071 // The last i goes to the interceptor.
2072 ExpectInt32("child.interceptor_age", 9999);
2073}
2074
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002075
danno@chromium.orgbf0c8202011-12-27 10:09:42 +00002076THREADED_TEST(SwitchFromInterceptorToJSAccessor) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002077 v8::HandleScope scope(CcTest::isolate());
danno@chromium.orgbf0c8202011-12-27 10:09:42 +00002078 Handle<FunctionTemplate> templ = FunctionTemplate::New();
2079 AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
2080 LocalContext env;
2081 env->Global()->Set(v8_str("Obj"), templ->GetFunction());
2082 CompileRun("var obj = new Obj;"
2083 "function setter(i) { this.accessor_age = i; };"
2084 "function getter() { return this.accessor_age; };"
2085 "function setAge(i) { obj.age = i; };"
2086 "Object.defineProperty(obj, 'age', { get:getter, set:setter });"
2087 "for(var i = 0; i <= 10000; i++) setAge(i);");
2088 // All i < 10000 go to the interceptor.
2089 ExpectInt32("obj.interceptor_age", 9999);
2090 // The last i goes to the JavaScript accessor.
2091 ExpectInt32("obj.accessor_age", 10000);
2092 // The installed JavaScript getter is still intact.
2093 // This last part is a regression test for issue 1651 and relies on the fact
2094 // that both interceptor and accessor are being installed on the same object.
2095 ExpectInt32("obj.age", 10000);
2096 ExpectBoolean("obj.hasOwnProperty('age')", true);
2097 ExpectUndefined("Object.getOwnPropertyDescriptor(obj, 'age').value");
2098}
2099
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002100
danno@chromium.orgbf0c8202011-12-27 10:09:42 +00002101THREADED_TEST(SwitchFromJSAccessorToInterceptor) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002102 v8::HandleScope scope(CcTest::isolate());
danno@chromium.orgbf0c8202011-12-27 10:09:42 +00002103 Handle<FunctionTemplate> templ = FunctionTemplate::New();
2104 AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
2105 LocalContext env;
2106 env->Global()->Set(v8_str("Obj"), templ->GetFunction());
2107 CompileRun("var obj = new Obj;"
2108 "function setter(i) { this.accessor_age = i; };"
2109 "function getter() { return this.accessor_age; };"
2110 "function setAge(i) { obj.age = i; };"
2111 "Object.defineProperty(obj, 'age', { get:getter, set:setter });"
2112 "for(var i = 20000; i >= 9999; i--) setAge(i);");
2113 // All i >= 10000 go to the accessor.
2114 ExpectInt32("obj.accessor_age", 10000);
2115 // The last i goes to the interceptor.
2116 ExpectInt32("obj.interceptor_age", 9999);
2117 // The installed JavaScript getter is still intact.
2118 // This last part is a regression test for issue 1651 and relies on the fact
2119 // that both interceptor and accessor are being installed on the same object.
2120 ExpectInt32("obj.age", 10000);
2121 ExpectBoolean("obj.hasOwnProperty('age')", true);
2122 ExpectUndefined("Object.getOwnPropertyDescriptor(obj, 'age').value");
2123}
2124
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002125
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002126THREADED_TEST(SwitchFromInterceptorToProperty) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002127 v8::HandleScope scope(CcTest::isolate());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002128 Handle<FunctionTemplate> parent = FunctionTemplate::New();
2129 Handle<FunctionTemplate> child = FunctionTemplate::New();
2130 child->Inherit(parent);
2131 AddInterceptor(child, InterceptorGetter, InterceptorSetter);
2132 LocalContext env;
2133 env->Global()->Set(v8_str("Child"), child->GetFunction());
2134 CompileRun("var child = new Child;"
2135 "function setAge(i){ child.age = i; };"
2136 "for(var i = 0; i <= 10000; i++) setAge(i);");
2137 // All i < 10000 go to the interceptor.
2138 ExpectInt32("child.interceptor_age", 9999);
2139 // The last i goes to child's own property.
2140 ExpectInt32("child.age", 10000);
2141}
2142
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002143
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002144THREADED_TEST(SwitchFromPropertyToInterceptor) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002145 v8::HandleScope scope(CcTest::isolate());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002146 Handle<FunctionTemplate> parent = FunctionTemplate::New();
2147 Handle<FunctionTemplate> child = FunctionTemplate::New();
2148 child->Inherit(parent);
2149 AddInterceptor(child, InterceptorGetter, InterceptorSetter);
2150 LocalContext env;
2151 env->Global()->Set(v8_str("Child"), child->GetFunction());
2152 CompileRun("var child = new Child;"
2153 "function setAge(i){ child.age = i; };"
2154 "for(var i = 20000; i >= 9999; i--) setAge(i);");
2155 // All i >= 10000 go to child's own property.
2156 ExpectInt32("child.age", 10000);
2157 // The last i goes to the interceptor.
2158 ExpectInt32("child.interceptor_age", 9999);
2159}
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002160
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002161
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002162THREADED_TEST(NamedPropertyHandlerGetter) {
2163 echo_named_call_count = 0;
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002164 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002165 v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
2166 templ->InstanceTemplate()->SetNamedPropertyHandler(EchoNamedProperty,
2167 0, 0, 0, 0,
2168 v8_str("data"));
2169 LocalContext env;
2170 env->Global()->Set(v8_str("obj"),
2171 templ->GetFunction()->NewInstance());
2172 CHECK_EQ(echo_named_call_count, 0);
2173 v8_compile("obj.x")->Run();
2174 CHECK_EQ(echo_named_call_count, 1);
2175 const char* code = "var str = 'oddle'; obj[str] + obj.poddle;";
2176 v8::Handle<Value> str = CompileRun(code);
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00002177 String::Utf8Value value(str);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002178 CHECK_EQ(*value, "oddlepoddle");
2179 // Check default behavior
2180 CHECK_EQ(v8_compile("obj.flob = 10;")->Run()->Int32Value(), 10);
2181 CHECK(v8_compile("'myProperty' in obj")->Run()->BooleanValue());
2182 CHECK(v8_compile("delete obj.myProperty")->Run()->BooleanValue());
2183}
2184
2185
2186int echo_indexed_call_count = 0;
2187
2188
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002189static void EchoIndexedProperty(
2190 uint32_t index,
2191 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002192 ApiTestFuzzer::Fuzz();
2193 CHECK_EQ(v8_num(637), info.Data());
2194 echo_indexed_call_count++;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002195 info.GetReturnValue().Set(v8_num(index));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002196}
2197
2198
2199THREADED_TEST(IndexedPropertyHandlerGetter) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002200 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002201 v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
2202 templ->InstanceTemplate()->SetIndexedPropertyHandler(EchoIndexedProperty,
2203 0, 0, 0, 0,
2204 v8_num(637));
2205 LocalContext env;
2206 env->Global()->Set(v8_str("obj"),
2207 templ->GetFunction()->NewInstance());
2208 Local<Script> script = v8_compile("obj[900]");
2209 CHECK_EQ(script->Run()->Int32Value(), 900);
2210}
2211
2212
2213v8::Handle<v8::Object> bottom;
2214
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002215static void CheckThisIndexedPropertyHandler(
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002216 uint32_t index,
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002217 const v8::PropertyCallbackInfo<v8::Value>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00002218 CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertyHandler));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002219 ApiTestFuzzer::Fuzz();
2220 CHECK(info.This()->Equals(bottom));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002221}
2222
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002223static void CheckThisNamedPropertyHandler(
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002224 Local<String> name,
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002225 const v8::PropertyCallbackInfo<v8::Value>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00002226 CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertyHandler));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002227 ApiTestFuzzer::Fuzz();
2228 CHECK(info.This()->Equals(bottom));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002229}
2230
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002231void CheckThisIndexedPropertySetter(
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002232 uint32_t index,
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002233 Local<Value> value,
2234 const v8::PropertyCallbackInfo<v8::Value>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00002235 CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertySetter));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002236 ApiTestFuzzer::Fuzz();
2237 CHECK(info.This()->Equals(bottom));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002238}
2239
2240
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002241void CheckThisNamedPropertySetter(
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002242 Local<String> property,
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002243 Local<Value> value,
2244 const v8::PropertyCallbackInfo<v8::Value>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00002245 CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertySetter));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002246 ApiTestFuzzer::Fuzz();
2247 CHECK(info.This()->Equals(bottom));
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002248}
2249
2250void CheckThisIndexedPropertyQuery(
2251 uint32_t index,
2252 const v8::PropertyCallbackInfo<v8::Integer>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00002253 CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertyQuery));
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002254 ApiTestFuzzer::Fuzz();
2255 CHECK(info.This()->Equals(bottom));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002256}
2257
2258
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002259void CheckThisNamedPropertyQuery(
2260 Local<String> property,
2261 const v8::PropertyCallbackInfo<v8::Integer>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00002262 CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertyQuery));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002263 ApiTestFuzzer::Fuzz();
2264 CHECK(info.This()->Equals(bottom));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002265}
2266
2267
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002268void CheckThisIndexedPropertyDeleter(
2269 uint32_t index,
2270 const v8::PropertyCallbackInfo<v8::Boolean>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00002271 CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertyDeleter));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002272 ApiTestFuzzer::Fuzz();
2273 CHECK(info.This()->Equals(bottom));
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002274}
2275
2276
2277void CheckThisNamedPropertyDeleter(
2278 Local<String> property,
2279 const v8::PropertyCallbackInfo<v8::Boolean>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00002280 CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertyDeleter));
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002281 ApiTestFuzzer::Fuzz();
2282 CHECK(info.This()->Equals(bottom));
2283}
2284
2285
2286void CheckThisIndexedPropertyEnumerator(
2287 const v8::PropertyCallbackInfo<v8::Array>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00002288 CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertyEnumerator));
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002289 ApiTestFuzzer::Fuzz();
2290 CHECK(info.This()->Equals(bottom));
2291}
2292
2293
2294void CheckThisNamedPropertyEnumerator(
2295 const v8::PropertyCallbackInfo<v8::Array>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00002296 CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertyEnumerator));
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002297 ApiTestFuzzer::Fuzz();
2298 CHECK(info.This()->Equals(bottom));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002299}
2300
2301
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002302THREADED_PROFILED_TEST(PropertyHandlerInPrototype) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002303 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00002304 v8::HandleScope scope(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002305
2306 // Set up a prototype chain with three interceptors.
2307 v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
2308 templ->InstanceTemplate()->SetIndexedPropertyHandler(
2309 CheckThisIndexedPropertyHandler,
2310 CheckThisIndexedPropertySetter,
2311 CheckThisIndexedPropertyQuery,
2312 CheckThisIndexedPropertyDeleter,
2313 CheckThisIndexedPropertyEnumerator);
2314
2315 templ->InstanceTemplate()->SetNamedPropertyHandler(
2316 CheckThisNamedPropertyHandler,
2317 CheckThisNamedPropertySetter,
2318 CheckThisNamedPropertyQuery,
2319 CheckThisNamedPropertyDeleter,
2320 CheckThisNamedPropertyEnumerator);
2321
2322 bottom = templ->GetFunction()->NewInstance();
2323 Local<v8::Object> top = templ->GetFunction()->NewInstance();
2324 Local<v8::Object> middle = templ->GetFunction()->NewInstance();
2325
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +00002326 bottom->SetPrototype(middle);
2327 middle->SetPrototype(top);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002328 env->Global()->Set(v8_str("obj"), bottom);
2329
2330 // Indexed and named get.
2331 Script::Compile(v8_str("obj[0]"))->Run();
2332 Script::Compile(v8_str("obj.x"))->Run();
2333
2334 // Indexed and named set.
2335 Script::Compile(v8_str("obj[1] = 42"))->Run();
2336 Script::Compile(v8_str("obj.y = 42"))->Run();
2337
2338 // Indexed and named query.
2339 Script::Compile(v8_str("0 in obj"))->Run();
2340 Script::Compile(v8_str("'x' in obj"))->Run();
2341
2342 // Indexed and named deleter.
2343 Script::Compile(v8_str("delete obj[0]"))->Run();
2344 Script::Compile(v8_str("delete obj.x"))->Run();
2345
2346 // Enumerators.
2347 Script::Compile(v8_str("for (var p in obj) ;"))->Run();
2348}
2349
2350
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002351static void PrePropertyHandlerGet(
2352 Local<String> key,
2353 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002354 ApiTestFuzzer::Fuzz();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002355 if (v8_str("pre")->Equals(key)) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002356 info.GetReturnValue().Set(v8_str("PrePropertyHandler: pre"));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002357 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002358}
2359
2360
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002361static void PrePropertyHandlerQuery(
2362 Local<String> key,
2363 const v8::PropertyCallbackInfo<v8::Integer>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002364 if (v8_str("pre")->Equals(key)) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002365 info.GetReturnValue().Set(static_cast<int32_t>(v8::None));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002366 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002367}
2368
2369
2370THREADED_TEST(PrePropertyHandler) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002371 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002372 v8::Handle<v8::FunctionTemplate> desc = v8::FunctionTemplate::New();
2373 desc->InstanceTemplate()->SetNamedPropertyHandler(PrePropertyHandlerGet,
2374 0,
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00002375 PrePropertyHandlerQuery);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002376 LocalContext env(NULL, desc->InstanceTemplate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002377 Script::Compile(v8_str(
2378 "var pre = 'Object: pre'; var on = 'Object: on';"))->Run();
2379 v8::Handle<Value> result_pre = Script::Compile(v8_str("pre"))->Run();
2380 CHECK_EQ(v8_str("PrePropertyHandler: pre"), result_pre);
2381 v8::Handle<Value> result_on = Script::Compile(v8_str("on"))->Run();
2382 CHECK_EQ(v8_str("Object: on"), result_on);
2383 v8::Handle<Value> result_post = Script::Compile(v8_str("post"))->Run();
2384 CHECK(result_post.IsEmpty());
2385}
2386
2387
ager@chromium.org870a0b62008-11-04 11:43:05 +00002388THREADED_TEST(UndefinedIsNotEnumerable) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00002389 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00002390 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org870a0b62008-11-04 11:43:05 +00002391 v8::Handle<Value> result = Script::Compile(v8_str(
2392 "this.propertyIsEnumerable(undefined)"))->Run();
2393 CHECK(result->IsFalse());
2394}
2395
2396
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002397v8::Handle<Script> call_recursively_script;
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00002398static const int kTargetRecursionDepth = 200; // near maximum
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002399
2400
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002401static void CallScriptRecursivelyCall(
2402 const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002403 ApiTestFuzzer::Fuzz();
2404 int depth = args.This()->Get(v8_str("depth"))->Int32Value();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002405 if (depth == kTargetRecursionDepth) return;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002406 args.This()->Set(v8_str("depth"), v8::Integer::New(depth + 1));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002407 args.GetReturnValue().Set(call_recursively_script->Run());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002408}
2409
2410
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002411static void CallFunctionRecursivelyCall(
2412 const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002413 ApiTestFuzzer::Fuzz();
2414 int depth = args.This()->Get(v8_str("depth"))->Int32Value();
2415 if (depth == kTargetRecursionDepth) {
2416 printf("[depth = %d]\n", depth);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002417 return;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002418 }
2419 args.This()->Set(v8_str("depth"), v8::Integer::New(depth + 1));
2420 v8::Handle<Value> function =
2421 args.This()->Get(v8_str("callFunctionRecursively"));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002422 args.GetReturnValue().Set(
2423 function.As<Function>()->Call(args.This(), 0, NULL));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002424}
2425
2426
2427THREADED_TEST(DeepCrossLanguageRecursion) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002428 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002429 v8::Handle<v8::ObjectTemplate> global = ObjectTemplate::New();
2430 global->Set(v8_str("callScriptRecursively"),
2431 v8::FunctionTemplate::New(CallScriptRecursivelyCall));
2432 global->Set(v8_str("callFunctionRecursively"),
2433 v8::FunctionTemplate::New(CallFunctionRecursivelyCall));
2434 LocalContext env(NULL, global);
2435
2436 env->Global()->Set(v8_str("depth"), v8::Integer::New(0));
2437 call_recursively_script = v8_compile("callScriptRecursively()");
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00002438 call_recursively_script->Run();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002439 call_recursively_script = v8::Handle<Script>();
2440
2441 env->Global()->Set(v8_str("depth"), v8::Integer::New(0));
2442 Script::Compile(v8_str("callFunctionRecursively()"))->Run();
2443}
2444
2445
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002446static void ThrowingPropertyHandlerGet(
2447 Local<String> key,
2448 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002449 ApiTestFuzzer::Fuzz();
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00002450 info.GetReturnValue().Set(info.GetIsolate()->ThrowException(key));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002451}
2452
2453
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002454static void ThrowingPropertyHandlerSet(
2455 Local<String> key,
2456 Local<Value>,
2457 const v8::PropertyCallbackInfo<v8::Value>& info) {
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00002458 info.GetIsolate()->ThrowException(key);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002459 info.GetReturnValue().SetUndefined(); // not the same as empty handle
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002460}
2461
2462
2463THREADED_TEST(CallbackExceptionRegression) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002464 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002465 v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
2466 obj->SetNamedPropertyHandler(ThrowingPropertyHandlerGet,
2467 ThrowingPropertyHandlerSet);
2468 LocalContext env;
2469 env->Global()->Set(v8_str("obj"), obj->NewInstance());
2470 v8::Handle<Value> otto = Script::Compile(v8_str(
2471 "try { with (obj) { otto; } } catch (e) { e; }"))->Run();
2472 CHECK_EQ(v8_str("otto"), otto);
2473 v8::Handle<Value> netto = Script::Compile(v8_str(
2474 "try { with (obj) { netto = 4; } } catch (e) { e; }"))->Run();
2475 CHECK_EQ(v8_str("netto"), netto);
2476}
2477
2478
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002479THREADED_TEST(FunctionPrototype) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002480 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002481 Local<v8::FunctionTemplate> Foo = v8::FunctionTemplate::New();
2482 Foo->PrototypeTemplate()->Set(v8_str("plak"), v8_num(321));
2483 LocalContext env;
2484 env->Global()->Set(v8_str("Foo"), Foo->GetFunction());
2485 Local<Script> script = Script::Compile(v8_str("Foo.prototype.plak"));
2486 CHECK_EQ(script->Run()->Int32Value(), 321);
2487}
2488
2489
2490THREADED_TEST(InternalFields) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002491 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00002492 v8::HandleScope scope(env->GetIsolate());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002493
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002494 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
2495 Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
2496 instance_templ->SetInternalFieldCount(1);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002497 Local<v8::Object> obj = templ->GetFunction()->NewInstance();
2498 CHECK_EQ(1, obj->InternalFieldCount());
2499 CHECK(obj->GetInternalField(0)->IsUndefined());
2500 obj->SetInternalField(0, v8_num(17));
2501 CHECK_EQ(17, obj->GetInternalField(0)->Int32Value());
2502}
2503
2504
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002505THREADED_TEST(GlobalObjectInternalFields) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002506 v8::HandleScope scope(CcTest::isolate());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002507 Local<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
2508 global_template->SetInternalFieldCount(1);
2509 LocalContext env(NULL, global_template);
2510 v8::Handle<v8::Object> global_proxy = env->Global();
2511 v8::Handle<v8::Object> global = global_proxy->GetPrototype().As<v8::Object>();
2512 CHECK_EQ(1, global->InternalFieldCount());
2513 CHECK(global->GetInternalField(0)->IsUndefined());
2514 global->SetInternalField(0, v8_num(17));
2515 CHECK_EQ(17, global->GetInternalField(0)->Int32Value());
2516}
2517
2518
danno@chromium.org169691d2013-07-15 08:01:13 +00002519THREADED_TEST(GlobalObjectHasRealIndexedProperty) {
2520 LocalContext env;
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002521 v8::HandleScope scope(CcTest::isolate());
danno@chromium.org169691d2013-07-15 08:01:13 +00002522
2523 v8::Local<v8::Object> global = env->Global();
2524 global->Set(0, v8::String::New("value"));
2525 CHECK(global->HasRealIndexedProperty(0));
2526}
2527
2528
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002529static void CheckAlignedPointerInInternalField(Handle<v8::Object> obj,
2530 void* value) {
2531 CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(value) & 0x1));
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00002532 obj->SetAlignedPointerInInternalField(0, value);
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002533 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00002534 CHECK_EQ(value, obj->GetAlignedPointerFromInternalField(0));
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002535}
2536
2537
2538THREADED_TEST(InternalFieldsAlignedPointers) {
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002539 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00002540 v8::HandleScope scope(env->GetIsolate());
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002541
2542 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
2543 Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
2544 instance_templ->SetInternalFieldCount(1);
2545 Local<v8::Object> obj = templ->GetFunction()->NewInstance();
2546 CHECK_EQ(1, obj->InternalFieldCount());
2547
2548 CheckAlignedPointerInInternalField(obj, NULL);
2549
2550 int* heap_allocated = new int[100];
2551 CheckAlignedPointerInInternalField(obj, heap_allocated);
2552 delete[] heap_allocated;
2553
2554 int stack_allocated[100];
2555 CheckAlignedPointerInInternalField(obj, stack_allocated);
2556
2557 void* huge = reinterpret_cast<void*>(~static_cast<uintptr_t>(1));
2558 CheckAlignedPointerInInternalField(obj, huge);
2559}
2560
2561
2562static void CheckAlignedPointerInEmbedderData(LocalContext* env,
2563 int index,
2564 void* value) {
2565 CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(value) & 0x1));
2566 (*env)->SetAlignedPointerInEmbedderData(index, value);
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002567 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002568 CHECK_EQ(value, (*env)->GetAlignedPointerFromEmbedderData(index));
2569}
2570
2571
2572static void* AlignedTestPointer(int i) {
2573 return reinterpret_cast<void*>(i * 1234);
2574}
2575
2576
2577THREADED_TEST(EmbedderDataAlignedPointers) {
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002578 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00002579 v8::HandleScope scope(env->GetIsolate());
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002580
2581 CheckAlignedPointerInEmbedderData(&env, 0, NULL);
2582
2583 int* heap_allocated = new int[100];
2584 CheckAlignedPointerInEmbedderData(&env, 1, heap_allocated);
2585 delete[] heap_allocated;
2586
2587 int stack_allocated[100];
2588 CheckAlignedPointerInEmbedderData(&env, 2, stack_allocated);
2589
2590 void* huge = reinterpret_cast<void*>(~static_cast<uintptr_t>(1));
2591 CheckAlignedPointerInEmbedderData(&env, 3, huge);
2592
2593 // Test growing of the embedder data's backing store.
2594 for (int i = 0; i < 100; i++) {
2595 env->SetAlignedPointerInEmbedderData(i, AlignedTestPointer(i));
2596 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002597 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002598 for (int i = 0; i < 100; i++) {
2599 CHECK_EQ(AlignedTestPointer(i), env->GetAlignedPointerFromEmbedderData(i));
2600 }
2601}
2602
2603
2604static void CheckEmbedderData(LocalContext* env,
2605 int index,
2606 v8::Handle<Value> data) {
2607 (*env)->SetEmbedderData(index, data);
2608 CHECK((*env)->GetEmbedderData(index)->StrictEquals(data));
2609}
2610
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002611
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002612THREADED_TEST(EmbedderData) {
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002613 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00002614 v8::HandleScope scope(env->GetIsolate());
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002615
2616 CheckEmbedderData(&env, 3, v8::String::New("The quick brown fox jumps"));
2617 CheckEmbedderData(&env, 2, v8::String::New("over the lazy dog."));
2618 CheckEmbedderData(&env, 1, v8::Number::New(1.2345));
2619 CheckEmbedderData(&env, 0, v8::Boolean::New(true));
2620}
2621
2622
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002623THREADED_TEST(IdentityHash) {
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002624 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00002625 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002626
2627 // Ensure that the test starts with an fresh heap to test whether the hash
2628 // code is based on the address.
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002629 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002630 Local<v8::Object> obj = v8::Object::New();
2631 int hash = obj->GetIdentityHash();
2632 int hash1 = obj->GetIdentityHash();
2633 CHECK_EQ(hash, hash1);
2634 int hash2 = v8::Object::New()->GetIdentityHash();
2635 // Since the identity hash is essentially a random number two consecutive
2636 // objects should not be assigned the same hash code. If the test below fails
2637 // the random number generator should be evaluated.
2638 CHECK_NE(hash, hash2);
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002639 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002640 int hash3 = v8::Object::New()->GetIdentityHash();
2641 // Make sure that the identity hash is not based on the initial address of
2642 // the object alone. If the test below fails the random number generator
2643 // should be evaluated.
2644 CHECK_NE(hash, hash3);
2645 int hash4 = obj->GetIdentityHash();
2646 CHECK_EQ(hash, hash4);
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002647
2648 // Check identity hashes behaviour in the presence of JS accessors.
2649 // Put a getter for 'v8::IdentityHash' on the Object's prototype:
2650 {
2651 CompileRun("Object.prototype['v8::IdentityHash'] = 42;\n");
2652 Local<v8::Object> o1 = v8::Object::New();
2653 Local<v8::Object> o2 = v8::Object::New();
2654 CHECK_NE(o1->GetIdentityHash(), o2->GetIdentityHash());
2655 }
2656 {
2657 CompileRun(
2658 "function cnst() { return 42; };\n"
2659 "Object.prototype.__defineGetter__('v8::IdentityHash', cnst);\n");
2660 Local<v8::Object> o1 = v8::Object::New();
2661 Local<v8::Object> o2 = v8::Object::New();
2662 CHECK_NE(o1->GetIdentityHash(), o2->GetIdentityHash());
2663 }
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002664}
2665
2666
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002667THREADED_TEST(SymbolProperties) {
2668 i::FLAG_harmony_symbols = true;
2669
2670 LocalContext env;
2671 v8::Isolate* isolate = env->GetIsolate();
2672 v8::HandleScope scope(isolate);
2673
2674 v8::Local<v8::Object> obj = v8::Object::New();
2675 v8::Local<v8::Symbol> sym1 = v8::Symbol::New(isolate);
2676 v8::Local<v8::Symbol> sym2 = v8::Symbol::New(isolate, "my-symbol");
2677
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002678 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002679
2680 // Check basic symbol functionality.
2681 CHECK(sym1->IsSymbol());
2682 CHECK(sym2->IsSymbol());
2683 CHECK(!obj->IsSymbol());
2684
2685 CHECK(sym1->Equals(sym1));
2686 CHECK(sym2->Equals(sym2));
2687 CHECK(!sym1->Equals(sym2));
2688 CHECK(!sym2->Equals(sym1));
2689 CHECK(sym1->StrictEquals(sym1));
2690 CHECK(sym2->StrictEquals(sym2));
2691 CHECK(!sym1->StrictEquals(sym2));
2692 CHECK(!sym2->StrictEquals(sym1));
2693
2694 CHECK(sym2->Name()->Equals(v8::String::New("my-symbol")));
2695
2696 v8::Local<v8::Value> sym_val = sym2;
2697 CHECK(sym_val->IsSymbol());
2698 CHECK(sym_val->Equals(sym2));
2699 CHECK(sym_val->StrictEquals(sym2));
2700 CHECK(v8::Symbol::Cast(*sym_val)->Equals(sym2));
2701
2702 v8::Local<v8::Value> sym_obj = v8::SymbolObject::New(isolate, sym2);
2703 CHECK(sym_obj->IsSymbolObject());
2704 CHECK(!sym2->IsSymbolObject());
2705 CHECK(!obj->IsSymbolObject());
2706 CHECK(sym_obj->Equals(sym2));
2707 CHECK(!sym_obj->StrictEquals(sym2));
2708 CHECK(v8::SymbolObject::Cast(*sym_obj)->Equals(sym_obj));
danno@chromium.orgd3c42102013-08-01 16:58:23 +00002709 CHECK(v8::SymbolObject::Cast(*sym_obj)->ValueOf()->Equals(sym2));
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002710
2711 // Make sure delete of a non-existent symbol property works.
2712 CHECK(obj->Delete(sym1));
2713 CHECK(!obj->Has(sym1));
2714
2715 CHECK(obj->Set(sym1, v8::Integer::New(1503)));
2716 CHECK(obj->Has(sym1));
2717 CHECK_EQ(1503, obj->Get(sym1)->Int32Value());
2718 CHECK(obj->Set(sym1, v8::Integer::New(2002)));
2719 CHECK(obj->Has(sym1));
2720 CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
2721 CHECK_EQ(v8::None, obj->GetPropertyAttributes(sym1));
2722
2723 CHECK_EQ(0, obj->GetOwnPropertyNames()->Length());
2724 int num_props = obj->GetPropertyNames()->Length();
2725 CHECK(obj->Set(v8::String::New("bla"), v8::Integer::New(20)));
2726 CHECK_EQ(1, obj->GetOwnPropertyNames()->Length());
2727 CHECK_EQ(num_props + 1, obj->GetPropertyNames()->Length());
2728
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002729 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002730
2731 // Add another property and delete it afterwards to force the object in
2732 // slow case.
2733 CHECK(obj->Set(sym2, v8::Integer::New(2008)));
2734 CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
2735 CHECK_EQ(2008, obj->Get(sym2)->Int32Value());
2736 CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
2737 CHECK_EQ(1, obj->GetOwnPropertyNames()->Length());
2738
2739 CHECK(obj->Has(sym1));
2740 CHECK(obj->Has(sym2));
2741 CHECK(obj->Delete(sym2));
2742 CHECK(obj->Has(sym1));
2743 CHECK(!obj->Has(sym2));
2744 CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
2745 CHECK_EQ(1, obj->GetOwnPropertyNames()->Length());
2746}
2747
2748
ulan@chromium.org837a67e2013-06-11 15:39:48 +00002749class ScopedArrayBufferContents {
2750 public:
2751 explicit ScopedArrayBufferContents(
2752 const v8::ArrayBuffer::Contents& contents)
2753 : contents_(contents) {}
2754 ~ScopedArrayBufferContents() { free(contents_.Data()); }
2755 void* Data() const { return contents_.Data(); }
2756 size_t ByteLength() const { return contents_.ByteLength(); }
2757 private:
2758 const v8::ArrayBuffer::Contents contents_;
2759};
2760
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002761template <typename T>
2762static void CheckInternalFieldsAreZero(v8::Handle<T> value) {
2763 CHECK_EQ(T::kInternalFieldCount, value->InternalFieldCount());
2764 for (int i = 0; i < value->InternalFieldCount(); i++) {
2765 CHECK_EQ(0, value->GetInternalField(i)->Int32Value());
2766 }
2767}
2768
ulan@chromium.org837a67e2013-06-11 15:39:48 +00002769
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002770THREADED_TEST(ArrayBuffer_ApiInternalToExternal) {
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002771 LocalContext env;
2772 v8::Isolate* isolate = env->GetIsolate();
2773 v8::HandleScope handle_scope(isolate);
2774
2775 Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(1024);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002776 CheckInternalFieldsAreZero(ab);
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002777 CHECK_EQ(1024, static_cast<int>(ab->ByteLength()));
2778 CHECK(!ab->IsExternal());
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002779 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002780
ulan@chromium.org837a67e2013-06-11 15:39:48 +00002781 ScopedArrayBufferContents ab_contents(ab->Externalize());
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002782 CHECK(ab->IsExternal());
2783
2784 CHECK_EQ(1024, static_cast<int>(ab_contents.ByteLength()));
2785 uint8_t* data = static_cast<uint8_t*>(ab_contents.Data());
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002786 ASSERT(data != NULL);
2787 env->Global()->Set(v8_str("ab"), ab);
2788
2789 v8::Handle<v8::Value> result = CompileRun("ab.byteLength");
2790 CHECK_EQ(1024, result->Int32Value());
2791
danno@chromium.orgf005df62013-04-30 16:36:45 +00002792 result = CompileRun("var u8 = new Uint8Array(ab);"
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002793 "u8[0] = 0xFF;"
2794 "u8[1] = 0xAA;"
2795 "u8.length");
2796 CHECK_EQ(1024, result->Int32Value());
2797 CHECK_EQ(0xFF, data[0]);
2798 CHECK_EQ(0xAA, data[1]);
2799 data[0] = 0xCC;
2800 data[1] = 0x11;
2801 result = CompileRun("u8[0] + u8[1]");
2802 CHECK_EQ(0xDD, result->Int32Value());
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002803}
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002804
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002805
2806THREADED_TEST(ArrayBuffer_JSInternalToExternal) {
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002807 LocalContext env;
2808 v8::Isolate* isolate = env->GetIsolate();
2809 v8::HandleScope handle_scope(isolate);
2810
2811
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00002812 v8::Local<v8::Value> result =
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002813 CompileRun("var ab1 = new ArrayBuffer(2);"
2814 "var u8_a = new Uint8Array(ab1);"
2815 "u8_a[0] = 0xAA;"
2816 "u8_a[1] = 0xFF; u8_a.buffer");
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00002817 Local<v8::ArrayBuffer> ab1 = Local<v8::ArrayBuffer>::Cast(result);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002818 CheckInternalFieldsAreZero(ab1);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002819 CHECK_EQ(2, static_cast<int>(ab1->ByteLength()));
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002820 CHECK(!ab1->IsExternal());
ulan@chromium.org837a67e2013-06-11 15:39:48 +00002821 ScopedArrayBufferContents ab1_contents(ab1->Externalize());
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002822 CHECK(ab1->IsExternal());
2823
2824 result = CompileRun("ab1.byteLength");
2825 CHECK_EQ(2, result->Int32Value());
2826 result = CompileRun("u8_a[0]");
2827 CHECK_EQ(0xAA, result->Int32Value());
2828 result = CompileRun("u8_a[1]");
2829 CHECK_EQ(0xFF, result->Int32Value());
2830 result = CompileRun("var u8_b = new Uint8Array(ab1);"
2831 "u8_b[0] = 0xBB;"
2832 "u8_a[0]");
2833 CHECK_EQ(0xBB, result->Int32Value());
2834 result = CompileRun("u8_b[1]");
2835 CHECK_EQ(0xFF, result->Int32Value());
2836
2837 CHECK_EQ(2, static_cast<int>(ab1_contents.ByteLength()));
2838 uint8_t* ab1_data = static_cast<uint8_t*>(ab1_contents.Data());
2839 CHECK_EQ(0xBB, ab1_data[0]);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002840 CHECK_EQ(0xFF, ab1_data[1]);
2841 ab1_data[0] = 0xCC;
2842 ab1_data[1] = 0x11;
2843 result = CompileRun("u8_a[0] + u8_a[1]");
2844 CHECK_EQ(0xDD, result->Int32Value());
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002845}
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002846
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002847
2848THREADED_TEST(ArrayBuffer_External) {
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002849 LocalContext env;
2850 v8::Isolate* isolate = env->GetIsolate();
2851 v8::HandleScope handle_scope(isolate);
2852
2853 i::ScopedVector<uint8_t> my_data(100);
2854 memset(my_data.start(), 0, 100);
2855 Local<v8::ArrayBuffer> ab3 = v8::ArrayBuffer::New(my_data.start(), 100);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002856 CheckInternalFieldsAreZero(ab3);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002857 CHECK_EQ(100, static_cast<int>(ab3->ByteLength()));
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002858 CHECK(ab3->IsExternal());
2859
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002860 env->Global()->Set(v8_str("ab3"), ab3);
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002861
2862 v8::Handle<v8::Value> result = CompileRun("ab3.byteLength");
2863 CHECK_EQ(100, result->Int32Value());
2864
danno@chromium.orgf005df62013-04-30 16:36:45 +00002865 result = CompileRun("var u8_b = new Uint8Array(ab3);"
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002866 "u8_b[0] = 0xBB;"
2867 "u8_b[1] = 0xCC;"
2868 "u8_b.length");
2869 CHECK_EQ(100, result->Int32Value());
2870 CHECK_EQ(0xBB, my_data[0]);
2871 CHECK_EQ(0xCC, my_data[1]);
2872 my_data[0] = 0xCC;
2873 my_data[1] = 0x11;
2874 result = CompileRun("u8_b[0] + u8_b[1]");
2875 CHECK_EQ(0xDD, result->Int32Value());
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002876}
2877
2878
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002879static void CheckDataViewIsNeutered(v8::Handle<v8::DataView> dv) {
2880 CHECK_EQ(0, static_cast<int>(dv->ByteLength()));
2881 CHECK_EQ(0, static_cast<int>(dv->ByteOffset()));
2882}
2883
2884
danno@chromium.org1fd77d52013-06-07 16:01:45 +00002885static void CheckIsNeutered(v8::Handle<v8::TypedArray> ta) {
2886 CHECK_EQ(0, static_cast<int>(ta->ByteLength()));
2887 CHECK_EQ(0, static_cast<int>(ta->Length()));
2888 CHECK_EQ(0, static_cast<int>(ta->ByteOffset()));
2889}
2890
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002891
2892static void CheckIsTypedArrayVarNeutered(const char* name) {
2893 i::ScopedVector<char> source(1024);
2894 i::OS::SNPrintF(source,
2895 "%s.byteLength == 0 && %s.byteOffset == 0 && %s.length == 0",
2896 name, name, name);
2897 CHECK(CompileRun(source.start())->IsTrue());
2898 v8::Handle<v8::TypedArray> ta =
2899 v8::Handle<v8::TypedArray>::Cast(CompileRun(name));
2900 CheckIsNeutered(ta);
2901}
2902
2903
danno@chromium.org1fd77d52013-06-07 16:01:45 +00002904template <typename TypedArray, int kElementSize>
2905static Handle<TypedArray> CreateAndCheck(Handle<v8::ArrayBuffer> ab,
2906 int byteOffset,
2907 int length) {
2908 v8::Handle<TypedArray> ta = TypedArray::New(ab, byteOffset, length);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002909 CheckInternalFieldsAreZero<v8::ArrayBufferView>(ta);
danno@chromium.org1fd77d52013-06-07 16:01:45 +00002910 CHECK_EQ(byteOffset, static_cast<int>(ta->ByteOffset()));
2911 CHECK_EQ(length, static_cast<int>(ta->Length()));
2912 CHECK_EQ(length * kElementSize, static_cast<int>(ta->ByteLength()));
2913 return ta;
2914}
2915
2916
2917THREADED_TEST(ArrayBuffer_NeuteringApi) {
2918 LocalContext env;
2919 v8::Isolate* isolate = env->GetIsolate();
2920 v8::HandleScope handle_scope(isolate);
2921
2922 v8::Handle<v8::ArrayBuffer> buffer = v8::ArrayBuffer::New(1024);
2923
2924 v8::Handle<v8::Uint8Array> u8a =
2925 CreateAndCheck<v8::Uint8Array, 1>(buffer, 1, 1023);
2926 v8::Handle<v8::Uint8ClampedArray> u8c =
2927 CreateAndCheck<v8::Uint8ClampedArray, 1>(buffer, 1, 1023);
2928 v8::Handle<v8::Int8Array> i8a =
2929 CreateAndCheck<v8::Int8Array, 1>(buffer, 1, 1023);
2930
2931 v8::Handle<v8::Uint16Array> u16a =
2932 CreateAndCheck<v8::Uint16Array, 2>(buffer, 2, 511);
2933 v8::Handle<v8::Int16Array> i16a =
2934 CreateAndCheck<v8::Int16Array, 2>(buffer, 2, 511);
2935
2936 v8::Handle<v8::Uint32Array> u32a =
2937 CreateAndCheck<v8::Uint32Array, 4>(buffer, 4, 255);
2938 v8::Handle<v8::Int32Array> i32a =
2939 CreateAndCheck<v8::Int32Array, 4>(buffer, 4, 255);
2940
2941 v8::Handle<v8::Float32Array> f32a =
2942 CreateAndCheck<v8::Float32Array, 4>(buffer, 4, 255);
2943 v8::Handle<v8::Float64Array> f64a =
2944 CreateAndCheck<v8::Float64Array, 8>(buffer, 8, 127);
2945
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002946 v8::Handle<v8::DataView> dv = v8::DataView::New(buffer, 1, 1023);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002947 CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002948 CHECK_EQ(1, static_cast<int>(dv->ByteOffset()));
2949 CHECK_EQ(1023, static_cast<int>(dv->ByteLength()));
2950
ulan@chromium.org837a67e2013-06-11 15:39:48 +00002951 ScopedArrayBufferContents contents(buffer->Externalize());
danno@chromium.org1fd77d52013-06-07 16:01:45 +00002952 buffer->Neuter();
2953 CHECK_EQ(0, static_cast<int>(buffer->ByteLength()));
2954 CheckIsNeutered(u8a);
2955 CheckIsNeutered(u8c);
2956 CheckIsNeutered(i8a);
2957 CheckIsNeutered(u16a);
2958 CheckIsNeutered(i16a);
2959 CheckIsNeutered(u32a);
2960 CheckIsNeutered(i32a);
2961 CheckIsNeutered(f32a);
2962 CheckIsNeutered(f64a);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002963 CheckDataViewIsNeutered(dv);
danno@chromium.org1fd77d52013-06-07 16:01:45 +00002964}
2965
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002966
danno@chromium.org1fd77d52013-06-07 16:01:45 +00002967THREADED_TEST(ArrayBuffer_NeuteringScript) {
2968 LocalContext env;
2969 v8::Isolate* isolate = env->GetIsolate();
2970 v8::HandleScope handle_scope(isolate);
2971
2972 CompileRun(
2973 "var ab = new ArrayBuffer(1024);"
2974 "var u8a = new Uint8Array(ab, 1, 1023);"
2975 "var u8c = new Uint8ClampedArray(ab, 1, 1023);"
2976 "var i8a = new Int8Array(ab, 1, 1023);"
2977 "var u16a = new Uint16Array(ab, 2, 511);"
2978 "var i16a = new Int16Array(ab, 2, 511);"
2979 "var u32a = new Uint32Array(ab, 4, 255);"
2980 "var i32a = new Int32Array(ab, 4, 255);"
2981 "var f32a = new Float32Array(ab, 4, 255);"
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002982 "var f64a = new Float64Array(ab, 8, 127);"
2983 "var dv = new DataView(ab, 1, 1023);");
danno@chromium.org1fd77d52013-06-07 16:01:45 +00002984
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00002985 v8::Handle<v8::ArrayBuffer> ab =
2986 Local<v8::ArrayBuffer>::Cast(CompileRun("ab"));
danno@chromium.org1fd77d52013-06-07 16:01:45 +00002987
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002988 v8::Handle<v8::DataView> dv =
2989 v8::Handle<v8::DataView>::Cast(CompileRun("dv"));
danno@chromium.org1fd77d52013-06-07 16:01:45 +00002990
ulan@chromium.org837a67e2013-06-11 15:39:48 +00002991 ScopedArrayBufferContents contents(ab->Externalize());
danno@chromium.org1fd77d52013-06-07 16:01:45 +00002992 ab->Neuter();
2993 CHECK_EQ(0, static_cast<int>(ab->ByteLength()));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002994 CHECK_EQ(0, CompileRun("ab.byteLength")->Int32Value());
2995
2996 CheckIsTypedArrayVarNeutered("u8a");
2997 CheckIsTypedArrayVarNeutered("u8c");
2998 CheckIsTypedArrayVarNeutered("i8a");
2999 CheckIsTypedArrayVarNeutered("u16a");
3000 CheckIsTypedArrayVarNeutered("i16a");
3001 CheckIsTypedArrayVarNeutered("u32a");
3002 CheckIsTypedArrayVarNeutered("i32a");
3003 CheckIsTypedArrayVarNeutered("f32a");
3004 CheckIsTypedArrayVarNeutered("f64a");
3005
3006 CHECK(CompileRun("dv.byteLength == 0 && dv.byteOffset == 0")->IsTrue());
3007 CheckDataViewIsNeutered(dv);
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003008}
3009
3010
3011
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003012THREADED_TEST(HiddenProperties) {
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003013 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003014 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003015
3016 v8::Local<v8::Object> obj = v8::Object::New();
3017 v8::Local<v8::String> key = v8_str("api-test::hidden-key");
3018 v8::Local<v8::String> empty = v8_str("");
3019 v8::Local<v8::String> prop_name = v8_str("prop_name");
3020
machenbach@chromium.org528ce022013-09-23 14:09:36 +00003021 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003022
kasperl@chromium.orgacae3782009-04-11 09:17:08 +00003023 // Make sure delete of a non-existent hidden value works
3024 CHECK(obj->DeleteHiddenValue(key));
3025
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003026 CHECK(obj->SetHiddenValue(key, v8::Integer::New(1503)));
3027 CHECK_EQ(1503, obj->GetHiddenValue(key)->Int32Value());
3028 CHECK(obj->SetHiddenValue(key, v8::Integer::New(2002)));
3029 CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
3030
machenbach@chromium.org528ce022013-09-23 14:09:36 +00003031 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003032
3033 // Make sure we do not find the hidden property.
3034 CHECK(!obj->Has(empty));
3035 CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
3036 CHECK(obj->Get(empty)->IsUndefined());
3037 CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
3038 CHECK(obj->Set(empty, v8::Integer::New(2003)));
3039 CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
3040 CHECK_EQ(2003, obj->Get(empty)->Int32Value());
3041
machenbach@chromium.org528ce022013-09-23 14:09:36 +00003042 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003043
3044 // Add another property and delete it afterwards to force the object in
3045 // slow case.
3046 CHECK(obj->Set(prop_name, v8::Integer::New(2008)));
3047 CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
3048 CHECK_EQ(2008, obj->Get(prop_name)->Int32Value());
3049 CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
3050 CHECK(obj->Delete(prop_name));
3051 CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
3052
machenbach@chromium.org528ce022013-09-23 14:09:36 +00003053 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003054
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00003055 CHECK(obj->SetHiddenValue(key, Handle<Value>()));
3056 CHECK(obj->GetHiddenValue(key).IsEmpty());
3057
3058 CHECK(obj->SetHiddenValue(key, v8::Integer::New(2002)));
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003059 CHECK(obj->DeleteHiddenValue(key));
3060 CHECK(obj->GetHiddenValue(key).IsEmpty());
3061}
3062
3063
ricow@chromium.org9fe9cdf2011-09-27 08:04:16 +00003064THREADED_TEST(Regress97784) {
3065 // Regression test for crbug.com/97784
3066 // Messing with the Object.prototype should not have effect on
3067 // hidden properties.
ricow@chromium.org9fe9cdf2011-09-27 08:04:16 +00003068 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003069 v8::HandleScope scope(env->GetIsolate());
ricow@chromium.org9fe9cdf2011-09-27 08:04:16 +00003070
3071 v8::Local<v8::Object> obj = v8::Object::New();
3072 v8::Local<v8::String> key = v8_str("hidden");
3073
3074 CompileRun(
3075 "set_called = false;"
3076 "Object.defineProperty("
3077 " Object.prototype,"
3078 " 'hidden',"
3079 " {get: function() { return 45; },"
3080 " set: function() { set_called = true; }})");
3081
3082 CHECK(obj->GetHiddenValue(key).IsEmpty());
3083 // Make sure that the getter and setter from Object.prototype is not invoked.
3084 // If it did we would have full access to the hidden properties in
3085 // the accessor.
3086 CHECK(obj->SetHiddenValue(key, v8::Integer::New(42)));
3087 ExpectFalse("set_called");
3088 CHECK_EQ(42, obj->GetHiddenValue(key)->Int32Value());
3089}
3090
3091
ager@chromium.orgc4c92722009-11-18 14:12:51 +00003092static bool interceptor_for_hidden_properties_called;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003093static void InterceptorForHiddenProperties(
3094 Local<String> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.orgc4c92722009-11-18 14:12:51 +00003095 interceptor_for_hidden_properties_called = true;
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00003096}
3097
3098
3099THREADED_TEST(HiddenPropertiesWithInterceptors) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00003100 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003101 v8::HandleScope scope(context->GetIsolate());
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00003102
ager@chromium.orgc4c92722009-11-18 14:12:51 +00003103 interceptor_for_hidden_properties_called = false;
3104
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00003105 v8::Local<v8::String> key = v8_str("api-test::hidden-key");
3106
3107 // Associate an interceptor with an object and start setting hidden values.
3108 Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
3109 Local<v8::ObjectTemplate> instance_templ = fun_templ->InstanceTemplate();
3110 instance_templ->SetNamedPropertyHandler(InterceptorForHiddenProperties);
3111 Local<v8::Function> function = fun_templ->GetFunction();
3112 Local<v8::Object> obj = function->NewInstance();
3113 CHECK(obj->SetHiddenValue(key, v8::Integer::New(2302)));
3114 CHECK_EQ(2302, obj->GetHiddenValue(key)->Int32Value());
ager@chromium.orgc4c92722009-11-18 14:12:51 +00003115 CHECK(!interceptor_for_hidden_properties_called);
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00003116}
3117
3118
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003119THREADED_TEST(External) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00003120 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003121 int x = 3;
3122 Local<v8::External> ext = v8::External::New(&x);
3123 LocalContext env;
3124 env->Global()->Set(v8_str("ext"), ext);
3125 Local<Value> reext_obj = Script::Compile(v8_str("this.ext"))->Run();
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00003126 v8::Handle<v8::External> reext = reext_obj.As<v8::External>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003127 int* ptr = static_cast<int*>(reext->Value());
3128 CHECK_EQ(x, 3);
3129 *ptr = 10;
3130 CHECK_EQ(x, 10);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00003131
3132 // Make sure unaligned pointers are wrapped properly.
3133 char* data = i::StrDup("0123456789");
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00003134 Local<v8::Value> zero = v8::External::New(&data[0]);
3135 Local<v8::Value> one = v8::External::New(&data[1]);
3136 Local<v8::Value> two = v8::External::New(&data[2]);
3137 Local<v8::Value> three = v8::External::New(&data[3]);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00003138
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00003139 char* char_ptr = reinterpret_cast<char*>(v8::External::Cast(*zero)->Value());
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00003140 CHECK_EQ('0', *char_ptr);
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00003141 char_ptr = reinterpret_cast<char*>(v8::External::Cast(*one)->Value());
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00003142 CHECK_EQ('1', *char_ptr);
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00003143 char_ptr = reinterpret_cast<char*>(v8::External::Cast(*two)->Value());
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00003144 CHECK_EQ('2', *char_ptr);
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00003145 char_ptr = reinterpret_cast<char*>(v8::External::Cast(*three)->Value());
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00003146 CHECK_EQ('3', *char_ptr);
3147 i::DeleteArray(data);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003148}
3149
3150
3151THREADED_TEST(GlobalHandle) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00003152 v8::Isolate* isolate = CcTest::isolate();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003153 v8::Persistent<String> global;
3154 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003155 v8::HandleScope scope(isolate);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003156 global.Reset(isolate, v8_str("str"));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003157 }
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00003158 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003159 v8::HandleScope scope(isolate);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003160 CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00003161 }
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003162 global.Dispose();
3163 global.Clear();
3164 {
3165 v8::HandleScope scope(isolate);
3166 global.Reset(isolate, v8_str("str"));
3167 }
3168 {
3169 v8::HandleScope scope(isolate);
3170 CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
3171 }
3172 global.Dispose();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003173}
3174
3175
ulan@chromium.org57ff8812013-05-10 08:16:55 +00003176THREADED_TEST(ResettingGlobalHandle) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00003177 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00003178 v8::Persistent<String> global;
3179 {
3180 v8::HandleScope scope(isolate);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003181 global.Reset(isolate, v8_str("str"));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00003182 }
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003183 v8::internal::GlobalHandles* global_handles =
3184 reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003185 int initial_handle_count = global_handles->global_handles_count();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00003186 {
3187 v8::HandleScope scope(isolate);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003188 CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00003189 }
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003190 {
3191 v8::HandleScope scope(isolate);
3192 global.Reset(isolate, v8_str("longer"));
3193 }
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003194 CHECK_EQ(global_handles->global_handles_count(), initial_handle_count);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003195 {
3196 v8::HandleScope scope(isolate);
3197 CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 6);
3198 }
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +00003199 global.Dispose();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003200 CHECK_EQ(global_handles->global_handles_count(), initial_handle_count - 1);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00003201}
3202
3203
3204THREADED_TEST(ResettingGlobalHandleToEmpty) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00003205 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00003206 v8::Persistent<String> global;
3207 {
3208 v8::HandleScope scope(isolate);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003209 global.Reset(isolate, v8_str("str"));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00003210 }
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003211 v8::internal::GlobalHandles* global_handles =
3212 reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003213 int initial_handle_count = global_handles->global_handles_count();
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003214 {
3215 v8::HandleScope scope(isolate);
3216 CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
3217 }
ulan@chromium.org57ff8812013-05-10 08:16:55 +00003218 {
3219 v8::HandleScope scope(isolate);
3220 Local<String> empty;
3221 global.Reset(isolate, empty);
3222 }
3223 CHECK(global.IsEmpty());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003224 CHECK_EQ(global_handles->global_handles_count(), initial_handle_count - 1);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00003225}
3226
3227
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00003228THREADED_TEST(ClearAndLeakGlobal) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00003229 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00003230 v8::internal::GlobalHandles* global_handles = NULL;
3231 int initial_handle_count = 0;
3232 v8::Persistent<String> global;
3233 {
3234 v8::HandleScope scope(isolate);
3235 Local<String> str = v8_str("str");
3236 global_handles =
3237 reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003238 initial_handle_count = global_handles->global_handles_count();
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003239 global.Reset(isolate, str);
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00003240 }
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003241 CHECK_EQ(global_handles->global_handles_count(), initial_handle_count + 1);
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00003242 String* str = global.ClearAndLeak();
3243 CHECK(global.IsEmpty());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003244 CHECK_EQ(global_handles->global_handles_count(), initial_handle_count + 1);
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00003245 global_handles->Destroy(reinterpret_cast<i::Object**>(str));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003246 CHECK_EQ(global_handles->global_handles_count(), initial_handle_count);
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00003247}
3248
3249
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003250THREADED_TEST(GlobalHandleUpcast) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00003251 v8::Isolate* isolate = CcTest::isolate();
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003252 v8::HandleScope scope(isolate);
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00003253 v8::Local<String> local = v8::Local<String>::New(isolate, v8_str("str"));
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003254 v8::Persistent<String> global_string(isolate, local);
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003255 v8::Persistent<Value>& global_value =
3256 v8::Persistent<Value>::Cast(global_string);
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003257 CHECK(v8::Local<v8::Value>::New(isolate, global_value)->IsString());
3258 CHECK(global_string == v8::Persistent<String>::Cast(global_value));
3259 global_string.Dispose();
3260}
3261
3262
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +00003263THREADED_TEST(HandleEquality) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00003264 v8::Isolate* isolate = CcTest::isolate();
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +00003265 v8::Persistent<String> global1;
3266 v8::Persistent<String> global2;
3267 {
3268 v8::HandleScope scope(isolate);
3269 global1.Reset(isolate, v8_str("str"));
3270 global2.Reset(isolate, v8_str("str2"));
3271 }
3272 CHECK_EQ(global1 == global1, true);
3273 CHECK_EQ(global1 != global1, false);
3274 {
3275 v8::HandleScope scope(isolate);
3276 Local<String> local1 = Local<String>::New(isolate, global1);
3277 Local<String> local2 = Local<String>::New(isolate, global2);
3278
3279 CHECK_EQ(global1 == local1, true);
3280 CHECK_EQ(global1 != local1, false);
3281 CHECK_EQ(local1 == global1, true);
3282 CHECK_EQ(local1 != global1, false);
3283
3284 CHECK_EQ(global1 == local2, false);
3285 CHECK_EQ(global1 != local2, true);
3286 CHECK_EQ(local2 == global1, false);
3287 CHECK_EQ(local2 != global1, true);
3288
3289 CHECK_EQ(local1 == local2, false);
3290 CHECK_EQ(local1 != local2, true);
3291
3292 Local<String> anotherLocal1 = Local<String>::New(isolate, global1);
3293 CHECK_EQ(local1 == anotherLocal1, true);
3294 CHECK_EQ(local1 != anotherLocal1, false);
3295 }
3296 global1.Dispose();
3297 global2.Dispose();
3298}
3299
3300
mstarzinger@chromium.org32280cf2012-12-06 17:32:37 +00003301THREADED_TEST(LocalHandle) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00003302 v8::HandleScope scope(CcTest::isolate());
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00003303 v8::Local<String> local =
3304 v8::Local<String>::New(CcTest::isolate(), v8_str("str"));
mstarzinger@chromium.org32280cf2012-12-06 17:32:37 +00003305 CHECK_EQ(local->Length(), 3);
3306}
3307
3308
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00003309class WeakCallCounter {
3310 public:
3311 explicit WeakCallCounter(int id) : id_(id), number_of_weak_calls_(0) { }
3312 int id() { return id_; }
3313 void increment() { number_of_weak_calls_++; }
3314 int NumberOfWeakCalls() { return number_of_weak_calls_; }
3315 private:
3316 int id_;
3317 int number_of_weak_calls_;
3318};
3319
3320
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00003321static void WeakPointerCallback(v8::Isolate* isolate,
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003322 Persistent<Value>* handle,
ulan@chromium.org57ff8812013-05-10 08:16:55 +00003323 WeakCallCounter* counter) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00003324 CHECK_EQ(1234, counter->id());
3325 counter->increment();
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +00003326 handle->Dispose();
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00003327}
3328
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00003329
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00003330static UniqueId MakeUniqueId(const Persistent<Value>& p) {
3331 return UniqueId(reinterpret_cast<uintptr_t>(*v8::Utils::OpenPersistent(p)));
3332}
3333
3334
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003335THREADED_TEST(ApiObjectGroups) {
3336 LocalContext env;
3337 v8::Isolate* iso = env->GetIsolate();
3338 HandleScope scope(iso);
3339
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003340 Persistent<Value> g1s1;
3341 Persistent<Value> g1s2;
3342 Persistent<Value> g1c1;
3343 Persistent<Value> g2s1;
3344 Persistent<Value> g2s2;
3345 Persistent<Value> g2c1;
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003346
3347 WeakCallCounter counter(1234);
3348
3349 {
3350 HandleScope scope(iso);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003351 g1s1.Reset(iso, Object::New());
3352 g1s2.Reset(iso, Object::New());
3353 g1c1.Reset(iso, Object::New());
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00003354 g1s1.MakeWeak(&counter, &WeakPointerCallback);
3355 g1s2.MakeWeak(&counter, &WeakPointerCallback);
3356 g1c1.MakeWeak(&counter, &WeakPointerCallback);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003357
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003358 g2s1.Reset(iso, Object::New());
3359 g2s2.Reset(iso, Object::New());
3360 g2c1.Reset(iso, Object::New());
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00003361 g2s1.MakeWeak(&counter, &WeakPointerCallback);
3362 g2s2.MakeWeak(&counter, &WeakPointerCallback);
3363 g2c1.MakeWeak(&counter, &WeakPointerCallback);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003364 }
3365
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003366 Persistent<Value> root(iso, g1s1); // make a root.
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003367
3368 // Connect group 1 and 2, make a cycle.
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003369 {
3370 HandleScope scope(iso);
3371 CHECK(Local<Object>::New(iso, g1s2.As<Object>())->
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00003372 Set(0, Local<Value>::New(iso, g2s2)));
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003373 CHECK(Local<Object>::New(iso, g2s1.As<Object>())->
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00003374 Set(0, Local<Value>::New(iso, g1s1)));
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003375 }
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003376
3377 {
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00003378 UniqueId id1 = MakeUniqueId(g1s1);
3379 UniqueId id2 = MakeUniqueId(g2s2);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003380 iso->SetObjectGroupId(g1s1, id1);
3381 iso->SetObjectGroupId(g1s2, id1);
3382 iso->SetReferenceFromGroup(id1, g1c1);
3383 iso->SetObjectGroupId(g2s1, id2);
3384 iso->SetObjectGroupId(g2s2, id2);
3385 iso->SetReferenceFromGroup(id2, g2c1);
3386 }
3387 // Do a single full GC, ensure incremental marking is stopped.
3388 v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>(
3389 iso)->heap();
3390 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
3391
3392 // All object should be alive.
3393 CHECK_EQ(0, counter.NumberOfWeakCalls());
3394
3395 // Weaken the root.
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00003396 root.MakeWeak(&counter, &WeakPointerCallback);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003397 // But make children strong roots---all the objects (except for children)
3398 // should be collectable now.
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +00003399 g1c1.ClearWeak();
3400 g2c1.ClearWeak();
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003401
3402 // Groups are deleted, rebuild groups.
3403 {
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00003404 UniqueId id1 = MakeUniqueId(g1s1);
3405 UniqueId id2 = MakeUniqueId(g2s2);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003406 iso->SetObjectGroupId(g1s1, id1);
3407 iso->SetObjectGroupId(g1s2, id1);
3408 iso->SetReferenceFromGroup(id1, g1c1);
3409 iso->SetObjectGroupId(g2s1, id2);
3410 iso->SetObjectGroupId(g2s2, id2);
3411 iso->SetReferenceFromGroup(id2, g2c1);
3412 }
3413
3414 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
3415
3416 // All objects should be gone. 5 global handles in total.
3417 CHECK_EQ(5, counter.NumberOfWeakCalls());
3418
3419 // And now make children weak again and collect them.
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00003420 g1c1.MakeWeak(&counter, &WeakPointerCallback);
3421 g2c1.MakeWeak(&counter, &WeakPointerCallback);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003422
3423 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
3424 CHECK_EQ(7, counter.NumberOfWeakCalls());
3425}
3426
3427
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003428THREADED_TEST(ApiObjectGroupsCycle) {
3429 LocalContext env;
3430 v8::Isolate* iso = env->GetIsolate();
3431 HandleScope scope(iso);
3432
3433 WeakCallCounter counter(1234);
3434
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003435 Persistent<Value> g1s1;
3436 Persistent<Value> g1s2;
3437 Persistent<Value> g2s1;
3438 Persistent<Value> g2s2;
3439 Persistent<Value> g3s1;
3440 Persistent<Value> g3s2;
3441 Persistent<Value> g4s1;
3442 Persistent<Value> g4s2;
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003443
3444 {
3445 HandleScope scope(iso);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003446 g1s1.Reset(iso, Object::New());
3447 g1s2.Reset(iso, Object::New());
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00003448 g1s1.MakeWeak(&counter, &WeakPointerCallback);
3449 g1s2.MakeWeak(&counter, &WeakPointerCallback);
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +00003450 CHECK(g1s1.IsWeak());
3451 CHECK(g1s2.IsWeak());
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003452
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003453 g2s1.Reset(iso, Object::New());
3454 g2s2.Reset(iso, Object::New());
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00003455 g2s1.MakeWeak(&counter, &WeakPointerCallback);
3456 g2s2.MakeWeak(&counter, &WeakPointerCallback);
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +00003457 CHECK(g2s1.IsWeak());
3458 CHECK(g2s2.IsWeak());
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003459
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003460 g3s1.Reset(iso, Object::New());
3461 g3s2.Reset(iso, Object::New());
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00003462 g3s1.MakeWeak(&counter, &WeakPointerCallback);
3463 g3s2.MakeWeak(&counter, &WeakPointerCallback);
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +00003464 CHECK(g3s1.IsWeak());
3465 CHECK(g3s2.IsWeak());
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003466
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003467 g4s1.Reset(iso, Object::New());
3468 g4s2.Reset(iso, Object::New());
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00003469 g4s1.MakeWeak(&counter, &WeakPointerCallback);
3470 g4s2.MakeWeak(&counter, &WeakPointerCallback);
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +00003471 CHECK(g4s1.IsWeak());
3472 CHECK(g4s2.IsWeak());
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003473 }
3474
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003475 Persistent<Value> root(iso, g1s1); // make a root.
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003476
3477 // Connect groups. We're building the following cycle:
3478 // G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other
3479 // groups.
3480 {
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00003481 UniqueId id1 = MakeUniqueId(g1s1);
3482 UniqueId id2 = MakeUniqueId(g2s1);
3483 UniqueId id3 = MakeUniqueId(g3s1);
3484 UniqueId id4 = MakeUniqueId(g4s1);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003485 iso->SetObjectGroupId(g1s1, id1);
3486 iso->SetObjectGroupId(g1s2, id1);
3487 iso->SetReferenceFromGroup(id1, g2s1);
3488 iso->SetObjectGroupId(g2s1, id2);
3489 iso->SetObjectGroupId(g2s2, id2);
3490 iso->SetReferenceFromGroup(id2, g3s1);
3491 iso->SetObjectGroupId(g3s1, id3);
3492 iso->SetObjectGroupId(g3s2, id3);
3493 iso->SetReferenceFromGroup(id3, g4s1);
3494 iso->SetObjectGroupId(g4s1, id4);
3495 iso->SetObjectGroupId(g4s2, id4);
3496 iso->SetReferenceFromGroup(id4, g1s1);
3497 }
3498 // Do a single full GC
3499 v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>(
3500 iso)->heap();
3501 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
3502
3503 // All object should be alive.
3504 CHECK_EQ(0, counter.NumberOfWeakCalls());
3505
3506 // Weaken the root.
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00003507 root.MakeWeak(&counter, &WeakPointerCallback);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003508
3509 // Groups are deleted, rebuild groups.
3510 {
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00003511 UniqueId id1 = MakeUniqueId(g1s1);
3512 UniqueId id2 = MakeUniqueId(g2s1);
3513 UniqueId id3 = MakeUniqueId(g3s1);
3514 UniqueId id4 = MakeUniqueId(g4s1);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003515 iso->SetObjectGroupId(g1s1, id1);
3516 iso->SetObjectGroupId(g1s2, id1);
3517 iso->SetReferenceFromGroup(id1, g2s1);
3518 iso->SetObjectGroupId(g2s1, id2);
3519 iso->SetObjectGroupId(g2s2, id2);
3520 iso->SetReferenceFromGroup(id2, g3s1);
3521 iso->SetObjectGroupId(g3s1, id3);
3522 iso->SetObjectGroupId(g3s2, id3);
3523 iso->SetReferenceFromGroup(id3, g4s1);
3524 iso->SetObjectGroupId(g4s1, id4);
3525 iso->SetObjectGroupId(g4s2, id4);
3526 iso->SetReferenceFromGroup(id4, g1s1);
3527 }
3528
3529 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
3530
3531 // All objects should be gone. 9 global handles in total.
3532 CHECK_EQ(9, counter.NumberOfWeakCalls());
3533}
3534
3535
mvstanton@chromium.orge4ac3ef2012-11-12 14:53:34 +00003536// TODO(mstarzinger): This should be a THREADED_TEST but causes failures
3537// on the buildbots, so was made non-threaded for the time being.
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003538TEST(ApiObjectGroupsCycleForScavenger) {
3539 i::FLAG_stress_compaction = false;
3540 i::FLAG_gc_global = false;
3541 LocalContext env;
3542 v8::Isolate* iso = env->GetIsolate();
3543 HandleScope scope(iso);
3544
3545 WeakCallCounter counter(1234);
3546
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003547 Persistent<Value> g1s1;
3548 Persistent<Value> g1s2;
3549 Persistent<Value> g2s1;
3550 Persistent<Value> g2s2;
3551 Persistent<Value> g3s1;
3552 Persistent<Value> g3s2;
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003553
3554 {
3555 HandleScope scope(iso);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003556 g1s1.Reset(iso, Object::New());
3557 g1s2.Reset(iso, Object::New());
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00003558 g1s1.MakeWeak(&counter, &WeakPointerCallback);
3559 g1s2.MakeWeak(&counter, &WeakPointerCallback);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003560
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003561 g2s1.Reset(iso, Object::New());
3562 g2s2.Reset(iso, Object::New());
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00003563 g2s1.MakeWeak(&counter, &WeakPointerCallback);
3564 g2s2.MakeWeak(&counter, &WeakPointerCallback);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003565
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003566 g3s1.Reset(iso, Object::New());
3567 g3s2.Reset(iso, Object::New());
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00003568 g3s1.MakeWeak(&counter, &WeakPointerCallback);
3569 g3s2.MakeWeak(&counter, &WeakPointerCallback);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003570 }
3571
3572 // Make a root.
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003573 Persistent<Value> root(iso, g1s1);
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +00003574 root.MarkPartiallyDependent();
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003575
3576 // Connect groups. We're building the following cycle:
3577 // G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other
3578 // groups.
3579 {
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003580 HandleScope handle_scope(iso);
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +00003581 g1s1.MarkPartiallyDependent();
3582 g1s2.MarkPartiallyDependent();
3583 g2s1.MarkPartiallyDependent();
3584 g2s2.MarkPartiallyDependent();
3585 g3s1.MarkPartiallyDependent();
3586 g3s2.MarkPartiallyDependent();
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003587 iso->SetObjectGroupId(g1s1, UniqueId(1));
3588 iso->SetObjectGroupId(g1s2, UniqueId(1));
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00003589 Local<Object>::New(iso, g1s1.As<Object>())->Set(
3590 v8_str("x"), Local<Value>::New(iso, g2s1));
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003591 iso->SetObjectGroupId(g2s1, UniqueId(2));
3592 iso->SetObjectGroupId(g2s2, UniqueId(2));
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00003593 Local<Object>::New(iso, g2s1.As<Object>())->Set(
3594 v8_str("x"), Local<Value>::New(iso, g3s1));
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003595 iso->SetObjectGroupId(g3s1, UniqueId(3));
3596 iso->SetObjectGroupId(g3s2, UniqueId(3));
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00003597 Local<Object>::New(iso, g3s1.As<Object>())->Set(
3598 v8_str("x"), Local<Value>::New(iso, g1s1));
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003599 }
3600
3601 v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>(
3602 iso)->heap();
3603 heap->CollectGarbage(i::NEW_SPACE);
3604
3605 // All objects should be alive.
3606 CHECK_EQ(0, counter.NumberOfWeakCalls());
3607
3608 // Weaken the root.
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00003609 root.MakeWeak(&counter, &WeakPointerCallback);
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +00003610 root.MarkPartiallyDependent();
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003611
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003612 // Groups are deleted, rebuild groups.
3613 {
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003614 HandleScope handle_scope(iso);
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +00003615 g1s1.MarkPartiallyDependent();
3616 g1s2.MarkPartiallyDependent();
3617 g2s1.MarkPartiallyDependent();
3618 g2s2.MarkPartiallyDependent();
3619 g3s1.MarkPartiallyDependent();
3620 g3s2.MarkPartiallyDependent();
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003621 iso->SetObjectGroupId(g1s1, UniqueId(1));
3622 iso->SetObjectGroupId(g1s2, UniqueId(1));
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00003623 Local<Object>::New(iso, g1s1.As<Object>())->Set(
3624 v8_str("x"), Local<Value>::New(iso, g2s1));
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003625 iso->SetObjectGroupId(g2s1, UniqueId(2));
3626 iso->SetObjectGroupId(g2s2, UniqueId(2));
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00003627 Local<Object>::New(iso, g2s1.As<Object>())->Set(
3628 v8_str("x"), Local<Value>::New(iso, g3s1));
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003629 iso->SetObjectGroupId(g3s1, UniqueId(3));
3630 iso->SetObjectGroupId(g3s2, UniqueId(3));
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00003631 Local<Object>::New(iso, g3s1.As<Object>())->Set(
3632 v8_str("x"), Local<Value>::New(iso, g1s1));
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003633 }
3634
3635 heap->CollectGarbage(i::NEW_SPACE);
3636
3637 // All objects should be gone. 7 global handles in total.
3638 CHECK_EQ(7, counter.NumberOfWeakCalls());
3639}
3640
3641
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003642THREADED_TEST(ScriptException) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003643 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003644 v8::HandleScope scope(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003645 Local<Script> script = Script::Compile(v8_str("throw 'panama!';"));
3646 v8::TryCatch try_catch;
3647 Local<Value> result = script->Run();
3648 CHECK(result.IsEmpty());
3649 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00003650 String::Utf8Value exception_value(try_catch.Exception());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003651 CHECK_EQ(*exception_value, "panama!");
3652}
3653
3654
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00003655TEST(TryCatchCustomException) {
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00003656 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003657 v8::HandleScope scope(env->GetIsolate());
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00003658 v8::TryCatch try_catch;
3659 CompileRun("function CustomError() { this.a = 'b'; }"
3660 "(function f() { throw new CustomError(); })();");
3661 CHECK(try_catch.HasCaught());
3662 CHECK(try_catch.Exception()->ToObject()->
3663 Get(v8_str("a"))->Equals(v8_str("b")));
3664}
3665
3666
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003667bool message_received;
3668
3669
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00003670static void check_message_0(v8::Handle<v8::Message> message,
3671 v8::Handle<Value> data) {
hpayer@chromium.org8432c912013-02-28 15:55:26 +00003672 CHECK_EQ(5.76, data->NumberValue());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003673 CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
ager@chromium.org65dad4b2009-04-23 08:48:43 +00003674 CHECK_EQ(7.56, message->GetScriptData()->NumberValue());
danno@chromium.orgd3c42102013-08-01 16:58:23 +00003675 CHECK(!message->IsSharedCrossOrigin());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003676 message_received = true;
3677}
3678
3679
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00003680THREADED_TEST(MessageHandler0) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003681 message_received = false;
machenbach@chromium.org528ce022013-09-23 14:09:36 +00003682 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003683 CHECK(!message_received);
hpayer@chromium.org8432c912013-02-28 15:55:26 +00003684 v8::V8::AddMessageListener(check_message_0, v8_num(5.76));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003685 LocalContext context;
3686 v8::ScriptOrigin origin =
3687 v8::ScriptOrigin(v8_str("6.75"));
ager@chromium.org65dad4b2009-04-23 08:48:43 +00003688 v8::Handle<v8::Script> script = Script::Compile(v8_str("throw 'error'"),
3689 &origin);
3690 script->SetData(v8_str("7.56"));
3691 script->Run();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003692 CHECK(message_received);
3693 // clear out the message listener
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00003694 v8::V8::RemoveMessageListeners(check_message_0);
3695}
3696
3697
3698static void check_message_1(v8::Handle<v8::Message> message,
3699 v8::Handle<Value> data) {
3700 CHECK(data->IsNumber());
3701 CHECK_EQ(1337, data->Int32Value());
danno@chromium.orgd3c42102013-08-01 16:58:23 +00003702 CHECK(!message->IsSharedCrossOrigin());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00003703 message_received = true;
3704}
3705
3706
3707TEST(MessageHandler1) {
3708 message_received = false;
machenbach@chromium.org528ce022013-09-23 14:09:36 +00003709 v8::HandleScope scope(CcTest::isolate());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00003710 CHECK(!message_received);
3711 v8::V8::AddMessageListener(check_message_1);
3712 LocalContext context;
3713 CompileRun("throw 1337;");
3714 CHECK(message_received);
3715 // clear out the message listener
3716 v8::V8::RemoveMessageListeners(check_message_1);
3717}
3718
3719
3720static void check_message_2(v8::Handle<v8::Message> message,
3721 v8::Handle<Value> data) {
3722 LocalContext context;
3723 CHECK(data->IsObject());
3724 v8::Local<v8::Value> hidden_property =
3725 v8::Object::Cast(*data)->GetHiddenValue(v8_str("hidden key"));
3726 CHECK(v8_str("hidden value")->Equals(hidden_property));
danno@chromium.orgd3c42102013-08-01 16:58:23 +00003727 CHECK(!message->IsSharedCrossOrigin());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00003728 message_received = true;
3729}
3730
3731
3732TEST(MessageHandler2) {
3733 message_received = false;
machenbach@chromium.org528ce022013-09-23 14:09:36 +00003734 v8::HandleScope scope(CcTest::isolate());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00003735 CHECK(!message_received);
3736 v8::V8::AddMessageListener(check_message_2);
3737 LocalContext context;
3738 v8::Local<v8::Value> error = v8::Exception::Error(v8_str("custom error"));
3739 v8::Object::Cast(*error)->SetHiddenValue(v8_str("hidden key"),
3740 v8_str("hidden value"));
3741 context->Global()->Set(v8_str("error"), error);
3742 CompileRun("throw error;");
3743 CHECK(message_received);
3744 // clear out the message listener
3745 v8::V8::RemoveMessageListeners(check_message_2);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003746}
3747
3748
danno@chromium.orgd3c42102013-08-01 16:58:23 +00003749static void check_message_3(v8::Handle<v8::Message> message,
3750 v8::Handle<Value> data) {
3751 CHECK(message->IsSharedCrossOrigin());
3752 CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
3753 message_received = true;
3754}
3755
3756
3757TEST(MessageHandler3) {
3758 message_received = false;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00003759 v8::Isolate* isolate = CcTest::isolate();
3760 v8::HandleScope scope(isolate);
danno@chromium.orgd3c42102013-08-01 16:58:23 +00003761 CHECK(!message_received);
3762 v8::V8::AddMessageListener(check_message_3);
3763 LocalContext context;
3764 v8::ScriptOrigin origin =
3765 v8::ScriptOrigin(v8_str("6.75"),
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00003766 v8::Integer::New(1, isolate),
3767 v8::Integer::New(2, isolate),
3768 v8::True(isolate));
danno@chromium.orgd3c42102013-08-01 16:58:23 +00003769 v8::Handle<v8::Script> script = Script::Compile(v8_str("throw 'error'"),
3770 &origin);
3771 script->Run();
3772 CHECK(message_received);
3773 // clear out the message listener
3774 v8::V8::RemoveMessageListeners(check_message_3);
3775}
3776
3777
3778static void check_message_4(v8::Handle<v8::Message> message,
3779 v8::Handle<Value> data) {
3780 CHECK(!message->IsSharedCrossOrigin());
3781 CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
3782 message_received = true;
3783}
3784
3785
3786TEST(MessageHandler4) {
3787 message_received = false;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00003788 v8::Isolate* isolate = CcTest::isolate();
3789 v8::HandleScope scope(isolate);
danno@chromium.orgd3c42102013-08-01 16:58:23 +00003790 CHECK(!message_received);
3791 v8::V8::AddMessageListener(check_message_4);
3792 LocalContext context;
3793 v8::ScriptOrigin origin =
3794 v8::ScriptOrigin(v8_str("6.75"),
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00003795 v8::Integer::New(1, isolate),
3796 v8::Integer::New(2, isolate),
3797 v8::False(isolate));
danno@chromium.orgd3c42102013-08-01 16:58:23 +00003798 v8::Handle<v8::Script> script = Script::Compile(v8_str("throw 'error'"),
3799 &origin);
3800 script->Run();
3801 CHECK(message_received);
3802 // clear out the message listener
3803 v8::V8::RemoveMessageListeners(check_message_4);
3804}
3805
3806
3807static void check_message_5a(v8::Handle<v8::Message> message,
3808 v8::Handle<Value> data) {
3809 CHECK(message->IsSharedCrossOrigin());
3810 CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
3811 message_received = true;
3812}
3813
3814
3815static void check_message_5b(v8::Handle<v8::Message> message,
3816 v8::Handle<Value> data) {
3817 CHECK(!message->IsSharedCrossOrigin());
3818 CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
3819 message_received = true;
3820}
3821
3822
3823TEST(MessageHandler5) {
3824 message_received = false;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00003825 v8::Isolate* isolate = CcTest::isolate();
3826 v8::HandleScope scope(isolate);
danno@chromium.orgd3c42102013-08-01 16:58:23 +00003827 CHECK(!message_received);
3828 v8::V8::AddMessageListener(check_message_5a);
3829 LocalContext context;
3830 v8::ScriptOrigin origin =
3831 v8::ScriptOrigin(v8_str("6.75"),
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00003832 v8::Integer::New(1, isolate),
3833 v8::Integer::New(2, isolate),
3834 v8::True(isolate));
danno@chromium.orgd3c42102013-08-01 16:58:23 +00003835 v8::Handle<v8::Script> script = Script::Compile(v8_str("throw 'error'"),
3836 &origin);
3837 script->Run();
3838 CHECK(message_received);
3839 // clear out the message listener
3840 v8::V8::RemoveMessageListeners(check_message_5a);
3841
3842 message_received = false;
3843 v8::V8::AddMessageListener(check_message_5b);
3844 origin =
3845 v8::ScriptOrigin(v8_str("6.75"),
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00003846 v8::Integer::New(1, isolate),
3847 v8::Integer::New(2, isolate),
3848 v8::False(isolate));
danno@chromium.orgd3c42102013-08-01 16:58:23 +00003849 script = Script::Compile(v8_str("throw 'error'"),
3850 &origin);
3851 script->Run();
3852 CHECK(message_received);
3853 // clear out the message listener
3854 v8::V8::RemoveMessageListeners(check_message_5b);
3855}
3856
3857
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003858THREADED_TEST(GetSetProperty) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003859 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003860 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003861 context->Global()->Set(v8_str("foo"), v8_num(14));
3862 context->Global()->Set(v8_str("12"), v8_num(92));
3863 context->Global()->Set(v8::Integer::New(16), v8_num(32));
3864 context->Global()->Set(v8_num(13), v8_num(56));
3865 Local<Value> foo = Script::Compile(v8_str("this.foo"))->Run();
3866 CHECK_EQ(14, foo->Int32Value());
3867 Local<Value> twelve = Script::Compile(v8_str("this[12]"))->Run();
3868 CHECK_EQ(92, twelve->Int32Value());
3869 Local<Value> sixteen = Script::Compile(v8_str("this[16]"))->Run();
3870 CHECK_EQ(32, sixteen->Int32Value());
3871 Local<Value> thirteen = Script::Compile(v8_str("this[13]"))->Run();
3872 CHECK_EQ(56, thirteen->Int32Value());
3873 CHECK_EQ(92, context->Global()->Get(v8::Integer::New(12))->Int32Value());
3874 CHECK_EQ(92, context->Global()->Get(v8_str("12"))->Int32Value());
3875 CHECK_EQ(92, context->Global()->Get(v8_num(12))->Int32Value());
3876 CHECK_EQ(32, context->Global()->Get(v8::Integer::New(16))->Int32Value());
3877 CHECK_EQ(32, context->Global()->Get(v8_str("16"))->Int32Value());
3878 CHECK_EQ(32, context->Global()->Get(v8_num(16))->Int32Value());
3879 CHECK_EQ(56, context->Global()->Get(v8::Integer::New(13))->Int32Value());
3880 CHECK_EQ(56, context->Global()->Get(v8_str("13"))->Int32Value());
3881 CHECK_EQ(56, context->Global()->Get(v8_num(13))->Int32Value());
3882}
3883
3884
3885THREADED_TEST(PropertyAttributes) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003886 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003887 v8::HandleScope scope(context->GetIsolate());
rossberg@chromium.org717967f2011-07-20 13:44:42 +00003888 // none
3889 Local<String> prop = v8_str("none");
3890 context->Global()->Set(prop, v8_num(7));
3891 CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(prop));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003892 // read-only
rossberg@chromium.org717967f2011-07-20 13:44:42 +00003893 prop = v8_str("read_only");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003894 context->Global()->Set(prop, v8_num(7), v8::ReadOnly);
3895 CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
rossberg@chromium.org717967f2011-07-20 13:44:42 +00003896 CHECK_EQ(v8::ReadOnly, context->Global()->GetPropertyAttributes(prop));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003897 Script::Compile(v8_str("read_only = 9"))->Run();
3898 CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
3899 context->Global()->Set(prop, v8_num(10));
3900 CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
3901 // dont-delete
3902 prop = v8_str("dont_delete");
3903 context->Global()->Set(prop, v8_num(13), v8::DontDelete);
3904 CHECK_EQ(13, context->Global()->Get(prop)->Int32Value());
3905 Script::Compile(v8_str("delete dont_delete"))->Run();
3906 CHECK_EQ(13, context->Global()->Get(prop)->Int32Value());
rossberg@chromium.org717967f2011-07-20 13:44:42 +00003907 CHECK_EQ(v8::DontDelete, context->Global()->GetPropertyAttributes(prop));
3908 // dont-enum
3909 prop = v8_str("dont_enum");
3910 context->Global()->Set(prop, v8_num(28), v8::DontEnum);
3911 CHECK_EQ(v8::DontEnum, context->Global()->GetPropertyAttributes(prop));
3912 // absent
3913 prop = v8_str("absent");
3914 CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(prop));
3915 Local<Value> fake_prop = v8_num(1);
3916 CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(fake_prop));
3917 // exception
3918 TryCatch try_catch;
3919 Local<Value> exception =
3920 CompileRun("({ toString: function() { throw 'exception';} })");
3921 CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(exception));
3922 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00003923 String::Utf8Value exception_value(try_catch.Exception());
rossberg@chromium.org717967f2011-07-20 13:44:42 +00003924 CHECK_EQ("exception", *exception_value);
3925 try_catch.Reset();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003926}
3927
3928
3929THREADED_TEST(Array) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003930 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003931 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003932 Local<v8::Array> array = v8::Array::New();
3933 CHECK_EQ(0, array->Length());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00003934 CHECK(array->Get(0)->IsUndefined());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003935 CHECK(!array->Has(0));
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00003936 CHECK(array->Get(100)->IsUndefined());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003937 CHECK(!array->Has(100));
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00003938 array->Set(2, v8_num(7));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003939 CHECK_EQ(3, array->Length());
3940 CHECK(!array->Has(0));
3941 CHECK(!array->Has(1));
3942 CHECK(array->Has(2));
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00003943 CHECK_EQ(7, array->Get(2)->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003944 Local<Value> obj = Script::Compile(v8_str("[1, 2, 3]"))->Run();
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00003945 Local<v8::Array> arr = obj.As<v8::Array>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003946 CHECK_EQ(3, arr->Length());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00003947 CHECK_EQ(1, arr->Get(0)->Int32Value());
3948 CHECK_EQ(2, arr->Get(1)->Int32Value());
3949 CHECK_EQ(3, arr->Get(2)->Int32Value());
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00003950 array = v8::Array::New(27);
3951 CHECK_EQ(27, array->Length());
3952 array = v8::Array::New(-27);
3953 CHECK_EQ(0, array->Length());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003954}
3955
3956
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003957void HandleF(const v8::FunctionCallbackInfo<v8::Value>& args) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003958 v8::HandleScope scope(args.GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003959 ApiTestFuzzer::Fuzz();
3960 Local<v8::Array> result = v8::Array::New(args.Length());
3961 for (int i = 0; i < args.Length(); i++)
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00003962 result->Set(i, args[i]);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003963 args.GetReturnValue().Set(scope.Close(result));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003964}
3965
3966
3967THREADED_TEST(Vector) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00003968 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003969 Local<ObjectTemplate> global = ObjectTemplate::New();
3970 global->Set(v8_str("f"), v8::FunctionTemplate::New(HandleF));
3971 LocalContext context(0, global);
3972
3973 const char* fun = "f()";
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00003974 Local<v8::Array> a0 = CompileRun(fun).As<v8::Array>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003975 CHECK_EQ(0, a0->Length());
3976
3977 const char* fun2 = "f(11)";
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00003978 Local<v8::Array> a1 = CompileRun(fun2).As<v8::Array>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003979 CHECK_EQ(1, a1->Length());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00003980 CHECK_EQ(11, a1->Get(0)->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003981
3982 const char* fun3 = "f(12, 13)";
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00003983 Local<v8::Array> a2 = CompileRun(fun3).As<v8::Array>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003984 CHECK_EQ(2, a2->Length());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00003985 CHECK_EQ(12, a2->Get(0)->Int32Value());
3986 CHECK_EQ(13, a2->Get(1)->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003987
3988 const char* fun4 = "f(14, 15, 16)";
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00003989 Local<v8::Array> a3 = CompileRun(fun4).As<v8::Array>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003990 CHECK_EQ(3, a3->Length());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00003991 CHECK_EQ(14, a3->Get(0)->Int32Value());
3992 CHECK_EQ(15, a3->Get(1)->Int32Value());
3993 CHECK_EQ(16, a3->Get(2)->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003994
3995 const char* fun5 = "f(17, 18, 19, 20)";
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00003996 Local<v8::Array> a4 = CompileRun(fun5).As<v8::Array>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003997 CHECK_EQ(4, a4->Length());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00003998 CHECK_EQ(17, a4->Get(0)->Int32Value());
3999 CHECK_EQ(18, a4->Get(1)->Int32Value());
4000 CHECK_EQ(19, a4->Get(2)->Int32Value());
4001 CHECK_EQ(20, a4->Get(3)->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004002}
4003
4004
4005THREADED_TEST(FunctionCall) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004006 LocalContext context;
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +00004007 v8::Isolate* isolate = context->GetIsolate();
4008 v8::HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004009 CompileRun(
4010 "function Foo() {"
4011 " var result = [];"
4012 " for (var i = 0; i < arguments.length; i++) {"
4013 " result.push(arguments[i]);"
4014 " }"
4015 " return result;"
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +00004016 "}"
4017 "function ReturnThisSloppy() {"
4018 " return this;"
4019 "}"
4020 "function ReturnThisStrict() {"
4021 " 'use strict';"
4022 " return this;"
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004023 "}");
4024 Local<Function> Foo =
4025 Local<Function>::Cast(context->Global()->Get(v8_str("Foo")));
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +00004026 Local<Function> ReturnThisSloppy =
4027 Local<Function>::Cast(context->Global()->Get(v8_str("ReturnThisSloppy")));
4028 Local<Function> ReturnThisStrict =
4029 Local<Function>::Cast(context->Global()->Get(v8_str("ReturnThisStrict")));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004030
4031 v8::Handle<Value>* args0 = NULL;
4032 Local<v8::Array> a0 = Local<v8::Array>::Cast(Foo->Call(Foo, 0, args0));
4033 CHECK_EQ(0, a0->Length());
4034
4035 v8::Handle<Value> args1[] = { v8_num(1.1) };
4036 Local<v8::Array> a1 = Local<v8::Array>::Cast(Foo->Call(Foo, 1, args1));
4037 CHECK_EQ(1, a1->Length());
4038 CHECK_EQ(1.1, a1->Get(v8::Integer::New(0))->NumberValue());
4039
4040 v8::Handle<Value> args2[] = { v8_num(2.2),
4041 v8_num(3.3) };
4042 Local<v8::Array> a2 = Local<v8::Array>::Cast(Foo->Call(Foo, 2, args2));
4043 CHECK_EQ(2, a2->Length());
4044 CHECK_EQ(2.2, a2->Get(v8::Integer::New(0))->NumberValue());
4045 CHECK_EQ(3.3, a2->Get(v8::Integer::New(1))->NumberValue());
4046
4047 v8::Handle<Value> args3[] = { v8_num(4.4),
4048 v8_num(5.5),
4049 v8_num(6.6) };
4050 Local<v8::Array> a3 = Local<v8::Array>::Cast(Foo->Call(Foo, 3, args3));
4051 CHECK_EQ(3, a3->Length());
4052 CHECK_EQ(4.4, a3->Get(v8::Integer::New(0))->NumberValue());
4053 CHECK_EQ(5.5, a3->Get(v8::Integer::New(1))->NumberValue());
4054 CHECK_EQ(6.6, a3->Get(v8::Integer::New(2))->NumberValue());
4055
4056 v8::Handle<Value> args4[] = { v8_num(7.7),
4057 v8_num(8.8),
4058 v8_num(9.9),
4059 v8_num(10.11) };
4060 Local<v8::Array> a4 = Local<v8::Array>::Cast(Foo->Call(Foo, 4, args4));
4061 CHECK_EQ(4, a4->Length());
4062 CHECK_EQ(7.7, a4->Get(v8::Integer::New(0))->NumberValue());
4063 CHECK_EQ(8.8, a4->Get(v8::Integer::New(1))->NumberValue());
4064 CHECK_EQ(9.9, a4->Get(v8::Integer::New(2))->NumberValue());
4065 CHECK_EQ(10.11, a4->Get(v8::Integer::New(3))->NumberValue());
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +00004066
4067 Local<v8::Value> r1 = ReturnThisSloppy->Call(v8::Undefined(isolate), 0, NULL);
4068 CHECK(r1->StrictEquals(context->Global()));
4069 Local<v8::Value> r2 = ReturnThisSloppy->Call(v8::Null(isolate), 0, NULL);
4070 CHECK(r2->StrictEquals(context->Global()));
4071 Local<v8::Value> r3 = ReturnThisSloppy->Call(v8_num(42), 0, NULL);
4072 CHECK(r3->IsNumberObject());
4073 CHECK_EQ(42.0, r3.As<v8::NumberObject>()->ValueOf());
4074 Local<v8::Value> r4 = ReturnThisSloppy->Call(v8_str("hello"), 0, NULL);
4075 CHECK(r4->IsStringObject());
4076 CHECK(r4.As<v8::StringObject>()->ValueOf()->StrictEquals(v8_str("hello")));
4077 Local<v8::Value> r5 = ReturnThisSloppy->Call(v8::True(isolate), 0, NULL);
4078 CHECK(r5->IsBooleanObject());
4079 CHECK(r5.As<v8::BooleanObject>()->ValueOf());
4080
4081 Local<v8::Value> r6 = ReturnThisStrict->Call(v8::Undefined(isolate), 0, NULL);
4082 CHECK(r6->IsUndefined());
4083 Local<v8::Value> r7 = ReturnThisStrict->Call(v8::Null(isolate), 0, NULL);
4084 CHECK(r7->IsNull());
4085 Local<v8::Value> r8 = ReturnThisStrict->Call(v8_num(42), 0, NULL);
4086 CHECK(r8->StrictEquals(v8_num(42)));
4087 Local<v8::Value> r9 = ReturnThisStrict->Call(v8_str("hello"), 0, NULL);
4088 CHECK(r9->StrictEquals(v8_str("hello")));
4089 Local<v8::Value> r10 = ReturnThisStrict->Call(v8::True(isolate), 0, NULL);
4090 CHECK(r10->StrictEquals(v8::True(isolate)));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004091}
4092
4093
4094static const char* js_code_causing_out_of_memory =
4095 "var a = new Array(); while(true) a.push(a);";
4096
4097
4098// These tests run for a long time and prevent us from running tests
4099// that come after them so they cannot run in parallel.
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00004100TEST(OutOfMemory) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004101 // It's not possible to read a snapshot into a heap with different dimensions.
lrn@chromium.org32d961d2010-06-30 09:09:34 +00004102 if (i::Snapshot::IsEnabled()) return;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004103 // Set heap limits.
4104 static const int K = 1024;
4105 v8::ResourceConstraints constraints;
4106 constraints.set_max_young_space_size(256 * K);
machenbach@chromium.orgc1789ee2013-07-05 07:09:57 +00004107 constraints.set_max_old_space_size(5 * K * K);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004108 v8::SetResourceConstraints(&constraints);
4109
4110 // Execute a script that causes out of memory.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004111 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004112 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004113 v8::V8::IgnoreOutOfMemoryException();
4114 Local<Script> script =
4115 Script::Compile(String::New(js_code_causing_out_of_memory));
4116 Local<Value> result = script->Run();
4117
4118 // Check for out of memory state.
4119 CHECK(result.IsEmpty());
4120 CHECK(context->HasOutOfMemoryException());
4121}
4122
4123
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00004124void ProvokeOutOfMemory(const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004125 ApiTestFuzzer::Fuzz();
4126
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004127 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004128 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004129 Local<Script> script =
4130 Script::Compile(String::New(js_code_causing_out_of_memory));
4131 Local<Value> result = script->Run();
4132
4133 // Check for out of memory state.
4134 CHECK(result.IsEmpty());
4135 CHECK(context->HasOutOfMemoryException());
4136
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00004137 args.GetReturnValue().Set(result);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004138}
4139
4140
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00004141TEST(OutOfMemoryNested) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004142 // It's not possible to read a snapshot into a heap with different dimensions.
lrn@chromium.org32d961d2010-06-30 09:09:34 +00004143 if (i::Snapshot::IsEnabled()) return;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004144 // Set heap limits.
4145 static const int K = 1024;
4146 v8::ResourceConstraints constraints;
4147 constraints.set_max_young_space_size(256 * K);
machenbach@chromium.orgc1789ee2013-07-05 07:09:57 +00004148 constraints.set_max_old_space_size(5 * K * K);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004149 v8::SetResourceConstraints(&constraints);
4150
machenbach@chromium.org528ce022013-09-23 14:09:36 +00004151 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004152 Local<ObjectTemplate> templ = ObjectTemplate::New();
4153 templ->Set(v8_str("ProvokeOutOfMemory"),
4154 v8::FunctionTemplate::New(ProvokeOutOfMemory));
4155 LocalContext context(0, templ);
4156 v8::V8::IgnoreOutOfMemoryException();
4157 Local<Value> result = CompileRun(
4158 "var thrown = false;"
4159 "try {"
4160 " ProvokeOutOfMemory();"
4161 "} catch (e) {"
4162 " thrown = true;"
4163 "}");
4164 // Check for out of memory state.
4165 CHECK(result.IsEmpty());
4166 CHECK(context->HasOutOfMemoryException());
4167}
4168
4169
4170TEST(HugeConsStringOutOfMemory) {
4171 // It's not possible to read a snapshot into a heap with different dimensions.
lrn@chromium.org32d961d2010-06-30 09:09:34 +00004172 if (i::Snapshot::IsEnabled()) return;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004173 // Set heap limits.
4174 static const int K = 1024;
4175 v8::ResourceConstraints constraints;
4176 constraints.set_max_young_space_size(256 * K);
machenbach@chromium.orgc1789ee2013-07-05 07:09:57 +00004177 constraints.set_max_old_space_size(4 * K * K);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004178 v8::SetResourceConstraints(&constraints);
4179
4180 // Execute a script that causes out of memory.
4181 v8::V8::IgnoreOutOfMemoryException();
4182
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00004183 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004184 v8::HandleScope scope(context->GetIsolate());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00004185
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004186 // Build huge string. This should fail with out of memory exception.
4187 Local<Value> result = CompileRun(
4188 "var str = Array.prototype.join.call({length: 513}, \"A\").toUpperCase();"
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00004189 "for (var i = 0; i < 22; i++) { str = str + str; }");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004190
4191 // Check for out of memory state.
4192 CHECK(result.IsEmpty());
4193 CHECK(context->HasOutOfMemoryException());
4194}
4195
4196
4197THREADED_TEST(ConstructCall) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004198 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004199 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004200 CompileRun(
4201 "function Foo() {"
4202 " var result = [];"
4203 " for (var i = 0; i < arguments.length; i++) {"
4204 " result.push(arguments[i]);"
4205 " }"
4206 " return result;"
4207 "}");
4208 Local<Function> Foo =
4209 Local<Function>::Cast(context->Global()->Get(v8_str("Foo")));
4210
4211 v8::Handle<Value>* args0 = NULL;
4212 Local<v8::Array> a0 = Local<v8::Array>::Cast(Foo->NewInstance(0, args0));
4213 CHECK_EQ(0, a0->Length());
4214
4215 v8::Handle<Value> args1[] = { v8_num(1.1) };
4216 Local<v8::Array> a1 = Local<v8::Array>::Cast(Foo->NewInstance(1, args1));
4217 CHECK_EQ(1, a1->Length());
4218 CHECK_EQ(1.1, a1->Get(v8::Integer::New(0))->NumberValue());
4219
4220 v8::Handle<Value> args2[] = { v8_num(2.2),
4221 v8_num(3.3) };
4222 Local<v8::Array> a2 = Local<v8::Array>::Cast(Foo->NewInstance(2, args2));
4223 CHECK_EQ(2, a2->Length());
4224 CHECK_EQ(2.2, a2->Get(v8::Integer::New(0))->NumberValue());
4225 CHECK_EQ(3.3, a2->Get(v8::Integer::New(1))->NumberValue());
4226
4227 v8::Handle<Value> args3[] = { v8_num(4.4),
4228 v8_num(5.5),
4229 v8_num(6.6) };
4230 Local<v8::Array> a3 = Local<v8::Array>::Cast(Foo->NewInstance(3, args3));
4231 CHECK_EQ(3, a3->Length());
4232 CHECK_EQ(4.4, a3->Get(v8::Integer::New(0))->NumberValue());
4233 CHECK_EQ(5.5, a3->Get(v8::Integer::New(1))->NumberValue());
4234 CHECK_EQ(6.6, a3->Get(v8::Integer::New(2))->NumberValue());
4235
4236 v8::Handle<Value> args4[] = { v8_num(7.7),
4237 v8_num(8.8),
4238 v8_num(9.9),
4239 v8_num(10.11) };
4240 Local<v8::Array> a4 = Local<v8::Array>::Cast(Foo->NewInstance(4, args4));
4241 CHECK_EQ(4, a4->Length());
4242 CHECK_EQ(7.7, a4->Get(v8::Integer::New(0))->NumberValue());
4243 CHECK_EQ(8.8, a4->Get(v8::Integer::New(1))->NumberValue());
4244 CHECK_EQ(9.9, a4->Get(v8::Integer::New(2))->NumberValue());
4245 CHECK_EQ(10.11, a4->Get(v8::Integer::New(3))->NumberValue());
4246}
4247
4248
4249static void CheckUncle(v8::TryCatch* try_catch) {
4250 CHECK(try_catch->HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00004251 String::Utf8Value str_value(try_catch->Exception());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004252 CHECK_EQ(*str_value, "uncle?");
4253 try_catch->Reset();
4254}
4255
4256
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004257THREADED_TEST(ConversionNumber) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004258 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004259 v8::HandleScope scope(env->GetIsolate());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004260 // Very large number.
4261 CompileRun("var obj = Math.pow(2,32) * 1237;");
4262 Local<Value> obj = env->Global()->Get(v8_str("obj"));
4263 CHECK_EQ(5312874545152.0, obj->ToNumber()->Value());
4264 CHECK_EQ(0, obj->ToInt32()->Value());
4265 CHECK(0u == obj->ToUint32()->Value()); // NOLINT - no CHECK_EQ for unsigned.
4266 // Large number.
4267 CompileRun("var obj = -1234567890123;");
4268 obj = env->Global()->Get(v8_str("obj"));
4269 CHECK_EQ(-1234567890123.0, obj->ToNumber()->Value());
4270 CHECK_EQ(-1912276171, obj->ToInt32()->Value());
4271 CHECK(2382691125u == obj->ToUint32()->Value()); // NOLINT
4272 // Small positive integer.
4273 CompileRun("var obj = 42;");
4274 obj = env->Global()->Get(v8_str("obj"));
4275 CHECK_EQ(42.0, obj->ToNumber()->Value());
4276 CHECK_EQ(42, obj->ToInt32()->Value());
4277 CHECK(42u == obj->ToUint32()->Value()); // NOLINT
4278 // Negative integer.
4279 CompileRun("var obj = -37;");
4280 obj = env->Global()->Get(v8_str("obj"));
4281 CHECK_EQ(-37.0, obj->ToNumber()->Value());
4282 CHECK_EQ(-37, obj->ToInt32()->Value());
4283 CHECK(4294967259u == obj->ToUint32()->Value()); // NOLINT
4284 // Positive non-int32 integer.
4285 CompileRun("var obj = 0x81234567;");
4286 obj = env->Global()->Get(v8_str("obj"));
4287 CHECK_EQ(2166572391.0, obj->ToNumber()->Value());
4288 CHECK_EQ(-2128394905, obj->ToInt32()->Value());
4289 CHECK(2166572391u == obj->ToUint32()->Value()); // NOLINT
4290 // Fraction.
4291 CompileRun("var obj = 42.3;");
4292 obj = env->Global()->Get(v8_str("obj"));
4293 CHECK_EQ(42.3, obj->ToNumber()->Value());
4294 CHECK_EQ(42, obj->ToInt32()->Value());
4295 CHECK(42u == obj->ToUint32()->Value()); // NOLINT
4296 // Large negative fraction.
4297 CompileRun("var obj = -5726623061.75;");
4298 obj = env->Global()->Get(v8_str("obj"));
4299 CHECK_EQ(-5726623061.75, obj->ToNumber()->Value());
4300 CHECK_EQ(-1431655765, obj->ToInt32()->Value());
4301 CHECK(2863311531u == obj->ToUint32()->Value()); // NOLINT
4302}
4303
4304
4305THREADED_TEST(isNumberType) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004306 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004307 v8::HandleScope scope(env->GetIsolate());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004308 // Very large number.
4309 CompileRun("var obj = Math.pow(2,32) * 1237;");
4310 Local<Value> obj = env->Global()->Get(v8_str("obj"));
4311 CHECK(!obj->IsInt32());
4312 CHECK(!obj->IsUint32());
4313 // Large negative number.
4314 CompileRun("var obj = -1234567890123;");
4315 obj = env->Global()->Get(v8_str("obj"));
4316 CHECK(!obj->IsInt32());
4317 CHECK(!obj->IsUint32());
4318 // Small positive integer.
4319 CompileRun("var obj = 42;");
4320 obj = env->Global()->Get(v8_str("obj"));
4321 CHECK(obj->IsInt32());
4322 CHECK(obj->IsUint32());
4323 // Negative integer.
4324 CompileRun("var obj = -37;");
4325 obj = env->Global()->Get(v8_str("obj"));
4326 CHECK(obj->IsInt32());
4327 CHECK(!obj->IsUint32());
4328 // Positive non-int32 integer.
4329 CompileRun("var obj = 0x81234567;");
4330 obj = env->Global()->Get(v8_str("obj"));
4331 CHECK(!obj->IsInt32());
4332 CHECK(obj->IsUint32());
4333 // Fraction.
4334 CompileRun("var obj = 42.3;");
4335 obj = env->Global()->Get(v8_str("obj"));
4336 CHECK(!obj->IsInt32());
4337 CHECK(!obj->IsUint32());
4338 // Large negative fraction.
4339 CompileRun("var obj = -5726623061.75;");
4340 obj = env->Global()->Get(v8_str("obj"));
4341 CHECK(!obj->IsInt32());
4342 CHECK(!obj->IsUint32());
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00004343 // Positive zero
4344 CompileRun("var obj = 0.0;");
4345 obj = env->Global()->Get(v8_str("obj"));
4346 CHECK(obj->IsInt32());
4347 CHECK(obj->IsUint32());
4348 // Positive zero
4349 CompileRun("var obj = -0.0;");
4350 obj = env->Global()->Get(v8_str("obj"));
4351 CHECK(!obj->IsInt32());
4352 CHECK(!obj->IsUint32());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004353}
4354
4355
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004356THREADED_TEST(ConversionException) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004357 LocalContext env;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00004358 v8::Isolate* isolate = env->GetIsolate();
4359 v8::HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004360 CompileRun(
4361 "function TestClass() { };"
4362 "TestClass.prototype.toString = function () { throw 'uncle?'; };"
4363 "var obj = new TestClass();");
4364 Local<Value> obj = env->Global()->Get(v8_str("obj"));
4365
4366 v8::TryCatch try_catch;
4367
4368 Local<Value> to_string_result = obj->ToString();
4369 CHECK(to_string_result.IsEmpty());
4370 CheckUncle(&try_catch);
4371
4372 Local<Value> to_number_result = obj->ToNumber();
4373 CHECK(to_number_result.IsEmpty());
4374 CheckUncle(&try_catch);
4375
4376 Local<Value> to_integer_result = obj->ToInteger();
4377 CHECK(to_integer_result.IsEmpty());
4378 CheckUncle(&try_catch);
4379
4380 Local<Value> to_uint32_result = obj->ToUint32();
4381 CHECK(to_uint32_result.IsEmpty());
4382 CheckUncle(&try_catch);
4383
4384 Local<Value> to_int32_result = obj->ToInt32();
4385 CHECK(to_int32_result.IsEmpty());
4386 CheckUncle(&try_catch);
4387
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00004388 Local<Value> to_object_result = v8::Undefined(isolate)->ToObject();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004389 CHECK(to_object_result.IsEmpty());
4390 CHECK(try_catch.HasCaught());
4391 try_catch.Reset();
4392
4393 int32_t int32_value = obj->Int32Value();
4394 CHECK_EQ(0, int32_value);
4395 CheckUncle(&try_catch);
4396
4397 uint32_t uint32_value = obj->Uint32Value();
4398 CHECK_EQ(0, uint32_value);
4399 CheckUncle(&try_catch);
4400
4401 double number_value = obj->NumberValue();
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00004402 CHECK_NE(0, std::isnan(number_value));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004403 CheckUncle(&try_catch);
4404
4405 int64_t integer_value = obj->IntegerValue();
4406 CHECK_EQ(0.0, static_cast<double>(integer_value));
4407 CheckUncle(&try_catch);
4408}
4409
4410
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00004411void ThrowFromC(const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004412 ApiTestFuzzer::Fuzz();
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00004413 args.GetIsolate()->ThrowException(v8_str("konto"));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004414}
4415
4416
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00004417void CCatcher(const v8::FunctionCallbackInfo<v8::Value>& args) {
4418 if (args.Length() < 1) {
4419 args.GetReturnValue().Set(false);
4420 return;
4421 }
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004422 v8::HandleScope scope(args.GetIsolate());
ager@chromium.org8bb60582008-12-11 12:02:20 +00004423 v8::TryCatch try_catch;
ager@chromium.org71daaf62009-04-01 07:22:49 +00004424 Local<Value> result = v8::Script::Compile(args[0]->ToString())->Run();
4425 CHECK(!try_catch.HasCaught() || result.IsEmpty());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00004426 args.GetReturnValue().Set(try_catch.HasCaught());
ager@chromium.org8bb60582008-12-11 12:02:20 +00004427}
4428
4429
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004430THREADED_TEST(APICatch) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00004431 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004432 Local<ObjectTemplate> templ = ObjectTemplate::New();
4433 templ->Set(v8_str("ThrowFromC"),
4434 v8::FunctionTemplate::New(ThrowFromC));
4435 LocalContext context(0, templ);
4436 CompileRun(
4437 "var thrown = false;"
4438 "try {"
4439 " ThrowFromC();"
4440 "} catch (e) {"
4441 " thrown = true;"
4442 "}");
4443 Local<Value> thrown = context->Global()->Get(v8_str("thrown"));
4444 CHECK(thrown->BooleanValue());
4445}
4446
4447
ager@chromium.org8bb60582008-12-11 12:02:20 +00004448THREADED_TEST(APIThrowTryCatch) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00004449 v8::HandleScope scope(CcTest::isolate());
ager@chromium.org8bb60582008-12-11 12:02:20 +00004450 Local<ObjectTemplate> templ = ObjectTemplate::New();
4451 templ->Set(v8_str("ThrowFromC"),
4452 v8::FunctionTemplate::New(ThrowFromC));
4453 LocalContext context(0, templ);
4454 v8::TryCatch try_catch;
4455 CompileRun("ThrowFromC();");
4456 CHECK(try_catch.HasCaught());
4457}
4458
4459
4460// Test that a try-finally block doesn't shadow a try-catch block
4461// when setting up an external handler.
ager@chromium.org71daaf62009-04-01 07:22:49 +00004462//
4463// BUG(271): Some of the exception propagation does not work on the
4464// ARM simulator because the simulator separates the C++ stack and the
4465// JS stack. This test therefore fails on the simulator. The test is
4466// not threaded to allow the threading tests to run on the simulator.
4467TEST(TryCatchInTryFinally) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00004468 v8::HandleScope scope(CcTest::isolate());
ager@chromium.org8bb60582008-12-11 12:02:20 +00004469 Local<ObjectTemplate> templ = ObjectTemplate::New();
4470 templ->Set(v8_str("CCatcher"),
4471 v8::FunctionTemplate::New(CCatcher));
4472 LocalContext context(0, templ);
4473 Local<Value> result = CompileRun("try {"
4474 " try {"
4475 " CCatcher('throw 7;');"
4476 " } finally {"
4477 " }"
4478 "} catch (e) {"
4479 "}");
4480 CHECK(result->IsTrue());
4481}
4482
4483
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00004484static void check_reference_error_message(
4485 v8::Handle<v8::Message> message,
4486 v8::Handle<v8::Value> data) {
4487 const char* reference_error = "Uncaught ReferenceError: asdf is not defined";
4488 CHECK(message->Get()->Equals(v8_str(reference_error)));
4489}
4490
4491
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00004492static void Fail(const v8::FunctionCallbackInfo<v8::Value>& args) {
kmillikin@chromium.org31b12772011-02-02 16:08:26 +00004493 ApiTestFuzzer::Fuzz();
4494 CHECK(false);
kmillikin@chromium.org31b12772011-02-02 16:08:26 +00004495}
4496
4497
4498// Test that overwritten methods are not invoked on uncaught exception
4499// formatting. However, they are invoked when performing normal error
4500// string conversions.
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00004501TEST(APIThrowMessageOverwrittenToString) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00004502 v8::HandleScope scope(CcTest::isolate());
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00004503 v8::V8::AddMessageListener(check_reference_error_message);
kmillikin@chromium.org31b12772011-02-02 16:08:26 +00004504 Local<ObjectTemplate> templ = ObjectTemplate::New();
4505 templ->Set(v8_str("fail"), v8::FunctionTemplate::New(Fail));
4506 LocalContext context(NULL, templ);
4507 CompileRun("asdf;");
4508 CompileRun("var limit = {};"
4509 "limit.valueOf = fail;"
4510 "Error.stackTraceLimit = limit;");
4511 CompileRun("asdf");
4512 CompileRun("Array.prototype.pop = fail;");
4513 CompileRun("Object.prototype.hasOwnProperty = fail;");
4514 CompileRun("Object.prototype.toString = function f() { return 'Yikes'; }");
whesse@chromium.org7a392b32011-01-31 11:30:36 +00004515 CompileRun("Number.prototype.toString = function f() { return 'Yikes'; }");
4516 CompileRun("String.prototype.toString = function f() { return 'Yikes'; }");
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00004517 CompileRun("ReferenceError.prototype.toString ="
4518 " function() { return 'Whoops' }");
4519 CompileRun("asdf;");
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00004520 CompileRun("ReferenceError.prototype.constructor.name = void 0;");
4521 CompileRun("asdf;");
4522 CompileRun("ReferenceError.prototype.constructor = void 0;");
4523 CompileRun("asdf;");
ager@chromium.org0ee099b2011-01-25 14:06:47 +00004524 CompileRun("ReferenceError.prototype.__proto__ = new Object();");
4525 CompileRun("asdf;");
4526 CompileRun("ReferenceError.prototype = new Object();");
4527 CompileRun("asdf;");
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00004528 v8::Handle<Value> string = CompileRun("try { asdf; } catch(e) { e + ''; }");
4529 CHECK(string->Equals(v8_str("Whoops")));
ager@chromium.org378b34e2011-01-28 08:04:38 +00004530 CompileRun("ReferenceError.prototype.constructor = new Object();"
4531 "ReferenceError.prototype.constructor.name = 1;"
4532 "Number.prototype.toString = function() { return 'Whoops'; };"
4533 "ReferenceError.prototype.toString = Object.prototype.toString;");
4534 CompileRun("asdf;");
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00004535 v8::V8::RemoveMessageListeners(check_reference_error_message);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00004536}
4537
4538
danno@chromium.org59400602013-08-13 17:09:37 +00004539static void check_custom_error_tostring(
yangguo@chromium.org304cc332012-07-24 07:59:48 +00004540 v8::Handle<v8::Message> message,
4541 v8::Handle<v8::Value> data) {
4542 const char* uncaught_error = "Uncaught MyError toString";
4543 CHECK(message->Get()->Equals(v8_str(uncaught_error)));
4544}
4545
4546
4547TEST(CustomErrorToString) {
yangguo@chromium.org304cc332012-07-24 07:59:48 +00004548 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004549 v8::HandleScope scope(context->GetIsolate());
danno@chromium.org59400602013-08-13 17:09:37 +00004550 v8::V8::AddMessageListener(check_custom_error_tostring);
yangguo@chromium.org304cc332012-07-24 07:59:48 +00004551 CompileRun(
4552 "function MyError(name, message) { "
4553 " this.name = name; "
4554 " this.message = message; "
4555 "} "
4556 "MyError.prototype = Object.create(Error.prototype); "
4557 "MyError.prototype.toString = function() { "
4558 " return 'MyError toString'; "
4559 "}; "
4560 "throw new MyError('my name', 'my message'); ");
danno@chromium.org59400602013-08-13 17:09:37 +00004561 v8::V8::RemoveMessageListeners(check_custom_error_tostring);
4562}
4563
4564
4565static void check_custom_error_message(
4566 v8::Handle<v8::Message> message,
4567 v8::Handle<v8::Value> data) {
4568 const char* uncaught_error = "Uncaught MyError: my message";
4569 printf("%s\n", *v8::String::Utf8Value(message->Get()));
4570 CHECK(message->Get()->Equals(v8_str(uncaught_error)));
4571}
4572
4573
4574TEST(CustomErrorMessage) {
4575 LocalContext context;
4576 v8::HandleScope scope(context->GetIsolate());
4577 v8::V8::AddMessageListener(check_custom_error_message);
4578
4579 // Handlebars.
4580 CompileRun(
4581 "function MyError(msg) { "
4582 " this.name = 'MyError'; "
4583 " this.message = msg; "
4584 "} "
4585 "MyError.prototype = new Error(); "
4586 "throw new MyError('my message'); ");
4587
4588 // Closure.
4589 CompileRun(
4590 "function MyError(msg) { "
4591 " this.name = 'MyError'; "
4592 " this.message = msg; "
4593 "} "
4594 "inherits = function(childCtor, parentCtor) { "
4595 " function tempCtor() {}; "
4596 " tempCtor.prototype = parentCtor.prototype; "
4597 " childCtor.superClass_ = parentCtor.prototype; "
4598 " childCtor.prototype = new tempCtor(); "
4599 " childCtor.prototype.constructor = childCtor; "
4600 "}; "
4601 "inherits(MyError, Error); "
4602 "throw new MyError('my message'); ");
4603
4604 // Object.create.
4605 CompileRun(
4606 "function MyError(msg) { "
4607 " this.name = 'MyError'; "
4608 " this.message = msg; "
4609 "} "
4610 "MyError.prototype = Object.create(Error.prototype); "
4611 "throw new MyError('my message'); ");
4612
yangguo@chromium.org304cc332012-07-24 07:59:48 +00004613 v8::V8::RemoveMessageListeners(check_custom_error_message);
4614}
4615
4616
ager@chromium.org8bb60582008-12-11 12:02:20 +00004617static void receive_message(v8::Handle<v8::Message> message,
4618 v8::Handle<v8::Value> data) {
ager@chromium.org71daaf62009-04-01 07:22:49 +00004619 message->Get();
ager@chromium.org8bb60582008-12-11 12:02:20 +00004620 message_received = true;
4621}
4622
4623
4624TEST(APIThrowMessage) {
4625 message_received = false;
machenbach@chromium.org528ce022013-09-23 14:09:36 +00004626 v8::HandleScope scope(CcTest::isolate());
ager@chromium.org8bb60582008-12-11 12:02:20 +00004627 v8::V8::AddMessageListener(receive_message);
4628 Local<ObjectTemplate> templ = ObjectTemplate::New();
4629 templ->Set(v8_str("ThrowFromC"),
4630 v8::FunctionTemplate::New(ThrowFromC));
4631 LocalContext context(0, templ);
4632 CompileRun("ThrowFromC();");
4633 CHECK(message_received);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00004634 v8::V8::RemoveMessageListeners(receive_message);
ager@chromium.org8bb60582008-12-11 12:02:20 +00004635}
4636
4637
4638TEST(APIThrowMessageAndVerboseTryCatch) {
4639 message_received = false;
machenbach@chromium.org528ce022013-09-23 14:09:36 +00004640 v8::HandleScope scope(CcTest::isolate());
ager@chromium.org8bb60582008-12-11 12:02:20 +00004641 v8::V8::AddMessageListener(receive_message);
4642 Local<ObjectTemplate> templ = ObjectTemplate::New();
4643 templ->Set(v8_str("ThrowFromC"),
4644 v8::FunctionTemplate::New(ThrowFromC));
4645 LocalContext context(0, templ);
4646 v8::TryCatch try_catch;
4647 try_catch.SetVerbose(true);
ager@chromium.org71daaf62009-04-01 07:22:49 +00004648 Local<Value> result = CompileRun("ThrowFromC();");
ager@chromium.org8bb60582008-12-11 12:02:20 +00004649 CHECK(try_catch.HasCaught());
ager@chromium.org71daaf62009-04-01 07:22:49 +00004650 CHECK(result.IsEmpty());
ager@chromium.org8bb60582008-12-11 12:02:20 +00004651 CHECK(message_received);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00004652 v8::V8::RemoveMessageListeners(receive_message);
ager@chromium.org8bb60582008-12-11 12:02:20 +00004653}
4654
4655
karlklose@chromium.org44bc7082011-04-11 12:33:05 +00004656TEST(APIStackOverflowAndVerboseTryCatch) {
4657 message_received = false;
karlklose@chromium.org44bc7082011-04-11 12:33:05 +00004658 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004659 v8::HandleScope scope(context->GetIsolate());
4660 v8::V8::AddMessageListener(receive_message);
karlklose@chromium.org44bc7082011-04-11 12:33:05 +00004661 v8::TryCatch try_catch;
4662 try_catch.SetVerbose(true);
4663 Local<Value> result = CompileRun("function foo() { foo(); } foo();");
4664 CHECK(try_catch.HasCaught());
4665 CHECK(result.IsEmpty());
4666 CHECK(message_received);
4667 v8::V8::RemoveMessageListeners(receive_message);
4668}
4669
4670
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004671THREADED_TEST(ExternalScriptException) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00004672 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004673 Local<ObjectTemplate> templ = ObjectTemplate::New();
4674 templ->Set(v8_str("ThrowFromC"),
4675 v8::FunctionTemplate::New(ThrowFromC));
4676 LocalContext context(0, templ);
4677
4678 v8::TryCatch try_catch;
4679 Local<Script> script
4680 = Script::Compile(v8_str("ThrowFromC(); throw 'panama';"));
4681 Local<Value> result = script->Run();
4682 CHECK(result.IsEmpty());
4683 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00004684 String::Utf8Value exception_value(try_catch.Exception());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004685 CHECK_EQ("konto", *exception_value);
4686}
4687
4688
4689
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00004690void CThrowCountDown(const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004691 ApiTestFuzzer::Fuzz();
4692 CHECK_EQ(4, args.Length());
4693 int count = args[0]->Int32Value();
4694 int cInterval = args[2]->Int32Value();
4695 if (count == 0) {
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00004696 args.GetIsolate()->ThrowException(v8_str("FromC"));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00004697 return;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004698 } else {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00004699 Local<v8::Object> global =
4700 args.GetIsolate()->GetCurrentContext()->Global();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004701 Local<Value> fun = global->Get(v8_str("JSThrowCountDown"));
4702 v8::Handle<Value> argv[] = { v8_num(count - 1),
4703 args[1],
4704 args[2],
4705 args[3] };
4706 if (count % cInterval == 0) {
4707 v8::TryCatch try_catch;
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004708 Local<Value> result = fun.As<Function>()->Call(global, 4, argv);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004709 int expected = args[3]->Int32Value();
4710 if (try_catch.HasCaught()) {
4711 CHECK_EQ(expected, count);
ager@chromium.org71daaf62009-04-01 07:22:49 +00004712 CHECK(result.IsEmpty());
machenbach@chromium.org528ce022013-09-23 14:09:36 +00004713 CHECK(!CcTest::i_isolate()->has_scheduled_exception());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004714 } else {
4715 CHECK_NE(expected, count);
4716 }
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00004717 args.GetReturnValue().Set(result);
4718 return;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004719 } else {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00004720 args.GetReturnValue().Set(fun.As<Function>()->Call(global, 4, argv));
4721 return;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004722 }
4723 }
4724}
4725
4726
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00004727void JSCheck(const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004728 ApiTestFuzzer::Fuzz();
4729 CHECK_EQ(3, args.Length());
4730 bool equality = args[0]->BooleanValue();
4731 int count = args[1]->Int32Value();
4732 int expected = args[2]->Int32Value();
4733 if (equality) {
4734 CHECK_EQ(count, expected);
4735 } else {
4736 CHECK_NE(count, expected);
4737 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004738}
4739
4740
ager@chromium.org8bb60582008-12-11 12:02:20 +00004741THREADED_TEST(EvalInTryFinally) {
ager@chromium.org8bb60582008-12-11 12:02:20 +00004742 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004743 v8::HandleScope scope(context->GetIsolate());
ager@chromium.org8bb60582008-12-11 12:02:20 +00004744 v8::TryCatch try_catch;
4745 CompileRun("(function() {"
4746 " try {"
4747 " eval('asldkf (*&^&*^');"
4748 " } finally {"
4749 " return;"
4750 " }"
4751 "})()");
4752 CHECK(!try_catch.HasCaught());
4753}
4754
4755
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004756// This test works by making a stack of alternating JavaScript and C
4757// activations. These activations set up exception handlers with regular
4758// intervals, one interval for C activations and another for JavaScript
4759// activations. When enough activations have been created an exception is
4760// thrown and we check that the right activation catches the exception and that
4761// no other activations do. The right activation is always the topmost one with
4762// a handler, regardless of whether it is in JavaScript or C.
4763//
4764// The notation used to describe a test case looks like this:
4765//
4766// *JS[4] *C[3] @JS[2] C[1] JS[0]
4767//
4768// Each entry is an activation, either JS or C. The index is the count at that
4769// level. Stars identify activations with exception handlers, the @ identifies
4770// the exception handler that should catch the exception.
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(ExceptionOrder) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00004777 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004778 Local<ObjectTemplate> templ = ObjectTemplate::New();
4779 templ->Set(v8_str("check"), v8::FunctionTemplate::New(JSCheck));
4780 templ->Set(v8_str("CThrowCountDown"),
4781 v8::FunctionTemplate::New(CThrowCountDown));
4782 LocalContext context(0, templ);
4783 CompileRun(
4784 "function JSThrowCountDown(count, jsInterval, cInterval, expected) {"
4785 " if (count == 0) throw 'FromJS';"
4786 " if (count % jsInterval == 0) {"
4787 " try {"
4788 " var value = CThrowCountDown(count - 1,"
4789 " jsInterval,"
4790 " cInterval,"
4791 " expected);"
4792 " check(false, count, expected);"
4793 " return value;"
4794 " } catch (e) {"
4795 " check(true, count, expected);"
4796 " }"
4797 " } else {"
4798 " return CThrowCountDown(count - 1, jsInterval, cInterval, expected);"
4799 " }"
4800 "}");
4801 Local<Function> fun =
4802 Local<Function>::Cast(context->Global()->Get(v8_str("JSThrowCountDown")));
4803
4804 const int argc = 4;
4805 // count jsInterval cInterval expected
4806
4807 // *JS[4] *C[3] @JS[2] C[1] JS[0]
4808 v8::Handle<Value> a0[argc] = { v8_num(4), v8_num(2), v8_num(3), v8_num(2) };
4809 fun->Call(fun, argc, a0);
4810
4811 // JS[5] *C[4] JS[3] @C[2] JS[1] C[0]
4812 v8::Handle<Value> a1[argc] = { v8_num(5), v8_num(6), v8_num(1), v8_num(2) };
4813 fun->Call(fun, argc, a1);
4814
4815 // JS[6] @C[5] JS[4] C[3] JS[2] C[1] JS[0]
4816 v8::Handle<Value> a2[argc] = { v8_num(6), v8_num(7), v8_num(5), v8_num(5) };
4817 fun->Call(fun, argc, a2);
4818
4819 // @JS[6] C[5] JS[4] C[3] JS[2] C[1] JS[0]
4820 v8::Handle<Value> a3[argc] = { v8_num(6), v8_num(6), v8_num(7), v8_num(6) };
4821 fun->Call(fun, argc, a3);
4822
4823 // JS[6] *C[5] @JS[4] C[3] JS[2] C[1] JS[0]
4824 v8::Handle<Value> a4[argc] = { v8_num(6), v8_num(4), v8_num(5), v8_num(4) };
4825 fun->Call(fun, argc, a4);
4826
4827 // JS[6] C[5] *JS[4] @C[3] JS[2] C[1] JS[0]
4828 v8::Handle<Value> a5[argc] = { v8_num(6), v8_num(4), v8_num(3), v8_num(3) };
4829 fun->Call(fun, argc, a5);
4830}
4831
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00004832
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00004833void ThrowValue(const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004834 ApiTestFuzzer::Fuzz();
4835 CHECK_EQ(1, args.Length());
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00004836 args.GetIsolate()->ThrowException(args[0]);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004837}
4838
4839
4840THREADED_TEST(ThrowValues) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00004841 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004842 Local<ObjectTemplate> templ = ObjectTemplate::New();
4843 templ->Set(v8_str("Throw"), v8::FunctionTemplate::New(ThrowValue));
4844 LocalContext context(0, templ);
4845 v8::Handle<v8::Array> result = v8::Handle<v8::Array>::Cast(CompileRun(
4846 "function Run(obj) {"
4847 " try {"
4848 " Throw(obj);"
4849 " } catch (e) {"
4850 " return e;"
4851 " }"
4852 " return 'no exception';"
4853 "}"
4854 "[Run('str'), Run(1), Run(0), Run(null), Run(void 0)];"));
4855 CHECK_EQ(5, result->Length());
4856 CHECK(result->Get(v8::Integer::New(0))->IsString());
4857 CHECK(result->Get(v8::Integer::New(1))->IsNumber());
4858 CHECK_EQ(1, result->Get(v8::Integer::New(1))->Int32Value());
4859 CHECK(result->Get(v8::Integer::New(2))->IsNumber());
4860 CHECK_EQ(0, result->Get(v8::Integer::New(2))->Int32Value());
4861 CHECK(result->Get(v8::Integer::New(3))->IsNull());
4862 CHECK(result->Get(v8::Integer::New(4))->IsUndefined());
4863}
4864
4865
4866THREADED_TEST(CatchZero) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004867 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004868 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004869 v8::TryCatch try_catch;
4870 CHECK(!try_catch.HasCaught());
4871 Script::Compile(v8_str("throw 10"))->Run();
4872 CHECK(try_catch.HasCaught());
4873 CHECK_EQ(10, try_catch.Exception()->Int32Value());
4874 try_catch.Reset();
4875 CHECK(!try_catch.HasCaught());
4876 Script::Compile(v8_str("throw 0"))->Run();
4877 CHECK(try_catch.HasCaught());
4878 CHECK_EQ(0, try_catch.Exception()->Int32Value());
4879}
4880
4881
4882THREADED_TEST(CatchExceptionFromWith) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004883 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004884 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004885 v8::TryCatch try_catch;
4886 CHECK(!try_catch.HasCaught());
4887 Script::Compile(v8_str("var o = {}; with (o) { throw 42; }"))->Run();
4888 CHECK(try_catch.HasCaught());
4889}
4890
4891
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00004892THREADED_TEST(TryCatchAndFinallyHidingException) {
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00004893 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004894 v8::HandleScope scope(context->GetIsolate());
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00004895 v8::TryCatch try_catch;
4896 CHECK(!try_catch.HasCaught());
4897 CompileRun("function f(k) { try { this[k]; } finally { return 0; } };");
4898 CompileRun("f({toString: function() { throw 42; }});");
4899 CHECK(!try_catch.HasCaught());
4900}
4901
4902
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00004903void WithTryCatch(const v8::FunctionCallbackInfo<v8::Value>& args) {
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00004904 v8::TryCatch try_catch;
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00004905}
4906
4907
4908THREADED_TEST(TryCatchAndFinally) {
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00004909 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004910 v8::HandleScope scope(context->GetIsolate());
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00004911 context->Global()->Set(
4912 v8_str("native_with_try_catch"),
4913 v8::FunctionTemplate::New(WithTryCatch)->GetFunction());
4914 v8::TryCatch try_catch;
4915 CHECK(!try_catch.HasCaught());
4916 CompileRun(
4917 "try {\n"
4918 " throw new Error('a');\n"
4919 "} finally {\n"
4920 " native_with_try_catch();\n"
4921 "}\n");
4922 CHECK(try_catch.HasCaught());
4923}
4924
4925
mmassi@chromium.org49a44672012-12-04 13:52:03 +00004926static void TryCatchNestedHelper(int depth) {
4927 if (depth > 0) {
4928 v8::TryCatch try_catch;
4929 try_catch.SetVerbose(true);
4930 TryCatchNestedHelper(depth - 1);
4931 CHECK(try_catch.HasCaught());
4932 try_catch.ReThrow();
4933 } else {
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00004934 CcTest::isolate()->ThrowException(v8_str("back"));
mmassi@chromium.org49a44672012-12-04 13:52:03 +00004935 }
4936}
4937
4938
4939TEST(TryCatchNested) {
4940 v8::V8::Initialize();
mmassi@chromium.org49a44672012-12-04 13:52:03 +00004941 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004942 v8::HandleScope scope(context->GetIsolate());
mmassi@chromium.org49a44672012-12-04 13:52:03 +00004943 v8::TryCatch try_catch;
4944 TryCatchNestedHelper(5);
4945 CHECK(try_catch.HasCaught());
4946 CHECK_EQ(0, strcmp(*v8::String::Utf8Value(try_catch.Exception()), "back"));
4947}
4948
4949
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +00004950void TryCatchMixedNestingCheck(v8::TryCatch* try_catch) {
4951 CHECK(try_catch->HasCaught());
4952 Handle<Message> message = try_catch->Message();
4953 Handle<Value> resource = message->GetScriptResourceName();
4954 CHECK_EQ(0, strcmp(*v8::String::Utf8Value(resource), "inner"));
4955 CHECK_EQ(0, strcmp(*v8::String::Utf8Value(message->Get()),
4956 "Uncaught Error: a"));
4957 CHECK_EQ(1, message->GetLineNumber());
4958 CHECK_EQ(6, message->GetStartColumn());
4959}
4960
4961
4962void TryCatchMixedNestingHelper(
4963 const v8::FunctionCallbackInfo<v8::Value>& args) {
4964 ApiTestFuzzer::Fuzz();
4965 v8::TryCatch try_catch;
4966 CompileRunWithOrigin("throw new Error('a');\n", "inner", 0, 0);
4967 CHECK(try_catch.HasCaught());
4968 TryCatchMixedNestingCheck(&try_catch);
4969 try_catch.ReThrow();
4970}
4971
4972
4973// This test ensures that an outer TryCatch in the following situation:
4974// C++/TryCatch -> JS -> C++/TryCatch -> JS w/ SyntaxError
4975// does not clobber the Message object generated for the inner TryCatch.
4976// This exercises the ability of TryCatch.ReThrow() to restore the
4977// inner pending Message before throwing the exception again.
4978TEST(TryCatchMixedNesting) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00004979 v8::HandleScope scope(CcTest::isolate());
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +00004980 v8::V8::Initialize();
4981 v8::TryCatch try_catch;
4982 Local<ObjectTemplate> templ = ObjectTemplate::New();
4983 templ->Set(v8_str("TryCatchMixedNestingHelper"),
4984 v8::FunctionTemplate::New(TryCatchMixedNestingHelper));
4985 LocalContext context(0, templ);
4986 CompileRunWithOrigin("TryCatchMixedNestingHelper();\n", "outer", 1, 1);
4987 TryCatchMixedNestingCheck(&try_catch);
4988}
4989
4990
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004991THREADED_TEST(Equality) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004992 LocalContext context;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00004993 v8::Isolate* isolate = context->GetIsolate();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004994 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004995 // Check that equality works at all before relying on CHECK_EQ
4996 CHECK(v8_str("a")->Equals(v8_str("a")));
4997 CHECK(!v8_str("a")->Equals(v8_str("b")));
4998
4999 CHECK_EQ(v8_str("a"), v8_str("a"));
5000 CHECK_NE(v8_str("a"), v8_str("b"));
5001 CHECK_EQ(v8_num(1), v8_num(1));
5002 CHECK_EQ(v8_num(1.00), v8_num(1));
5003 CHECK_NE(v8_num(1), v8_num(2));
5004
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00005005 // Assume String is not internalized.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005006 CHECK(v8_str("a")->StrictEquals(v8_str("a")));
5007 CHECK(!v8_str("a")->StrictEquals(v8_str("b")));
5008 CHECK(!v8_str("5")->StrictEquals(v8_num(5)));
5009 CHECK(v8_num(1)->StrictEquals(v8_num(1)));
5010 CHECK(!v8_num(1)->StrictEquals(v8_num(2)));
machenbach@chromium.org3d079fe2013-09-25 08:19:55 +00005011 CHECK(v8_num(0.0)->StrictEquals(v8_num(-0.0)));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005012 Local<Value> not_a_number = v8_num(i::OS::nan_value());
5013 CHECK(!not_a_number->StrictEquals(not_a_number));
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00005014 CHECK(v8::False(isolate)->StrictEquals(v8::False(isolate)));
5015 CHECK(!v8::False(isolate)->StrictEquals(v8::Undefined(isolate)));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005016
5017 v8::Handle<v8::Object> obj = v8::Object::New();
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00005018 v8::Persistent<v8::Object> alias(isolate, obj);
rossberg@chromium.org79e79022013-06-03 15:43:46 +00005019 CHECK(v8::Local<v8::Object>::New(isolate, alias)->StrictEquals(obj));
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +00005020 alias.Dispose();
machenbach@chromium.org3d079fe2013-09-25 08:19:55 +00005021
5022 CHECK(v8_str("a")->SameValue(v8_str("a")));
5023 CHECK(!v8_str("a")->SameValue(v8_str("b")));
5024 CHECK(!v8_str("5")->SameValue(v8_num(5)));
5025 CHECK(v8_num(1)->SameValue(v8_num(1)));
5026 CHECK(!v8_num(1)->SameValue(v8_num(2)));
5027 CHECK(!v8_num(0.0)->SameValue(v8_num(-0.0)));
5028 CHECK(not_a_number->SameValue(not_a_number));
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00005029 CHECK(v8::False(isolate)->SameValue(v8::False(isolate)));
5030 CHECK(!v8::False(isolate)->SameValue(v8::Undefined(isolate)));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005031}
5032
5033
5034THREADED_TEST(MultiRun) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005035 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005036 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005037 Local<Script> script = Script::Compile(v8_str("x"));
5038 for (int i = 0; i < 10; i++)
5039 script->Run();
5040}
5041
5042
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005043static void GetXValue(Local<String> name,
5044 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005045 ApiTestFuzzer::Fuzz();
5046 CHECK_EQ(info.Data(), v8_str("donut"));
5047 CHECK_EQ(name, v8_str("x"));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005048 info.GetReturnValue().Set(name);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005049}
5050
5051
5052THREADED_TEST(SimplePropertyRead) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005053 LocalContext context;
5054 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005055 Local<ObjectTemplate> templ = ObjectTemplate::New();
5056 templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005057 context->Global()->Set(v8_str("obj"), templ->NewInstance());
5058 Local<Script> script = Script::Compile(v8_str("obj.x"));
5059 for (int i = 0; i < 10; i++) {
5060 Local<Value> result = script->Run();
5061 CHECK_EQ(result, v8_str("x"));
5062 }
5063}
5064
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00005065
ager@chromium.org5c838252010-02-19 08:53:10 +00005066THREADED_TEST(DefinePropertyOnAPIAccessor) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005067 LocalContext context;
5068 v8::HandleScope scope(context->GetIsolate());
ager@chromium.org5c838252010-02-19 08:53:10 +00005069 Local<ObjectTemplate> templ = ObjectTemplate::New();
5070 templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
ager@chromium.org5c838252010-02-19 08:53:10 +00005071 context->Global()->Set(v8_str("obj"), templ->NewInstance());
5072
5073 // Uses getOwnPropertyDescriptor to check the configurable status
5074 Local<Script> script_desc
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00005075 = Script::Compile(v8_str("var prop = Object.getOwnPropertyDescriptor( "
ager@chromium.org5c838252010-02-19 08:53:10 +00005076 "obj, 'x');"
5077 "prop.configurable;"));
5078 Local<Value> result = script_desc->Run();
5079 CHECK_EQ(result->BooleanValue(), true);
5080
5081 // Redefine get - but still configurable
5082 Local<Script> script_define
5083 = Script::Compile(v8_str("var desc = { get: function(){return 42; },"
5084 " configurable: true };"
5085 "Object.defineProperty(obj, 'x', desc);"
5086 "obj.x"));
5087 result = script_define->Run();
5088 CHECK_EQ(result, v8_num(42));
5089
5090 // Check that the accessor is still configurable
5091 result = script_desc->Run();
5092 CHECK_EQ(result->BooleanValue(), true);
5093
5094 // Redefine to a non-configurable
5095 script_define
5096 = Script::Compile(v8_str("var desc = { get: function(){return 43; },"
5097 " configurable: false };"
5098 "Object.defineProperty(obj, 'x', desc);"
5099 "obj.x"));
5100 result = script_define->Run();
5101 CHECK_EQ(result, v8_num(43));
5102 result = script_desc->Run();
5103 CHECK_EQ(result->BooleanValue(), false);
5104
5105 // Make sure that it is not possible to redefine again
5106 v8::TryCatch try_catch;
5107 result = script_define->Run();
5108 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00005109 String::Utf8Value exception_value(try_catch.Exception());
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00005110 CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x");
ager@chromium.org5c838252010-02-19 08:53:10 +00005111}
5112
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00005113
ager@chromium.org5c838252010-02-19 08:53:10 +00005114THREADED_TEST(DefinePropertyOnDefineGetterSetter) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00005115 v8::HandleScope scope(CcTest::isolate());
ager@chromium.org5c838252010-02-19 08:53:10 +00005116 Local<ObjectTemplate> templ = ObjectTemplate::New();
5117 templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
5118 LocalContext context;
5119 context->Global()->Set(v8_str("obj"), templ->NewInstance());
5120
5121 Local<Script> script_desc = Script::Compile(v8_str("var prop ="
5122 "Object.getOwnPropertyDescriptor( "
5123 "obj, 'x');"
5124 "prop.configurable;"));
5125 Local<Value> result = script_desc->Run();
5126 CHECK_EQ(result->BooleanValue(), true);
5127
5128 Local<Script> script_define =
5129 Script::Compile(v8_str("var desc = {get: function(){return 42; },"
5130 " configurable: true };"
5131 "Object.defineProperty(obj, 'x', desc);"
5132 "obj.x"));
5133 result = script_define->Run();
5134 CHECK_EQ(result, v8_num(42));
5135
5136
5137 result = script_desc->Run();
5138 CHECK_EQ(result->BooleanValue(), true);
5139
5140
5141 script_define =
5142 Script::Compile(v8_str("var desc = {get: function(){return 43; },"
5143 " configurable: false };"
5144 "Object.defineProperty(obj, 'x', desc);"
5145 "obj.x"));
5146 result = script_define->Run();
5147 CHECK_EQ(result, v8_num(43));
5148 result = script_desc->Run();
5149
5150 CHECK_EQ(result->BooleanValue(), false);
5151
5152 v8::TryCatch try_catch;
5153 result = script_define->Run();
5154 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00005155 String::Utf8Value exception_value(try_catch.Exception());
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00005156 CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x");
ager@chromium.org5c838252010-02-19 08:53:10 +00005157}
5158
5159
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00005160static v8::Handle<v8::Object> GetGlobalProperty(LocalContext* context,
5161 char const* name) {
5162 return v8::Handle<v8::Object>::Cast((*context)->Global()->Get(v8_str(name)));
5163}
ager@chromium.org5c838252010-02-19 08:53:10 +00005164
5165
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00005166THREADED_TEST(DefineAPIAccessorOnObject) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00005167 v8::HandleScope scope(CcTest::isolate());
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00005168 Local<ObjectTemplate> templ = ObjectTemplate::New();
5169 LocalContext context;
5170
5171 context->Global()->Set(v8_str("obj1"), templ->NewInstance());
5172 CompileRun("var obj2 = {};");
5173
5174 CHECK(CompileRun("obj1.x")->IsUndefined());
5175 CHECK(CompileRun("obj2.x")->IsUndefined());
5176
5177 CHECK(GetGlobalProperty(&context, "obj1")->
5178 SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5179
5180 ExpectString("obj1.x", "x");
5181 CHECK(CompileRun("obj2.x")->IsUndefined());
5182
5183 CHECK(GetGlobalProperty(&context, "obj2")->
5184 SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5185
5186 ExpectString("obj1.x", "x");
5187 ExpectString("obj2.x", "x");
5188
5189 ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
5190 ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
5191
5192 CompileRun("Object.defineProperty(obj1, 'x',"
5193 "{ get: function() { return 'y'; }, configurable: true })");
5194
5195 ExpectString("obj1.x", "y");
5196 ExpectString("obj2.x", "x");
5197
5198 CompileRun("Object.defineProperty(obj2, 'x',"
5199 "{ get: function() { return 'y'; }, configurable: true })");
5200
5201 ExpectString("obj1.x", "y");
5202 ExpectString("obj2.x", "y");
5203
5204 ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
5205 ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
5206
5207 CHECK(GetGlobalProperty(&context, "obj1")->
5208 SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5209 CHECK(GetGlobalProperty(&context, "obj2")->
5210 SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5211
5212 ExpectString("obj1.x", "x");
5213 ExpectString("obj2.x", "x");
5214
5215 ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
5216 ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
5217
5218 // Define getters/setters, but now make them not configurable.
5219 CompileRun("Object.defineProperty(obj1, 'x',"
5220 "{ get: function() { return 'z'; }, configurable: false })");
5221 CompileRun("Object.defineProperty(obj2, 'x',"
5222 "{ get: function() { return 'z'; }, configurable: false })");
5223
5224 ExpectTrue("!Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
5225 ExpectTrue("!Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
5226
5227 ExpectString("obj1.x", "z");
5228 ExpectString("obj2.x", "z");
5229
5230 CHECK(!GetGlobalProperty(&context, "obj1")->
5231 SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5232 CHECK(!GetGlobalProperty(&context, "obj2")->
5233 SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5234
5235 ExpectString("obj1.x", "z");
5236 ExpectString("obj2.x", "z");
5237}
5238
5239
5240THREADED_TEST(DontDeleteAPIAccessorsCannotBeOverriden) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00005241 v8::HandleScope scope(CcTest::isolate());
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00005242 Local<ObjectTemplate> templ = ObjectTemplate::New();
5243 LocalContext context;
5244
5245 context->Global()->Set(v8_str("obj1"), templ->NewInstance());
5246 CompileRun("var obj2 = {};");
5247
5248 CHECK(GetGlobalProperty(&context, "obj1")->SetAccessor(
5249 v8_str("x"),
5250 GetXValue, NULL,
5251 v8_str("donut"), v8::DEFAULT, v8::DontDelete));
5252 CHECK(GetGlobalProperty(&context, "obj2")->SetAccessor(
5253 v8_str("x"),
5254 GetXValue, NULL,
5255 v8_str("donut"), v8::DEFAULT, v8::DontDelete));
5256
5257 ExpectString("obj1.x", "x");
5258 ExpectString("obj2.x", "x");
5259
5260 ExpectTrue("!Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
5261 ExpectTrue("!Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
5262
5263 CHECK(!GetGlobalProperty(&context, "obj1")->
5264 SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5265 CHECK(!GetGlobalProperty(&context, "obj2")->
5266 SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5267
5268 {
5269 v8::TryCatch try_catch;
5270 CompileRun("Object.defineProperty(obj1, 'x',"
5271 "{get: function() { return 'func'; }})");
5272 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00005273 String::Utf8Value exception_value(try_catch.Exception());
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00005274 CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x");
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00005275 }
5276 {
5277 v8::TryCatch try_catch;
5278 CompileRun("Object.defineProperty(obj2, 'x',"
5279 "{get: function() { return 'func'; }})");
5280 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00005281 String::Utf8Value exception_value(try_catch.Exception());
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00005282 CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x");
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00005283 }
5284}
5285
5286
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005287static void Get239Value(Local<String> name,
5288 const v8::PropertyCallbackInfo<v8::Value>& info) {
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00005289 ApiTestFuzzer::Fuzz();
5290 CHECK_EQ(info.Data(), v8_str("donut"));
5291 CHECK_EQ(name, v8_str("239"));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005292 info.GetReturnValue().Set(name);
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00005293}
5294
5295
5296THREADED_TEST(ElementAPIAccessor) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00005297 v8::HandleScope scope(CcTest::isolate());
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00005298 Local<ObjectTemplate> templ = ObjectTemplate::New();
5299 LocalContext context;
5300
5301 context->Global()->Set(v8_str("obj1"), templ->NewInstance());
5302 CompileRun("var obj2 = {};");
5303
5304 CHECK(GetGlobalProperty(&context, "obj1")->SetAccessor(
5305 v8_str("239"),
5306 Get239Value, NULL,
5307 v8_str("donut")));
5308 CHECK(GetGlobalProperty(&context, "obj2")->SetAccessor(
5309 v8_str("239"),
5310 Get239Value, NULL,
5311 v8_str("donut")));
5312
5313 ExpectString("obj1[239]", "239");
5314 ExpectString("obj2[239]", "239");
5315 ExpectString("obj1['239']", "239");
5316 ExpectString("obj2['239']", "239");
5317}
5318
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005319
5320v8::Persistent<Value> xValue;
5321
5322
5323static void SetXValue(Local<String> name,
5324 Local<Value> value,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005325 const v8::PropertyCallbackInfo<void>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005326 CHECK_EQ(value, v8_num(4));
5327 CHECK_EQ(info.Data(), v8_str("donut"));
5328 CHECK_EQ(name, v8_str("x"));
5329 CHECK(xValue.IsEmpty());
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00005330 xValue.Reset(info.GetIsolate(), value);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005331}
5332
5333
5334THREADED_TEST(SimplePropertyWrite) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00005335 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005336 Local<ObjectTemplate> templ = ObjectTemplate::New();
5337 templ->SetAccessor(v8_str("x"), GetXValue, SetXValue, v8_str("donut"));
5338 LocalContext context;
5339 context->Global()->Set(v8_str("obj"), templ->NewInstance());
5340 Local<Script> script = Script::Compile(v8_str("obj.x = 4"));
5341 for (int i = 0; i < 10; i++) {
5342 CHECK(xValue.IsEmpty());
5343 script->Run();
machenbach@chromium.org528ce022013-09-23 14:09:36 +00005344 CHECK_EQ(v8_num(4), Local<Value>::New(CcTest::isolate(), xValue));
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +00005345 xValue.Dispose();
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00005346 xValue.Clear();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005347 }
5348}
5349
5350
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00005351THREADED_TEST(SetterOnly) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00005352 v8::HandleScope scope(CcTest::isolate());
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00005353 Local<ObjectTemplate> templ = ObjectTemplate::New();
5354 templ->SetAccessor(v8_str("x"), NULL, SetXValue, v8_str("donut"));
5355 LocalContext context;
5356 context->Global()->Set(v8_str("obj"), templ->NewInstance());
5357 Local<Script> script = Script::Compile(v8_str("obj.x = 4; obj.x"));
5358 for (int i = 0; i < 10; i++) {
5359 CHECK(xValue.IsEmpty());
5360 script->Run();
machenbach@chromium.org528ce022013-09-23 14:09:36 +00005361 CHECK_EQ(v8_num(4), Local<Value>::New(CcTest::isolate(), xValue));
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +00005362 xValue.Dispose();
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00005363 xValue.Clear();
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00005364 }
5365}
5366
5367
5368THREADED_TEST(NoAccessors) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00005369 v8::HandleScope scope(CcTest::isolate());
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00005370 Local<ObjectTemplate> templ = ObjectTemplate::New();
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00005371 templ->SetAccessor(v8_str("x"),
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005372 static_cast<v8::AccessorGetterCallback>(NULL),
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00005373 NULL,
5374 v8_str("donut"));
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00005375 LocalContext context;
5376 context->Global()->Set(v8_str("obj"), templ->NewInstance());
5377 Local<Script> script = Script::Compile(v8_str("obj.x = 4; obj.x"));
5378 for (int i = 0; i < 10; i++) {
5379 script->Run();
5380 }
5381}
5382
5383
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005384static void XPropertyGetter(Local<String> property,
5385 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005386 ApiTestFuzzer::Fuzz();
5387 CHECK(info.Data()->IsUndefined());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005388 info.GetReturnValue().Set(property);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005389}
5390
5391
ager@chromium.orgeadaf222009-06-16 09:43:10 +00005392THREADED_TEST(NamedInterceptorPropertyRead) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00005393 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005394 Local<ObjectTemplate> templ = ObjectTemplate::New();
5395 templ->SetNamedPropertyHandler(XPropertyGetter);
5396 LocalContext context;
5397 context->Global()->Set(v8_str("obj"), templ->NewInstance());
5398 Local<Script> script = Script::Compile(v8_str("obj.x"));
5399 for (int i = 0; i < 10; i++) {
5400 Local<Value> result = script->Run();
5401 CHECK_EQ(result, v8_str("x"));
5402 }
5403}
5404
ager@chromium.orgeadaf222009-06-16 09:43:10 +00005405
ager@chromium.orgb26c50a2010-03-26 09:27:16 +00005406THREADED_TEST(NamedInterceptorDictionaryIC) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00005407 v8::HandleScope scope(CcTest::isolate());
ager@chromium.orgb26c50a2010-03-26 09:27:16 +00005408 Local<ObjectTemplate> templ = ObjectTemplate::New();
5409 templ->SetNamedPropertyHandler(XPropertyGetter);
5410 LocalContext context;
5411 // Create an object with a named interceptor.
5412 context->Global()->Set(v8_str("interceptor_obj"), templ->NewInstance());
5413 Local<Script> script = Script::Compile(v8_str("interceptor_obj.x"));
5414 for (int i = 0; i < 10; i++) {
5415 Local<Value> result = script->Run();
5416 CHECK_EQ(result, v8_str("x"));
5417 }
5418 // Create a slow case object and a function accessing a property in
5419 // that slow case object (with dictionary probing in generated
5420 // code). Then force object with a named interceptor into slow-case,
5421 // pass it to the function, and check that the interceptor is called
5422 // instead of accessing the local property.
5423 Local<Value> result =
5424 CompileRun("function get_x(o) { return o.x; };"
5425 "var obj = { x : 42, y : 0 };"
5426 "delete obj.y;"
5427 "for (var i = 0; i < 10; i++) get_x(obj);"
5428 "interceptor_obj.x = 42;"
5429 "interceptor_obj.y = 10;"
5430 "delete interceptor_obj.y;"
5431 "get_x(interceptor_obj)");
5432 CHECK_EQ(result, v8_str("x"));
5433}
5434
5435
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00005436THREADED_TEST(NamedInterceptorDictionaryICMultipleContext) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00005437 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00005438 v8::HandleScope scope(isolate);
5439 v8::Local<Context> context1 = Context::New(isolate);
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00005440
5441 context1->Enter();
5442 Local<ObjectTemplate> templ = ObjectTemplate::New();
5443 templ->SetNamedPropertyHandler(XPropertyGetter);
5444 // Create an object with a named interceptor.
5445 v8::Local<v8::Object> object = templ->NewInstance();
5446 context1->Global()->Set(v8_str("interceptor_obj"), object);
5447
5448 // Force the object into the slow case.
5449 CompileRun("interceptor_obj.y = 0;"
5450 "delete interceptor_obj.y;");
5451 context1->Exit();
5452
5453 {
5454 // Introduce the object into a different context.
5455 // Repeat named loads to exercise ICs.
5456 LocalContext context2;
5457 context2->Global()->Set(v8_str("interceptor_obj"), object);
5458 Local<Value> result =
5459 CompileRun("function get_x(o) { return o.x; }"
5460 "interceptor_obj.x = 42;"
5461 "for (var i=0; i != 10; i++) {"
5462 " get_x(interceptor_obj);"
5463 "}"
5464 "get_x(interceptor_obj)");
5465 // Check that the interceptor was actually invoked.
5466 CHECK_EQ(result, v8_str("x"));
5467 }
5468
5469 // Return to the original context and force some object to the slow case
5470 // to cause the NormalizedMapCache to verify.
5471 context1->Enter();
5472 CompileRun("var obj = { x : 0 }; delete obj.x;");
5473 context1->Exit();
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00005474}
5475
5476
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005477static void SetXOnPrototypeGetter(
5478 Local<String> property,
5479 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.org5c838252010-02-19 08:53:10 +00005480 // Set x on the prototype object and do not handle the get request.
5481 v8::Handle<v8::Value> proto = info.Holder()->GetPrototype();
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00005482 proto.As<v8::Object>()->Set(v8_str("x"), v8::Integer::New(23));
ager@chromium.org5c838252010-02-19 08:53:10 +00005483}
5484
5485
5486// This is a regression test for http://crbug.com/20104. Map
5487// transitions should not interfere with post interceptor lookup.
5488THREADED_TEST(NamedInterceptorMapTransitionRead) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00005489 v8::HandleScope scope(CcTest::isolate());
ager@chromium.org5c838252010-02-19 08:53:10 +00005490 Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New();
5491 Local<v8::ObjectTemplate> instance_template
5492 = function_template->InstanceTemplate();
5493 instance_template->SetNamedPropertyHandler(SetXOnPrototypeGetter);
5494 LocalContext context;
5495 context->Global()->Set(v8_str("F"), function_template->GetFunction());
5496 // Create an instance of F and introduce a map transition for x.
5497 CompileRun("var o = new F(); o.x = 23;");
5498 // Create an instance of F and invoke the getter. The result should be 23.
5499 Local<Value> result = CompileRun("o = new F(); o.x");
5500 CHECK_EQ(result->Int32Value(), 23);
5501}
5502
5503
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005504static void IndexedPropertyGetter(
5505 uint32_t index,
5506 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.orgeadaf222009-06-16 09:43:10 +00005507 ApiTestFuzzer::Fuzz();
5508 if (index == 37) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005509 info.GetReturnValue().Set(v8_num(625));
ager@chromium.orgeadaf222009-06-16 09:43:10 +00005510 }
ager@chromium.orgeadaf222009-06-16 09:43:10 +00005511}
5512
5513
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005514static void IndexedPropertySetter(
5515 uint32_t index,
5516 Local<Value> value,
5517 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.orgeadaf222009-06-16 09:43:10 +00005518 ApiTestFuzzer::Fuzz();
5519 if (index == 39) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005520 info.GetReturnValue().Set(value);
ager@chromium.orgeadaf222009-06-16 09:43:10 +00005521 }
ager@chromium.orgeadaf222009-06-16 09:43:10 +00005522}
5523
5524
5525THREADED_TEST(IndexedInterceptorWithIndexedAccessor) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00005526 v8::HandleScope scope(CcTest::isolate());
ager@chromium.orgeadaf222009-06-16 09:43:10 +00005527 Local<ObjectTemplate> templ = ObjectTemplate::New();
5528 templ->SetIndexedPropertyHandler(IndexedPropertyGetter,
5529 IndexedPropertySetter);
5530 LocalContext context;
5531 context->Global()->Set(v8_str("obj"), templ->NewInstance());
5532 Local<Script> getter_script = Script::Compile(v8_str(
5533 "obj.__defineGetter__(\"3\", function(){return 5;});obj[3];"));
5534 Local<Script> setter_script = Script::Compile(v8_str(
5535 "obj.__defineSetter__(\"17\", function(val){this.foo = val;});"
5536 "obj[17] = 23;"
5537 "obj.foo;"));
5538 Local<Script> interceptor_setter_script = Script::Compile(v8_str(
5539 "obj.__defineSetter__(\"39\", function(val){this.foo = \"hit\";});"
5540 "obj[39] = 47;"
5541 "obj.foo;")); // This setter should not run, due to the interceptor.
5542 Local<Script> interceptor_getter_script = Script::Compile(v8_str(
5543 "obj[37];"));
5544 Local<Value> result = getter_script->Run();
5545 CHECK_EQ(v8_num(5), result);
5546 result = setter_script->Run();
5547 CHECK_EQ(v8_num(23), result);
5548 result = interceptor_setter_script->Run();
5549 CHECK_EQ(v8_num(23), result);
5550 result = interceptor_getter_script->Run();
5551 CHECK_EQ(v8_num(625), result);
5552}
5553
5554
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005555static void UnboxedDoubleIndexedPropertyGetter(
ricow@chromium.org9fa09672011-07-25 11:05:35 +00005556 uint32_t index,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005557 const v8::PropertyCallbackInfo<v8::Value>& info) {
ricow@chromium.org9fa09672011-07-25 11:05:35 +00005558 ApiTestFuzzer::Fuzz();
5559 if (index < 25) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005560 info.GetReturnValue().Set(v8_num(index));
ricow@chromium.org9fa09672011-07-25 11:05:35 +00005561 }
ricow@chromium.org9fa09672011-07-25 11:05:35 +00005562}
5563
5564
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005565static void UnboxedDoubleIndexedPropertySetter(
ricow@chromium.org9fa09672011-07-25 11:05:35 +00005566 uint32_t index,
5567 Local<Value> value,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005568 const v8::PropertyCallbackInfo<v8::Value>& info) {
ricow@chromium.org9fa09672011-07-25 11:05:35 +00005569 ApiTestFuzzer::Fuzz();
5570 if (index < 25) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005571 info.GetReturnValue().Set(v8_num(index));
ricow@chromium.org9fa09672011-07-25 11:05:35 +00005572 }
ricow@chromium.org9fa09672011-07-25 11:05:35 +00005573}
5574
5575
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005576void UnboxedDoubleIndexedPropertyEnumerator(
5577 const v8::PropertyCallbackInfo<v8::Array>& info) {
ricow@chromium.org9fa09672011-07-25 11:05:35 +00005578 // Force the list of returned keys to be stored in a FastDoubleArray.
5579 Local<Script> indexed_property_names_script = Script::Compile(v8_str(
5580 "keys = new Array(); keys[125000] = 1;"
5581 "for(i = 0; i < 80000; i++) { keys[i] = i; };"
5582 "keys.length = 25; keys;"));
5583 Local<Value> result = indexed_property_names_script->Run();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005584 info.GetReturnValue().Set(Local<v8::Array>::Cast(result));
ricow@chromium.org9fa09672011-07-25 11:05:35 +00005585}
5586
5587
5588// Make sure that the the interceptor code in the runtime properly handles
5589// merging property name lists for double-array-backed arrays.
5590THREADED_TEST(IndexedInterceptorUnboxedDoubleWithIndexedAccessor) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00005591 v8::HandleScope scope(CcTest::isolate());
ricow@chromium.org9fa09672011-07-25 11:05:35 +00005592 Local<ObjectTemplate> templ = ObjectTemplate::New();
5593 templ->SetIndexedPropertyHandler(UnboxedDoubleIndexedPropertyGetter,
5594 UnboxedDoubleIndexedPropertySetter,
5595 0,
5596 0,
5597 UnboxedDoubleIndexedPropertyEnumerator);
5598 LocalContext context;
5599 context->Global()->Set(v8_str("obj"), templ->NewInstance());
5600 // When obj is created, force it to be Stored in a FastDoubleArray.
5601 Local<Script> create_unboxed_double_script = Script::Compile(v8_str(
5602 "obj[125000] = 1; for(i = 0; i < 80000; i+=2) { obj[i] = i; } "
5603 "key_count = 0; "
5604 "for (x in obj) {key_count++;};"
5605 "obj;"));
5606 Local<Value> result = create_unboxed_double_script->Run();
5607 CHECK(result->ToObject()->HasRealIndexedProperty(2000));
5608 Local<Script> key_count_check = Script::Compile(v8_str(
5609 "key_count;"));
5610 result = key_count_check->Run();
5611 CHECK_EQ(v8_num(40013), result);
5612}
5613
5614
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005615void NonStrictArgsIndexedPropertyEnumerator(
5616 const v8::PropertyCallbackInfo<v8::Array>& info) {
rossberg@chromium.org28a37082011-08-22 11:03:23 +00005617 // Force the list of returned keys to be stored in a Arguments object.
5618 Local<Script> indexed_property_names_script = Script::Compile(v8_str(
5619 "function f(w,x) {"
5620 " return arguments;"
5621 "}"
5622 "keys = f(0, 1, 2, 3);"
5623 "keys;"));
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00005624 Local<Object> result =
5625 Local<Object>::Cast(indexed_property_names_script->Run());
5626 // Have to populate the handle manually, as it's not Cast-able.
5627 i::Handle<i::JSObject> o =
5628 v8::Utils::OpenHandle<Object, i::JSObject>(result);
5629 i::Handle<i::JSArray> array(reinterpret_cast<i::JSArray*>(*o));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005630 info.GetReturnValue().Set(v8::Utils::ToLocal(array));
rossberg@chromium.org28a37082011-08-22 11:03:23 +00005631}
5632
5633
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005634static void NonStrictIndexedPropertyGetter(
rossberg@chromium.org28a37082011-08-22 11:03:23 +00005635 uint32_t index,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005636 const v8::PropertyCallbackInfo<v8::Value>& info) {
rossberg@chromium.org28a37082011-08-22 11:03:23 +00005637 ApiTestFuzzer::Fuzz();
5638 if (index < 4) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005639 info.GetReturnValue().Set(v8_num(index));
rossberg@chromium.org28a37082011-08-22 11:03:23 +00005640 }
rossberg@chromium.org28a37082011-08-22 11:03:23 +00005641}
5642
5643
5644// Make sure that the the interceptor code in the runtime properly handles
5645// merging property name lists for non-string arguments arrays.
5646THREADED_TEST(IndexedInterceptorNonStrictArgsWithIndexedAccessor) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00005647 v8::HandleScope scope(CcTest::isolate());
rossberg@chromium.org28a37082011-08-22 11:03:23 +00005648 Local<ObjectTemplate> templ = ObjectTemplate::New();
5649 templ->SetIndexedPropertyHandler(NonStrictIndexedPropertyGetter,
5650 0,
5651 0,
5652 0,
5653 NonStrictArgsIndexedPropertyEnumerator);
5654 LocalContext context;
5655 context->Global()->Set(v8_str("obj"), templ->NewInstance());
5656 Local<Script> create_args_script =
5657 Script::Compile(v8_str(
5658 "var key_count = 0;"
5659 "for (x in obj) {key_count++;} key_count;"));
5660 Local<Value> result = create_args_script->Run();
5661 CHECK_EQ(v8_num(4), result);
5662}
5663
5664
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005665static void IdentityIndexedPropertyGetter(
kasperl@chromium.orgeac059f2010-01-25 11:02:06 +00005666 uint32_t index,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005667 const v8::PropertyCallbackInfo<v8::Value>& info) {
5668 info.GetReturnValue().Set(index);
kasperl@chromium.orgeac059f2010-01-25 11:02:06 +00005669}
5670
5671
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00005672THREADED_TEST(IndexedInterceptorWithGetOwnPropertyDescriptor) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00005673 v8::HandleScope scope(CcTest::isolate());
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00005674 Local<ObjectTemplate> templ = ObjectTemplate::New();
5675 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
5676
5677 LocalContext context;
5678 context->Global()->Set(v8_str("obj"), templ->NewInstance());
5679
5680 // Check fast object case.
5681 const char* fast_case_code =
5682 "Object.getOwnPropertyDescriptor(obj, 0).value.toString()";
5683 ExpectString(fast_case_code, "0");
5684
5685 // Check slow case.
5686 const char* slow_case_code =
5687 "obj.x = 1; delete obj.x;"
5688 "Object.getOwnPropertyDescriptor(obj, 1).value.toString()";
5689 ExpectString(slow_case_code, "1");
5690}
5691
5692
kasperl@chromium.orgeac059f2010-01-25 11:02:06 +00005693THREADED_TEST(IndexedInterceptorWithNoSetter) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00005694 v8::HandleScope scope(CcTest::isolate());
kasperl@chromium.orgeac059f2010-01-25 11:02:06 +00005695 Local<ObjectTemplate> templ = ObjectTemplate::New();
5696 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
5697
5698 LocalContext context;
5699 context->Global()->Set(v8_str("obj"), templ->NewInstance());
5700
5701 const char* code =
5702 "try {"
5703 " obj[0] = 239;"
5704 " for (var i = 0; i < 100; i++) {"
5705 " var v = obj[0];"
5706 " if (v != 0) throw 'Wrong value ' + v + ' at iteration ' + i;"
5707 " }"
5708 " 'PASSED'"
5709 "} catch(e) {"
5710 " e"
5711 "}";
5712 ExpectString(code, "PASSED");
5713}
5714
5715
ager@chromium.org5c838252010-02-19 08:53:10 +00005716THREADED_TEST(IndexedInterceptorWithAccessorCheck) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00005717 v8::HandleScope scope(CcTest::isolate());
ager@chromium.org5c838252010-02-19 08:53:10 +00005718 Local<ObjectTemplate> templ = ObjectTemplate::New();
5719 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
5720
5721 LocalContext context;
5722 Local<v8::Object> obj = templ->NewInstance();
5723 obj->TurnOnAccessCheck();
5724 context->Global()->Set(v8_str("obj"), obj);
5725
5726 const char* code =
5727 "try {"
5728 " for (var i = 0; i < 100; i++) {"
5729 " var v = obj[0];"
5730 " if (v != undefined) throw 'Wrong value ' + v + ' at iteration ' + i;"
5731 " }"
5732 " 'PASSED'"
5733 "} catch(e) {"
5734 " e"
5735 "}";
5736 ExpectString(code, "PASSED");
5737}
5738
5739
5740THREADED_TEST(IndexedInterceptorWithAccessorCheckSwitchedOn) {
5741 i::FLAG_allow_natives_syntax = true;
machenbach@chromium.org528ce022013-09-23 14:09:36 +00005742 v8::HandleScope scope(CcTest::isolate());
ager@chromium.org5c838252010-02-19 08:53:10 +00005743 Local<ObjectTemplate> templ = ObjectTemplate::New();
5744 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
5745
5746 LocalContext context;
5747 Local<v8::Object> obj = templ->NewInstance();
5748 context->Global()->Set(v8_str("obj"), obj);
5749
5750 const char* code =
5751 "try {"
5752 " for (var i = 0; i < 100; i++) {"
5753 " var expected = i;"
5754 " if (i == 5) {"
5755 " %EnableAccessChecks(obj);"
5756 " expected = undefined;"
5757 " }"
5758 " var v = obj[i];"
5759 " if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
5760 " if (i == 5) %DisableAccessChecks(obj);"
5761 " }"
5762 " 'PASSED'"
5763 "} catch(e) {"
5764 " e"
5765 "}";
5766 ExpectString(code, "PASSED");
5767}
5768
5769
5770THREADED_TEST(IndexedInterceptorWithDifferentIndices) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00005771 v8::HandleScope scope(CcTest::isolate());
ager@chromium.org5c838252010-02-19 08:53:10 +00005772 Local<ObjectTemplate> templ = ObjectTemplate::New();
5773 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
5774
5775 LocalContext context;
5776 Local<v8::Object> obj = templ->NewInstance();
5777 context->Global()->Set(v8_str("obj"), obj);
5778
5779 const char* code =
5780 "try {"
5781 " for (var i = 0; i < 100; i++) {"
5782 " var v = obj[i];"
5783 " if (v != i) throw 'Wrong value ' + v + ' at iteration ' + i;"
5784 " }"
5785 " 'PASSED'"
5786 "} catch(e) {"
5787 " e"
5788 "}";
5789 ExpectString(code, "PASSED");
5790}
5791
5792
kmillikin@chromium.orgf05f2912010-09-30 10:07:24 +00005793THREADED_TEST(IndexedInterceptorWithNegativeIndices) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00005794 v8::HandleScope scope(CcTest::isolate());
kmillikin@chromium.orgf05f2912010-09-30 10:07:24 +00005795 Local<ObjectTemplate> templ = ObjectTemplate::New();
5796 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
5797
5798 LocalContext context;
5799 Local<v8::Object> obj = templ->NewInstance();
5800 context->Global()->Set(v8_str("obj"), obj);
5801
5802 const char* code =
5803 "try {"
5804 " for (var i = 0; i < 100; i++) {"
5805 " var expected = i;"
5806 " var key = i;"
5807 " if (i == 25) {"
5808 " key = -1;"
5809 " expected = undefined;"
5810 " }"
5811 " if (i == 50) {"
5812 " /* probe minimal Smi number on 32-bit platforms */"
5813 " key = -(1 << 30);"
5814 " expected = undefined;"
5815 " }"
5816 " if (i == 75) {"
5817 " /* probe minimal Smi number on 64-bit platforms */"
5818 " key = 1 << 31;"
5819 " expected = undefined;"
5820 " }"
5821 " var v = obj[key];"
5822 " if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
5823 " }"
5824 " 'PASSED'"
5825 "} catch(e) {"
5826 " e"
5827 "}";
5828 ExpectString(code, "PASSED");
5829}
5830
5831
ager@chromium.org5c838252010-02-19 08:53:10 +00005832THREADED_TEST(IndexedInterceptorWithNotSmiLookup) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00005833 v8::HandleScope scope(CcTest::isolate());
ager@chromium.org5c838252010-02-19 08:53:10 +00005834 Local<ObjectTemplate> templ = ObjectTemplate::New();
5835 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
5836
5837 LocalContext context;
5838 Local<v8::Object> obj = templ->NewInstance();
5839 context->Global()->Set(v8_str("obj"), obj);
5840
5841 const char* code =
5842 "try {"
5843 " for (var i = 0; i < 100; i++) {"
5844 " var expected = i;"
kmillikin@chromium.orgf05f2912010-09-30 10:07:24 +00005845 " var key = i;"
ager@chromium.org5c838252010-02-19 08:53:10 +00005846 " if (i == 50) {"
kmillikin@chromium.orgf05f2912010-09-30 10:07:24 +00005847 " key = 'foobar';"
ager@chromium.org5c838252010-02-19 08:53:10 +00005848 " expected = undefined;"
5849 " }"
kmillikin@chromium.orgf05f2912010-09-30 10:07:24 +00005850 " var v = obj[key];"
ager@chromium.org5c838252010-02-19 08:53:10 +00005851 " if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
5852 " }"
5853 " 'PASSED'"
5854 "} catch(e) {"
5855 " e"
5856 "}";
5857 ExpectString(code, "PASSED");
5858}
5859
5860
5861THREADED_TEST(IndexedInterceptorGoingMegamorphic) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00005862 v8::HandleScope scope(CcTest::isolate());
ager@chromium.org5c838252010-02-19 08:53:10 +00005863 Local<ObjectTemplate> templ = ObjectTemplate::New();
5864 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
5865
5866 LocalContext context;
5867 Local<v8::Object> obj = templ->NewInstance();
5868 context->Global()->Set(v8_str("obj"), obj);
5869
5870 const char* code =
5871 "var original = obj;"
5872 "try {"
5873 " for (var i = 0; i < 100; i++) {"
5874 " var expected = i;"
5875 " if (i == 50) {"
5876 " obj = {50: 'foobar'};"
5877 " expected = 'foobar';"
5878 " }"
5879 " var v = obj[i];"
5880 " if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
5881 " if (i == 50) obj = original;"
5882 " }"
5883 " 'PASSED'"
5884 "} catch(e) {"
5885 " e"
5886 "}";
5887 ExpectString(code, "PASSED");
5888}
5889
5890
5891THREADED_TEST(IndexedInterceptorReceiverTurningSmi) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00005892 v8::HandleScope scope(CcTest::isolate());
ager@chromium.org5c838252010-02-19 08:53:10 +00005893 Local<ObjectTemplate> templ = ObjectTemplate::New();
5894 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
5895
5896 LocalContext context;
5897 Local<v8::Object> obj = templ->NewInstance();
5898 context->Global()->Set(v8_str("obj"), obj);
5899
5900 const char* code =
5901 "var original = obj;"
5902 "try {"
5903 " for (var i = 0; i < 100; i++) {"
5904 " var expected = i;"
5905 " if (i == 5) {"
5906 " obj = 239;"
5907 " expected = undefined;"
5908 " }"
5909 " var v = obj[i];"
5910 " if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
5911 " if (i == 5) obj = original;"
5912 " }"
5913 " 'PASSED'"
5914 "} catch(e) {"
5915 " e"
5916 "}";
5917 ExpectString(code, "PASSED");
5918}
5919
5920
5921THREADED_TEST(IndexedInterceptorOnProto) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00005922 v8::HandleScope scope(CcTest::isolate());
ager@chromium.org5c838252010-02-19 08:53:10 +00005923 Local<ObjectTemplate> templ = ObjectTemplate::New();
5924 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
5925
5926 LocalContext context;
5927 Local<v8::Object> obj = templ->NewInstance();
5928 context->Global()->Set(v8_str("obj"), obj);
5929
5930 const char* code =
5931 "var o = {__proto__: obj};"
5932 "try {"
5933 " for (var i = 0; i < 100; i++) {"
5934 " var v = o[i];"
5935 " if (v != i) throw 'Wrong value ' + v + ' at iteration ' + i;"
5936 " }"
5937 " 'PASSED'"
5938 "} catch(e) {"
5939 " e"
5940 "}";
5941 ExpectString(code, "PASSED");
5942}
5943
5944
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005945THREADED_TEST(MultiContexts) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00005946 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005947 v8::Handle<ObjectTemplate> templ = ObjectTemplate::New();
5948 templ->Set(v8_str("dummy"), v8::FunctionTemplate::New(DummyCallHandler));
5949
5950 Local<String> password = v8_str("Password");
5951
5952 // Create an environment
5953 LocalContext context0(0, templ);
5954 context0->SetSecurityToken(password);
5955 v8::Handle<v8::Object> global0 = context0->Global();
5956 global0->Set(v8_str("custom"), v8_num(1234));
5957 CHECK_EQ(1234, global0->Get(v8_str("custom"))->Int32Value());
5958
5959 // Create an independent environment
5960 LocalContext context1(0, templ);
5961 context1->SetSecurityToken(password);
5962 v8::Handle<v8::Object> global1 = context1->Global();
5963 global1->Set(v8_str("custom"), v8_num(1234));
5964 CHECK_NE(global0, global1);
5965 CHECK_EQ(1234, global0->Get(v8_str("custom"))->Int32Value());
5966 CHECK_EQ(1234, global1->Get(v8_str("custom"))->Int32Value());
5967
5968 // Now create a new context with the old global
5969 LocalContext context2(0, templ, global1);
5970 context2->SetSecurityToken(password);
5971 v8::Handle<v8::Object> global2 = context2->Global();
5972 CHECK_EQ(global1, global2);
5973 CHECK_EQ(0, global1->Get(v8_str("custom"))->Int32Value());
5974 CHECK_EQ(0, global2->Get(v8_str("custom"))->Int32Value());
5975}
5976
5977
5978THREADED_TEST(FunctionPrototypeAcrossContexts) {
5979 // Make sure that functions created by cloning boilerplates cannot
5980 // communicate through their __proto__ field.
5981
machenbach@chromium.org528ce022013-09-23 14:09:36 +00005982 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005983
5984 LocalContext env0;
5985 v8::Handle<v8::Object> global0 =
5986 env0->Global();
5987 v8::Handle<v8::Object> object0 =
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00005988 global0->Get(v8_str("Object")).As<v8::Object>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005989 v8::Handle<v8::Object> tostring0 =
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00005990 object0->Get(v8_str("toString")).As<v8::Object>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005991 v8::Handle<v8::Object> proto0 =
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00005992 tostring0->Get(v8_str("__proto__")).As<v8::Object>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005993 proto0->Set(v8_str("custom"), v8_num(1234));
5994
5995 LocalContext env1;
5996 v8::Handle<v8::Object> global1 =
5997 env1->Global();
5998 v8::Handle<v8::Object> object1 =
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00005999 global1->Get(v8_str("Object")).As<v8::Object>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006000 v8::Handle<v8::Object> tostring1 =
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00006001 object1->Get(v8_str("toString")).As<v8::Object>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006002 v8::Handle<v8::Object> proto1 =
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00006003 tostring1->Get(v8_str("__proto__")).As<v8::Object>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006004 CHECK(!proto1->Has(v8_str("custom")));
6005}
6006
6007
6008THREADED_TEST(Regress892105) {
6009 // Make sure that object and array literals created by cloning
6010 // boilerplates cannot communicate through their __proto__
6011 // field. This is rather difficult to check, but we try to add stuff
6012 // to Object.prototype and Array.prototype and create a new
6013 // environment. This should succeed.
6014
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006015 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006016
6017 Local<String> source = v8_str("Object.prototype.obj = 1234;"
6018 "Array.prototype.arr = 4567;"
6019 "8901");
6020
6021 LocalContext env0;
6022 Local<Script> script0 = Script::Compile(source);
6023 CHECK_EQ(8901.0, script0->Run()->NumberValue());
6024
6025 LocalContext env1;
6026 Local<Script> script1 = Script::Compile(source);
6027 CHECK_EQ(8901.0, script1->Run()->NumberValue());
6028}
6029
6030
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006031THREADED_TEST(UndetectableObject) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006032 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00006033 v8::HandleScope scope(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006034
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00006035 Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006036 desc->InstanceTemplate()->MarkAsUndetectable(); // undetectable
6037
6038 Local<v8::Object> obj = desc->GetFunction()->NewInstance();
6039 env->Global()->Set(v8_str("undetectable"), obj);
6040
6041 ExpectString("undetectable.toString()", "[object Object]");
6042 ExpectString("typeof undetectable", "undefined");
6043 ExpectString("typeof(undetectable)", "undefined");
6044 ExpectBoolean("typeof undetectable == 'undefined'", true);
6045 ExpectBoolean("typeof undetectable == 'object'", false);
6046 ExpectBoolean("if (undetectable) { true; } else { false; }", false);
6047 ExpectBoolean("!undetectable", true);
6048
6049 ExpectObject("true&&undetectable", obj);
6050 ExpectBoolean("false&&undetectable", false);
6051 ExpectBoolean("true||undetectable", true);
6052 ExpectObject("false||undetectable", obj);
6053
6054 ExpectObject("undetectable&&true", obj);
6055 ExpectObject("undetectable&&false", obj);
6056 ExpectBoolean("undetectable||true", true);
6057 ExpectBoolean("undetectable||false", false);
6058
6059 ExpectBoolean("undetectable==null", true);
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00006060 ExpectBoolean("null==undetectable", true);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006061 ExpectBoolean("undetectable==undefined", true);
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00006062 ExpectBoolean("undefined==undetectable", true);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006063 ExpectBoolean("undetectable==undetectable", true);
6064
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00006065
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006066 ExpectBoolean("undetectable===null", false);
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00006067 ExpectBoolean("null===undetectable", false);
6068 ExpectBoolean("undetectable===undefined", false);
6069 ExpectBoolean("undefined===undetectable", false);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006070 ExpectBoolean("undetectable===undetectable", true);
6071}
6072
6073
ager@chromium.org04921a82011-06-27 13:21:41 +00006074THREADED_TEST(VoidLiteral) {
ager@chromium.org04921a82011-06-27 13:21:41 +00006075 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00006076 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org04921a82011-06-27 13:21:41 +00006077
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00006078 Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New();
ager@chromium.org04921a82011-06-27 13:21:41 +00006079 desc->InstanceTemplate()->MarkAsUndetectable(); // undetectable
6080
6081 Local<v8::Object> obj = desc->GetFunction()->NewInstance();
6082 env->Global()->Set(v8_str("undetectable"), obj);
6083
6084 ExpectBoolean("undefined == void 0", true);
6085 ExpectBoolean("undetectable == void 0", true);
6086 ExpectBoolean("null == void 0", true);
6087 ExpectBoolean("undefined === void 0", true);
6088 ExpectBoolean("undetectable === void 0", false);
6089 ExpectBoolean("null === void 0", false);
6090
6091 ExpectBoolean("void 0 == undefined", true);
6092 ExpectBoolean("void 0 == undetectable", true);
6093 ExpectBoolean("void 0 == null", true);
6094 ExpectBoolean("void 0 === undefined", true);
6095 ExpectBoolean("void 0 === undetectable", false);
6096 ExpectBoolean("void 0 === null", false);
6097
6098 ExpectString("(function() {"
6099 " try {"
6100 " return x === void 0;"
6101 " } catch(e) {"
6102 " return e.toString();"
6103 " }"
6104 "})()",
6105 "ReferenceError: x is not defined");
6106 ExpectString("(function() {"
6107 " try {"
6108 " return void 0 === x;"
6109 " } catch(e) {"
6110 " return e.toString();"
6111 " }"
6112 "})()",
6113 "ReferenceError: x is not defined");
6114}
6115
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00006116
6117THREADED_TEST(ExtensibleOnUndetectable) {
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00006118 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00006119 v8::HandleScope scope(env->GetIsolate());
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00006120
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00006121 Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New();
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00006122 desc->InstanceTemplate()->MarkAsUndetectable(); // undetectable
6123
6124 Local<v8::Object> obj = desc->GetFunction()->NewInstance();
6125 env->Global()->Set(v8_str("undetectable"), obj);
6126
6127 Local<String> source = v8_str("undetectable.x = 42;"
6128 "undetectable.x");
6129
6130 Local<Script> script = Script::Compile(source);
6131
6132 CHECK_EQ(v8::Integer::New(42), script->Run());
6133
6134 ExpectBoolean("Object.isExtensible(undetectable)", true);
6135
6136 source = v8_str("Object.preventExtensions(undetectable);");
6137 script = Script::Compile(source);
6138 script->Run();
6139 ExpectBoolean("Object.isExtensible(undetectable)", false);
6140
6141 source = v8_str("undetectable.y = 2000;");
6142 script = Script::Compile(source);
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00006143 script->Run();
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00006144 ExpectBoolean("undetectable.y == undefined", true);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00006145}
6146
6147
6148
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006149THREADED_TEST(UndetectableString) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006150 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00006151 v8::HandleScope scope(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006152
6153 Local<String> obj = String::NewUndetectable("foo");
6154 env->Global()->Set(v8_str("undetectable"), obj);
6155
6156 ExpectString("undetectable", "foo");
6157 ExpectString("typeof undetectable", "undefined");
6158 ExpectString("typeof(undetectable)", "undefined");
6159 ExpectBoolean("typeof undetectable == 'undefined'", true);
6160 ExpectBoolean("typeof undetectable == 'string'", false);
6161 ExpectBoolean("if (undetectable) { true; } else { false; }", false);
6162 ExpectBoolean("!undetectable", true);
6163
6164 ExpectObject("true&&undetectable", obj);
6165 ExpectBoolean("false&&undetectable", false);
6166 ExpectBoolean("true||undetectable", true);
6167 ExpectObject("false||undetectable", obj);
6168
6169 ExpectObject("undetectable&&true", obj);
6170 ExpectObject("undetectable&&false", obj);
6171 ExpectBoolean("undetectable||true", true);
6172 ExpectBoolean("undetectable||false", false);
6173
6174 ExpectBoolean("undetectable==null", true);
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00006175 ExpectBoolean("null==undetectable", true);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006176 ExpectBoolean("undetectable==undefined", true);
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00006177 ExpectBoolean("undefined==undetectable", true);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006178 ExpectBoolean("undetectable==undetectable", true);
6179
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00006180
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006181 ExpectBoolean("undetectable===null", false);
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00006182 ExpectBoolean("null===undetectable", false);
6183 ExpectBoolean("undetectable===undefined", false);
6184 ExpectBoolean("undefined===undetectable", false);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006185 ExpectBoolean("undetectable===undetectable", true);
6186}
6187
6188
vegorov@chromium.org7304bca2011-05-16 12:14:13 +00006189TEST(UndetectableOptimized) {
6190 i::FLAG_allow_natives_syntax = true;
vegorov@chromium.org7304bca2011-05-16 12:14:13 +00006191 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00006192 v8::HandleScope scope(env->GetIsolate());
vegorov@chromium.org7304bca2011-05-16 12:14:13 +00006193
6194 Local<String> obj = String::NewUndetectable("foo");
6195 env->Global()->Set(v8_str("undetectable"), obj);
6196 env->Global()->Set(v8_str("detectable"), v8_str("bar"));
6197
6198 ExpectString(
6199 "function testBranch() {"
6200 " if (!%_IsUndetectableObject(undetectable)) throw 1;"
6201 " if (%_IsUndetectableObject(detectable)) throw 2;"
6202 "}\n"
6203 "function testBool() {"
6204 " var b1 = !%_IsUndetectableObject(undetectable);"
6205 " var b2 = %_IsUndetectableObject(detectable);"
6206 " if (b1) throw 3;"
6207 " if (b2) throw 4;"
6208 " return b1 == b2;"
6209 "}\n"
6210 "%OptimizeFunctionOnNextCall(testBranch);"
6211 "%OptimizeFunctionOnNextCall(testBool);"
6212 "for (var i = 0; i < 10; i++) {"
6213 " testBranch();"
6214 " testBool();"
6215 "}\n"
6216 "\"PASS\"",
6217 "PASS");
6218}
6219
6220
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006221template <typename T> static void USE(T) { }
6222
6223
6224// This test is not intended to be run, just type checked.
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00006225static inline void PersistentHandles(v8::Isolate* isolate) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006226 USE(PersistentHandles);
6227 Local<String> str = v8_str("foo");
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00006228 v8::Persistent<String> p_str(isolate, str);
6229 p_str.Dispose();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006230 Local<Script> scr = Script::Compile(v8_str(""));
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00006231 v8::Persistent<Script> p_scr(isolate, scr);
6232 p_scr.Dispose();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006233 Local<ObjectTemplate> templ = ObjectTemplate::New();
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00006234 v8::Persistent<ObjectTemplate> p_templ(isolate, templ);
6235 p_templ.Dispose();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006236}
6237
6238
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00006239static void HandleLogDelegator(
6240 const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006241 ApiTestFuzzer::Fuzz();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006242}
6243
6244
6245THREADED_TEST(GlobalObjectTemplate) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006246 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006247 v8::HandleScope handle_scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006248 Local<ObjectTemplate> global_template = ObjectTemplate::New();
6249 global_template->Set(v8_str("JSNI_Log"),
6250 v8::FunctionTemplate::New(HandleLogDelegator));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006251 v8::Local<Context> context = Context::New(isolate, 0, global_template);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006252 Context::Scope context_scope(context);
6253 Script::Compile(v8_str("JSNI_Log('LOG')"))->Run();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006254}
6255
6256
6257static const char* kSimpleExtensionSource =
6258 "function Foo() {"
6259 " return 4;"
6260 "}";
6261
6262
6263THREADED_TEST(SimpleExtensions) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006264 v8::HandleScope handle_scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006265 v8::RegisterExtension(new Extension("simpletest", kSimpleExtensionSource));
6266 const char* extension_names[] = { "simpletest" };
6267 v8::ExtensionConfiguration extensions(1, extension_names);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006268 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006269 Context::New(CcTest::isolate(), &extensions);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006270 Context::Scope lock(context);
6271 v8::Handle<Value> result = Script::Compile(v8_str("Foo()"))->Run();
6272 CHECK_EQ(result, v8::Integer::New(4));
6273}
6274
6275
danno@chromium.org412fa512012-09-14 13:28:26 +00006276THREADED_TEST(NullExtensions) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006277 v8::HandleScope handle_scope(CcTest::isolate());
danno@chromium.org412fa512012-09-14 13:28:26 +00006278 v8::RegisterExtension(new Extension("nulltest", NULL));
6279 const char* extension_names[] = { "nulltest" };
6280 v8::ExtensionConfiguration extensions(1, extension_names);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006281 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006282 Context::New(CcTest::isolate(), &extensions);
danno@chromium.org412fa512012-09-14 13:28:26 +00006283 Context::Scope lock(context);
6284 v8::Handle<Value> result = Script::Compile(v8_str("1+3"))->Run();
6285 CHECK_EQ(result, v8::Integer::New(4));
6286}
6287
6288
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00006289static const char* kEmbeddedExtensionSource =
6290 "function Ret54321(){return 54321;}~~@@$"
6291 "$%% THIS IS A SERIES OF NON-NULL-TERMINATED STRINGS.";
6292static const int kEmbeddedExtensionSourceValidLen = 34;
6293
6294
6295THREADED_TEST(ExtensionMissingSourceLength) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006296 v8::HandleScope handle_scope(CcTest::isolate());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00006297 v8::RegisterExtension(new Extension("srclentest_fail",
6298 kEmbeddedExtensionSource));
6299 const char* extension_names[] = { "srclentest_fail" };
6300 v8::ExtensionConfiguration extensions(1, extension_names);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006301 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006302 Context::New(CcTest::isolate(), &extensions);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00006303 CHECK_EQ(0, *context);
6304}
6305
6306
6307THREADED_TEST(ExtensionWithSourceLength) {
6308 for (int source_len = kEmbeddedExtensionSourceValidLen - 1;
6309 source_len <= kEmbeddedExtensionSourceValidLen + 1; ++source_len) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006310 v8::HandleScope handle_scope(CcTest::isolate());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00006311 i::ScopedVector<char> extension_name(32);
6312 i::OS::SNPrintF(extension_name, "ext #%d", source_len);
6313 v8::RegisterExtension(new Extension(extension_name.start(),
6314 kEmbeddedExtensionSource, 0, 0,
6315 source_len));
6316 const char* extension_names[1] = { extension_name.start() };
6317 v8::ExtensionConfiguration extensions(1, extension_names);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006318 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006319 Context::New(CcTest::isolate(), &extensions);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00006320 if (source_len == kEmbeddedExtensionSourceValidLen) {
6321 Context::Scope lock(context);
6322 v8::Handle<Value> result = Script::Compile(v8_str("Ret54321()"))->Run();
6323 CHECK_EQ(v8::Integer::New(54321), result);
6324 } else {
6325 // Anything but exactly the right length should fail to compile.
6326 CHECK_EQ(0, *context);
6327 }
6328 }
6329}
6330
6331
ager@chromium.org18ad94b2009-09-02 08:22:29 +00006332static const char* kEvalExtensionSource1 =
6333 "function UseEval1() {"
kasperl@chromium.org2d18d102009-04-15 13:27:32 +00006334 " var x = 42;"
6335 " return eval('x');"
6336 "}";
6337
6338
ager@chromium.org18ad94b2009-09-02 08:22:29 +00006339static const char* kEvalExtensionSource2 =
6340 "(function() {"
6341 " var x = 42;"
6342 " function e() {"
6343 " return eval('x');"
6344 " }"
6345 " this.UseEval2 = e;"
6346 "})()";
6347
6348
kasperl@chromium.org2d18d102009-04-15 13:27:32 +00006349THREADED_TEST(UseEvalFromExtension) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006350 v8::HandleScope handle_scope(CcTest::isolate());
ager@chromium.org18ad94b2009-09-02 08:22:29 +00006351 v8::RegisterExtension(new Extension("evaltest1", kEvalExtensionSource1));
6352 v8::RegisterExtension(new Extension("evaltest2", kEvalExtensionSource2));
6353 const char* extension_names[] = { "evaltest1", "evaltest2" };
6354 v8::ExtensionConfiguration extensions(2, extension_names);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006355 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006356 Context::New(CcTest::isolate(), &extensions);
kasperl@chromium.org2d18d102009-04-15 13:27:32 +00006357 Context::Scope lock(context);
ager@chromium.org18ad94b2009-09-02 08:22:29 +00006358 v8::Handle<Value> result = Script::Compile(v8_str("UseEval1()"))->Run();
6359 CHECK_EQ(result, v8::Integer::New(42));
6360 result = Script::Compile(v8_str("UseEval2()"))->Run();
kasperl@chromium.org2d18d102009-04-15 13:27:32 +00006361 CHECK_EQ(result, v8::Integer::New(42));
6362}
6363
6364
ager@chromium.org18ad94b2009-09-02 08:22:29 +00006365static const char* kWithExtensionSource1 =
6366 "function UseWith1() {"
kasperl@chromium.org2d18d102009-04-15 13:27:32 +00006367 " var x = 42;"
6368 " with({x:87}) { return x; }"
6369 "}";
6370
6371
ager@chromium.org18ad94b2009-09-02 08:22:29 +00006372
6373static const char* kWithExtensionSource2 =
6374 "(function() {"
6375 " var x = 42;"
6376 " function e() {"
6377 " with ({x:87}) { return x; }"
6378 " }"
6379 " this.UseWith2 = e;"
6380 "})()";
6381
6382
kasperl@chromium.org2d18d102009-04-15 13:27:32 +00006383THREADED_TEST(UseWithFromExtension) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006384 v8::HandleScope handle_scope(CcTest::isolate());
ager@chromium.org18ad94b2009-09-02 08:22:29 +00006385 v8::RegisterExtension(new Extension("withtest1", kWithExtensionSource1));
6386 v8::RegisterExtension(new Extension("withtest2", kWithExtensionSource2));
6387 const char* extension_names[] = { "withtest1", "withtest2" };
6388 v8::ExtensionConfiguration extensions(2, extension_names);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006389 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006390 Context::New(CcTest::isolate(), &extensions);
kasperl@chromium.org2d18d102009-04-15 13:27:32 +00006391 Context::Scope lock(context);
ager@chromium.org18ad94b2009-09-02 08:22:29 +00006392 v8::Handle<Value> result = Script::Compile(v8_str("UseWith1()"))->Run();
6393 CHECK_EQ(result, v8::Integer::New(87));
6394 result = Script::Compile(v8_str("UseWith2()"))->Run();
kasperl@chromium.org2d18d102009-04-15 13:27:32 +00006395 CHECK_EQ(result, v8::Integer::New(87));
6396}
6397
6398
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006399THREADED_TEST(AutoExtensions) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006400 v8::HandleScope handle_scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006401 Extension* extension = new Extension("autotest", kSimpleExtensionSource);
6402 extension->set_auto_enable(true);
6403 v8::RegisterExtension(extension);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006404 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006405 Context::New(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006406 Context::Scope lock(context);
6407 v8::Handle<Value> result = Script::Compile(v8_str("Foo()"))->Run();
6408 CHECK_EQ(result, v8::Integer::New(4));
6409}
6410
6411
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00006412static const char* kSyntaxErrorInExtensionSource =
6413 "[";
6414
6415
6416// Test that a syntax error in an extension does not cause a fatal
6417// error but results in an empty context.
6418THREADED_TEST(SyntaxErrorExtensions) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006419 v8::HandleScope handle_scope(CcTest::isolate());
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00006420 v8::RegisterExtension(new Extension("syntaxerror",
6421 kSyntaxErrorInExtensionSource));
6422 const char* extension_names[] = { "syntaxerror" };
6423 v8::ExtensionConfiguration extensions(1, extension_names);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006424 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006425 Context::New(CcTest::isolate(), &extensions);
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00006426 CHECK(context.IsEmpty());
6427}
6428
6429
6430static const char* kExceptionInExtensionSource =
6431 "throw 42";
6432
6433
6434// Test that an exception when installing an extension does not cause
6435// a fatal error but results in an empty context.
6436THREADED_TEST(ExceptionExtensions) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006437 v8::HandleScope handle_scope(CcTest::isolate());
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00006438 v8::RegisterExtension(new Extension("exception",
6439 kExceptionInExtensionSource));
6440 const char* extension_names[] = { "exception" };
6441 v8::ExtensionConfiguration extensions(1, extension_names);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006442 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006443 Context::New(CcTest::isolate(), &extensions);
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00006444 CHECK(context.IsEmpty());
6445}
6446
6447
ager@chromium.org5b2fbee2010-09-08 06:38:15 +00006448static const char* kNativeCallInExtensionSource =
6449 "function call_runtime_last_index_of(x) {"
6450 " return %StringLastIndexOf(x, 'bob', 10);"
6451 "}";
6452
6453
6454static const char* kNativeCallTest =
6455 "call_runtime_last_index_of('bobbobboellebobboellebobbob');";
6456
6457// Test that a native runtime calls are supported in extensions.
6458THREADED_TEST(NativeCallInExtensions) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006459 v8::HandleScope handle_scope(CcTest::isolate());
ager@chromium.org5b2fbee2010-09-08 06:38:15 +00006460 v8::RegisterExtension(new Extension("nativecall",
6461 kNativeCallInExtensionSource));
6462 const char* extension_names[] = { "nativecall" };
6463 v8::ExtensionConfiguration extensions(1, extension_names);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006464 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006465 Context::New(CcTest::isolate(), &extensions);
ager@chromium.org5b2fbee2010-09-08 06:38:15 +00006466 Context::Scope lock(context);
6467 v8::Handle<Value> result = Script::Compile(v8_str(kNativeCallTest))->Run();
6468 CHECK_EQ(result, v8::Integer::New(3));
6469}
6470
6471
whesse@chromium.org7b260152011-06-20 15:33:18 +00006472class NativeFunctionExtension : public Extension {
6473 public:
6474 NativeFunctionExtension(const char* name,
6475 const char* source,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00006476 v8::FunctionCallback fun = &Echo)
whesse@chromium.org7b260152011-06-20 15:33:18 +00006477 : Extension(name, source),
6478 function_(fun) { }
6479
6480 virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction(
6481 v8::Handle<v8::String> name) {
6482 return v8::FunctionTemplate::New(function_);
6483 }
6484
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00006485 static void Echo(const v8::FunctionCallbackInfo<v8::Value>& args) {
6486 if (args.Length() >= 1) args.GetReturnValue().Set(args[0]);
whesse@chromium.org7b260152011-06-20 15:33:18 +00006487 }
6488 private:
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00006489 v8::FunctionCallback function_;
whesse@chromium.org7b260152011-06-20 15:33:18 +00006490};
6491
6492
6493THREADED_TEST(NativeFunctionDeclaration) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006494 v8::HandleScope handle_scope(CcTest::isolate());
whesse@chromium.org7b260152011-06-20 15:33:18 +00006495 const char* name = "nativedecl";
6496 v8::RegisterExtension(new NativeFunctionExtension(name,
6497 "native function foo();"));
6498 const char* extension_names[] = { name };
6499 v8::ExtensionConfiguration extensions(1, extension_names);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006500 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006501 Context::New(CcTest::isolate(), &extensions);
whesse@chromium.org7b260152011-06-20 15:33:18 +00006502 Context::Scope lock(context);
6503 v8::Handle<Value> result = Script::Compile(v8_str("foo(42);"))->Run();
6504 CHECK_EQ(result, v8::Integer::New(42));
6505}
6506
6507
6508THREADED_TEST(NativeFunctionDeclarationError) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006509 v8::HandleScope handle_scope(CcTest::isolate());
lrn@chromium.org67e236d2011-06-23 10:18:16 +00006510 const char* name = "nativedeclerr";
whesse@chromium.org7b260152011-06-20 15:33:18 +00006511 // Syntax error in extension code.
6512 v8::RegisterExtension(new NativeFunctionExtension(name,
6513 "native\nfunction foo();"));
6514 const char* extension_names[] = { name };
6515 v8::ExtensionConfiguration extensions(1, extension_names);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006516 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006517 Context::New(CcTest::isolate(), &extensions);
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00006518 CHECK(context.IsEmpty());
whesse@chromium.org7b260152011-06-20 15:33:18 +00006519}
6520
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00006521
whesse@chromium.org7b260152011-06-20 15:33:18 +00006522THREADED_TEST(NativeFunctionDeclarationErrorEscape) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006523 v8::HandleScope handle_scope(CcTest::isolate());
lrn@chromium.org67e236d2011-06-23 10:18:16 +00006524 const char* name = "nativedeclerresc";
whesse@chromium.org7b260152011-06-20 15:33:18 +00006525 // Syntax error in extension code - escape code in "native" means that
6526 // it's not treated as a keyword.
6527 v8::RegisterExtension(new NativeFunctionExtension(
6528 name,
6529 "nativ\\u0065 function foo();"));
6530 const char* extension_names[] = { name };
6531 v8::ExtensionConfiguration extensions(1, extension_names);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006532 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006533 Context::New(CcTest::isolate(), &extensions);
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00006534 CHECK(context.IsEmpty());
whesse@chromium.org7b260152011-06-20 15:33:18 +00006535}
6536
6537
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006538static void CheckDependencies(const char* name, const char* expected) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006539 v8::HandleScope handle_scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006540 v8::ExtensionConfiguration config(1, &name);
6541 LocalContext context(&config);
6542 CHECK_EQ(String::New(expected), context->Global()->Get(v8_str("loaded")));
6543}
6544
6545
6546/*
6547 * Configuration:
6548 *
6549 * /-- B <--\
6550 * A <- -- D <-- E
6551 * \-- C <--/
6552 */
6553THREADED_TEST(ExtensionDependency) {
6554 static const char* kEDeps[] = { "D" };
6555 v8::RegisterExtension(new Extension("E", "this.loaded += 'E';", 1, kEDeps));
6556 static const char* kDDeps[] = { "B", "C" };
6557 v8::RegisterExtension(new Extension("D", "this.loaded += 'D';", 2, kDDeps));
6558 static const char* kBCDeps[] = { "A" };
6559 v8::RegisterExtension(new Extension("B", "this.loaded += 'B';", 1, kBCDeps));
6560 v8::RegisterExtension(new Extension("C", "this.loaded += 'C';", 1, kBCDeps));
6561 v8::RegisterExtension(new Extension("A", "this.loaded += 'A';"));
6562 CheckDependencies("A", "undefinedA");
6563 CheckDependencies("B", "undefinedAB");
6564 CheckDependencies("C", "undefinedAC");
6565 CheckDependencies("D", "undefinedABCD");
6566 CheckDependencies("E", "undefinedABCDE");
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006567 v8::HandleScope handle_scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006568 static const char* exts[2] = { "C", "E" };
6569 v8::ExtensionConfiguration config(2, exts);
6570 LocalContext context(&config);
6571 CHECK_EQ(v8_str("undefinedACBDE"), context->Global()->Get(v8_str("loaded")));
6572}
6573
6574
6575static const char* kExtensionTestScript =
6576 "native function A();"
6577 "native function B();"
6578 "native function C();"
6579 "function Foo(i) {"
6580 " if (i == 0) return A();"
6581 " if (i == 1) return B();"
6582 " if (i == 2) return C();"
6583 "}";
6584
6585
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00006586static void CallFun(const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006587 ApiTestFuzzer::Fuzz();
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00006588 if (args.IsConstructCall()) {
6589 args.This()->Set(v8_str("data"), args.Data());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00006590 args.GetReturnValue().SetNull();
6591 return;
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00006592 }
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00006593 args.GetReturnValue().Set(args.Data());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006594}
6595
6596
6597class FunctionExtension : public Extension {
6598 public:
6599 FunctionExtension() : Extension("functiontest", kExtensionTestScript) { }
6600 virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction(
6601 v8::Handle<String> name);
6602};
6603
6604
6605static int lookup_count = 0;
6606v8::Handle<v8::FunctionTemplate> FunctionExtension::GetNativeFunction(
6607 v8::Handle<String> name) {
6608 lookup_count++;
6609 if (name->Equals(v8_str("A"))) {
6610 return v8::FunctionTemplate::New(CallFun, v8::Integer::New(8));
6611 } else if (name->Equals(v8_str("B"))) {
6612 return v8::FunctionTemplate::New(CallFun, v8::Integer::New(7));
6613 } else if (name->Equals(v8_str("C"))) {
6614 return v8::FunctionTemplate::New(CallFun, v8::Integer::New(6));
6615 } else {
6616 return v8::Handle<v8::FunctionTemplate>();
6617 }
6618}
6619
6620
6621THREADED_TEST(FunctionLookup) {
6622 v8::RegisterExtension(new FunctionExtension());
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006623 v8::HandleScope handle_scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006624 static const char* exts[1] = { "functiontest" };
6625 v8::ExtensionConfiguration config(1, exts);
6626 LocalContext context(&config);
6627 CHECK_EQ(3, lookup_count);
6628 CHECK_EQ(v8::Integer::New(8), Script::Compile(v8_str("Foo(0)"))->Run());
6629 CHECK_EQ(v8::Integer::New(7), Script::Compile(v8_str("Foo(1)"))->Run());
6630 CHECK_EQ(v8::Integer::New(6), Script::Compile(v8_str("Foo(2)"))->Run());
6631}
6632
6633
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00006634THREADED_TEST(NativeFunctionConstructCall) {
6635 v8::RegisterExtension(new FunctionExtension());
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006636 v8::HandleScope handle_scope(CcTest::isolate());
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00006637 static const char* exts[1] = { "functiontest" };
6638 v8::ExtensionConfiguration config(1, exts);
6639 LocalContext context(&config);
6640 for (int i = 0; i < 10; i++) {
6641 // Run a few times to ensure that allocation of objects doesn't
6642 // change behavior of a constructor function.
6643 CHECK_EQ(v8::Integer::New(8),
6644 Script::Compile(v8_str("(new A()).data"))->Run());
6645 CHECK_EQ(v8::Integer::New(7),
6646 Script::Compile(v8_str("(new B()).data"))->Run());
6647 CHECK_EQ(v8::Integer::New(6),
6648 Script::Compile(v8_str("(new C()).data"))->Run());
6649 }
6650}
6651
6652
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006653static const char* last_location;
6654static const char* last_message;
6655void StoringErrorCallback(const char* location, const char* message) {
6656 if (last_location == NULL) {
6657 last_location = location;
6658 last_message = message;
6659 }
6660}
6661
6662
6663// ErrorReporting creates a circular extensions configuration and
6664// tests that the fatal error handler gets called. This renders V8
6665// unusable and therefore this test cannot be run in parallel.
6666TEST(ErrorReporting) {
6667 v8::V8::SetFatalErrorHandler(StoringErrorCallback);
6668 static const char* aDeps[] = { "B" };
6669 v8::RegisterExtension(new Extension("A", "", 1, aDeps));
6670 static const char* bDeps[] = { "A" };
6671 v8::RegisterExtension(new Extension("B", "", 1, bDeps));
6672 last_location = NULL;
6673 v8::ExtensionConfiguration config(1, bDeps);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006674 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006675 Context::New(CcTest::isolate(), &config);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006676 CHECK(context.IsEmpty());
6677 CHECK_NE(last_location, NULL);
6678}
6679
6680
ager@chromium.org7c537e22008-10-16 08:43:32 +00006681static const char* js_code_causing_huge_string_flattening =
6682 "var str = 'X';"
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +00006683 "for (var i = 0; i < 30; i++) {"
ager@chromium.org7c537e22008-10-16 08:43:32 +00006684 " str = str + str;"
6685 "}"
6686 "str.match(/X/);";
6687
6688
6689void OOMCallback(const char* location, const char* message) {
6690 exit(0);
6691}
6692
6693
6694TEST(RegexpOutOfMemory) {
6695 // Execute a script that causes out of memory when flattening a string.
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006696 v8::HandleScope scope(CcTest::isolate());
ager@chromium.org7c537e22008-10-16 08:43:32 +00006697 v8::V8::SetFatalErrorHandler(OOMCallback);
6698 LocalContext context;
6699 Local<Script> script =
6700 Script::Compile(String::New(js_code_causing_huge_string_flattening));
6701 last_location = NULL;
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00006702 script->Run();
ager@chromium.org7c537e22008-10-16 08:43:32 +00006703
6704 CHECK(false); // Should not return.
6705}
6706
6707
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006708static void MissingScriptInfoMessageListener(v8::Handle<v8::Message> message,
6709 v8::Handle<Value> data) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00006710 CHECK(message->GetScriptResourceName()->IsUndefined());
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00006711 CHECK_EQ(v8::Undefined(CcTest::isolate()), message->GetScriptResourceName());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006712 message->GetLineNumber();
6713 message->GetSourceLine();
6714}
6715
6716
6717THREADED_TEST(ErrorWithMissingScriptInfo) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006718 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00006719 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006720 v8::V8::AddMessageListener(MissingScriptInfoMessageListener);
6721 Script::Compile(v8_str("throw Error()"))->Run();
6722 v8::V8::RemoveMessageListeners(MissingScriptInfoMessageListener);
6723}
6724
6725
6726int global_index = 0;
6727
6728class Snorkel {
6729 public:
6730 Snorkel() { index_ = global_index++; }
6731 int index_;
6732};
6733
6734class Whammy {
6735 public:
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00006736 explicit Whammy(v8::Isolate* isolate) : cursor_(0), isolate_(isolate) { }
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +00006737 ~Whammy() { script_.Dispose(); }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006738 v8::Handle<Script> getScript() {
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00006739 if (script_.IsEmpty()) script_.Reset(isolate_, v8_compile("({}).blammo"));
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00006740 return Local<Script>::New(isolate_, script_);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006741 }
6742
6743 public:
6744 static const int kObjectCount = 256;
6745 int cursor_;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00006746 v8::Isolate* isolate_;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006747 v8::Persistent<v8::Object> objects_[kObjectCount];
6748 v8::Persistent<Script> script_;
6749};
6750
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00006751static void HandleWeakReference(v8::Isolate* isolate,
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006752 v8::Persistent<v8::Value>* obj,
6753 Snorkel* snorkel) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006754 delete snorkel;
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +00006755 obj->ClearWeak();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006756}
6757
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00006758void WhammyPropertyGetter(Local<String> name,
6759 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006760 Whammy* whammy =
6761 static_cast<Whammy*>(v8::Handle<v8::External>::Cast(info.Data())->Value());
6762
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00006763 v8::Persistent<v8::Object>& prev = whammy->objects_[whammy->cursor_];
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006764
6765 v8::Handle<v8::Object> obj = v8::Object::New();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006766 if (!prev.IsEmpty()) {
rossberg@chromium.org79e79022013-06-03 15:43:46 +00006767 v8::Local<v8::Object>::New(info.GetIsolate(), prev)
6768 ->Set(v8_str("next"), obj);
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00006769 prev.MakeWeak<Value, Snorkel>(new Snorkel(), &HandleWeakReference);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006770 whammy->objects_[whammy->cursor_].Clear();
6771 }
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00006772 whammy->objects_[whammy->cursor_].Reset(info.GetIsolate(), obj);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006773 whammy->cursor_ = (whammy->cursor_ + 1) % Whammy::kObjectCount;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00006774 info.GetReturnValue().Set(whammy->getScript()->Run());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006775}
6776
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00006777
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006778THREADED_TEST(WeakReference) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006779 v8::HandleScope handle_scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006780 v8::Handle<v8::ObjectTemplate> templ= v8::ObjectTemplate::New();
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006781 Whammy* whammy = new Whammy(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006782 templ->SetNamedPropertyHandler(WhammyPropertyGetter,
6783 0, 0, 0, 0,
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +00006784 v8::External::New(whammy));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006785 const char* extension_list[] = { "v8/gc" };
6786 v8::ExtensionConfiguration extensions(1, extension_list);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006787 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006788 Context::New(CcTest::isolate(), &extensions);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006789 Context::Scope context_scope(context);
6790
6791 v8::Handle<v8::Object> interceptor = templ->NewInstance();
6792 context->Global()->Set(v8_str("whammy"), interceptor);
6793 const char* code =
6794 "var last;"
6795 "for (var i = 0; i < 10000; i++) {"
6796 " var obj = whammy.length;"
6797 " if (last) last.next = obj;"
6798 " last = obj;"
6799 "}"
6800 "gc();"
6801 "4";
6802 v8::Handle<Value> result = CompileRun(code);
6803 CHECK_EQ(4.0, result->NumberValue());
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +00006804 delete whammy;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006805}
6806
6807
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00006808static void DisposeAndSetFlag(v8::Isolate* isolate,
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006809 v8::Persistent<v8::Object>* obj,
6810 bool* data) {
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +00006811 obj->Dispose();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006812 *(data) = true;
ager@chromium.orgc4c92722009-11-18 14:12:51 +00006813}
6814
ager@chromium.orgc4c92722009-11-18 14:12:51 +00006815
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00006816THREADED_TEST(IndependentWeakHandle) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006817 v8::Isolate* iso = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006818 v8::HandleScope scope(iso);
6819 v8::Handle<Context> context = Context::New(iso);
ager@chromium.orgc4c92722009-11-18 14:12:51 +00006820 Context::Scope context_scope(context);
6821
mvstanton@chromium.orge4ac3ef2012-11-12 14:53:34 +00006822 v8::Persistent<v8::Object> object_a, object_b;
ager@chromium.orgc4c92722009-11-18 14:12:51 +00006823
6824 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00006825 v8::HandleScope handle_scope(iso);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00006826 object_a.Reset(iso, v8::Object::New());
6827 object_b.Reset(iso, v8::Object::New());
ager@chromium.orgc4c92722009-11-18 14:12:51 +00006828 }
6829
6830 bool object_a_disposed = false;
mvstanton@chromium.orge4ac3ef2012-11-12 14:53:34 +00006831 bool object_b_disposed = false;
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00006832 object_a.MakeWeak(&object_a_disposed, &DisposeAndSetFlag);
6833 object_b.MakeWeak(&object_b_disposed, &DisposeAndSetFlag);
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +00006834 CHECK(!object_b.IsIndependent());
6835 object_a.MarkIndependent();
6836 object_b.MarkIndependent();
6837 CHECK(object_b.IsIndependent());
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006838 CcTest::heap()->PerformScavenge();
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00006839 CHECK(object_a_disposed);
mvstanton@chromium.orge4ac3ef2012-11-12 14:53:34 +00006840 CHECK(object_b_disposed);
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00006841}
ager@chromium.orgc4c92722009-11-18 14:12:51 +00006842
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00006843
6844static void InvokeScavenge() {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006845 CcTest::heap()->PerformScavenge();
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00006846}
6847
6848
6849static void InvokeMarkSweep() {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006850 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00006851}
6852
6853
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00006854static void ForceScavenge(v8::Isolate* isolate,
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006855 v8::Persistent<v8::Object>* obj,
6856 bool* data) {
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +00006857 obj->Dispose();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006858 *(data) = true;
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00006859 InvokeScavenge();
6860}
6861
6862
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00006863static void ForceMarkSweep(v8::Isolate* isolate,
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006864 v8::Persistent<v8::Object>* obj,
6865 bool* data) {
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +00006866 obj->Dispose();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006867 *(data) = true;
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00006868 InvokeMarkSweep();
6869}
6870
6871
6872THREADED_TEST(GCFromWeakCallbacks) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006873 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006874 v8::HandleScope scope(isolate);
6875 v8::Handle<Context> context = Context::New(isolate);
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00006876 Context::Scope context_scope(context);
6877
6878 static const int kNumberOfGCTypes = 2;
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006879 typedef v8::WeakReferenceCallbacks<v8::Object, bool>::Revivable Callback;
6880 Callback gc_forcing_callback[kNumberOfGCTypes] =
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00006881 {&ForceScavenge, &ForceMarkSweep};
6882
6883 typedef void (*GCInvoker)();
6884 GCInvoker invoke_gc[kNumberOfGCTypes] = {&InvokeScavenge, &InvokeMarkSweep};
6885
6886 for (int outer_gc = 0; outer_gc < kNumberOfGCTypes; outer_gc++) {
6887 for (int inner_gc = 0; inner_gc < kNumberOfGCTypes; inner_gc++) {
6888 v8::Persistent<v8::Object> object;
6889 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00006890 v8::HandleScope handle_scope(isolate);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00006891 object.Reset(isolate, v8::Object::New());
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00006892 }
6893 bool disposed = false;
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00006894 object.MakeWeak(&disposed, gc_forcing_callback[inner_gc]);
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +00006895 object.MarkIndependent();
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00006896 invoke_gc[outer_gc]();
6897 CHECK(disposed);
6898 }
ager@chromium.orgc4c92722009-11-18 14:12:51 +00006899 }
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00006900}
6901
6902
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00006903static void RevivingCallback(v8::Isolate* isolate,
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006904 v8::Persistent<v8::Object>* obj,
6905 bool* data) {
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +00006906 obj->ClearWeak();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006907 *(data) = true;
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00006908}
6909
6910
6911THREADED_TEST(IndependentHandleRevival) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006912 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006913 v8::HandleScope scope(isolate);
6914 v8::Handle<Context> context = Context::New(isolate);
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00006915 Context::Scope context_scope(context);
6916
6917 v8::Persistent<v8::Object> object;
6918 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00006919 v8::HandleScope handle_scope(isolate);
rossberg@chromium.org79e79022013-06-03 15:43:46 +00006920 v8::Local<v8::Object> o = v8::Object::New();
6921 object.Reset(isolate, o);
6922 o->Set(v8_str("x"), v8::Integer::New(1));
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00006923 v8::Local<String> y_str = v8_str("y");
rossberg@chromium.org79e79022013-06-03 15:43:46 +00006924 o->Set(y_str, y_str);
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00006925 }
6926 bool revived = false;
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00006927 object.MakeWeak(&revived, &RevivingCallback);
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +00006928 object.MarkIndependent();
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006929 CcTest::heap()->PerformScavenge();
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00006930 CHECK(revived);
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006931 CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00006932 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00006933 v8::HandleScope handle_scope(isolate);
rossberg@chromium.org79e79022013-06-03 15:43:46 +00006934 v8::Local<v8::Object> o = v8::Local<v8::Object>::New(isolate, object);
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00006935 v8::Local<String> y_str = v8_str("y");
rossberg@chromium.org79e79022013-06-03 15:43:46 +00006936 CHECK_EQ(v8::Integer::New(1), o->Get(v8_str("x")));
6937 CHECK(o->Get(y_str)->Equals(y_str));
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00006938 }
ager@chromium.orgc4c92722009-11-18 14:12:51 +00006939}
6940
6941
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006942v8::Handle<Function> args_fun;
6943
6944
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00006945static void ArgumentsTestCallback(
6946 const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006947 ApiTestFuzzer::Fuzz();
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00006948 v8::Isolate* isolate = args.GetIsolate();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006949 CHECK_EQ(args_fun, args.Callee());
6950 CHECK_EQ(3, args.Length());
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00006951 CHECK_EQ(v8::Integer::New(1, isolate), args[0]);
6952 CHECK_EQ(v8::Integer::New(2, isolate), args[1]);
6953 CHECK_EQ(v8::Integer::New(3, isolate), args[2]);
6954 CHECK_EQ(v8::Undefined(isolate), args[3]);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00006955 v8::HandleScope scope(args.GetIsolate());
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006956 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006957}
6958
6959
6960THREADED_TEST(Arguments) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006961 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006962 v8::Handle<v8::ObjectTemplate> global = ObjectTemplate::New();
6963 global->Set(v8_str("f"), v8::FunctionTemplate::New(ArgumentsTestCallback));
6964 LocalContext context(NULL, global);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00006965 args_fun = context->Global()->Get(v8_str("f")).As<Function>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006966 v8_compile("f(1, 2, 3)")->Run();
6967}
6968
6969
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00006970static void NoBlockGetterX(Local<String> name,
6971 const v8::PropertyCallbackInfo<v8::Value>&) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006972}
6973
6974
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00006975static void NoBlockGetterI(uint32_t index,
6976 const v8::PropertyCallbackInfo<v8::Value>&) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006977}
6978
6979
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00006980static void PDeleter(Local<String> name,
6981 const v8::PropertyCallbackInfo<v8::Boolean>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006982 if (!name->Equals(v8_str("foo"))) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00006983 return; // not intercepted
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006984 }
6985
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00006986 info.GetReturnValue().Set(false); // intercepted, don't delete the property
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006987}
6988
6989
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00006990static void IDeleter(uint32_t index,
6991 const v8::PropertyCallbackInfo<v8::Boolean>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006992 if (index != 2) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00006993 return; // not intercepted
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006994 }
6995
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00006996 info.GetReturnValue().Set(false); // intercepted, don't delete the property
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006997}
6998
6999
7000THREADED_TEST(Deleter) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007001 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007002 v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
7003 obj->SetNamedPropertyHandler(NoBlockGetterX, NULL, NULL, PDeleter, NULL);
7004 obj->SetIndexedPropertyHandler(NoBlockGetterI, NULL, NULL, IDeleter, NULL);
7005 LocalContext context;
7006 context->Global()->Set(v8_str("k"), obj->NewInstance());
7007 CompileRun(
7008 "k.foo = 'foo';"
7009 "k.bar = 'bar';"
7010 "k[2] = 2;"
7011 "k[4] = 4;");
7012 CHECK(v8_compile("delete k.foo")->Run()->IsFalse());
7013 CHECK(v8_compile("delete k.bar")->Run()->IsTrue());
7014
7015 CHECK_EQ(v8_compile("k.foo")->Run(), v8_str("foo"));
7016 CHECK(v8_compile("k.bar")->Run()->IsUndefined());
7017
7018 CHECK(v8_compile("delete k[2]")->Run()->IsFalse());
7019 CHECK(v8_compile("delete k[4]")->Run()->IsTrue());
7020
7021 CHECK_EQ(v8_compile("k[2]")->Run(), v8_num(2));
7022 CHECK(v8_compile("k[4]")->Run()->IsUndefined());
7023}
7024
7025
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007026static void GetK(Local<String> name,
7027 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007028 ApiTestFuzzer::Fuzz();
ager@chromium.org65dad4b2009-04-23 08:48:43 +00007029 if (name->Equals(v8_str("foo")) ||
7030 name->Equals(v8_str("bar")) ||
7031 name->Equals(v8_str("baz"))) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007032 info.GetReturnValue().SetUndefined();
ager@chromium.org65dad4b2009-04-23 08:48:43 +00007033 }
ager@chromium.org65dad4b2009-04-23 08:48:43 +00007034}
7035
7036
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007037static void IndexedGetK(uint32_t index,
7038 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.org65dad4b2009-04-23 08:48:43 +00007039 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007040 if (index == 0 || index == 1) info.GetReturnValue().SetUndefined();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007041}
7042
7043
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007044static void NamedEnum(const v8::PropertyCallbackInfo<v8::Array>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007045 ApiTestFuzzer::Fuzz();
7046 v8::Handle<v8::Array> result = v8::Array::New(3);
7047 result->Set(v8::Integer::New(0), v8_str("foo"));
7048 result->Set(v8::Integer::New(1), v8_str("bar"));
7049 result->Set(v8::Integer::New(2), v8_str("baz"));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007050 info.GetReturnValue().Set(result);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007051}
7052
7053
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007054static void IndexedEnum(const v8::PropertyCallbackInfo<v8::Array>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007055 ApiTestFuzzer::Fuzz();
7056 v8::Handle<v8::Array> result = v8::Array::New(2);
ager@chromium.org65dad4b2009-04-23 08:48:43 +00007057 result->Set(v8::Integer::New(0), v8_str("0"));
7058 result->Set(v8::Integer::New(1), v8_str("1"));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007059 info.GetReturnValue().Set(result);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007060}
7061
7062
7063THREADED_TEST(Enumerators) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007064 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007065 v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
7066 obj->SetNamedPropertyHandler(GetK, NULL, NULL, NULL, NamedEnum);
ager@chromium.org65dad4b2009-04-23 08:48:43 +00007067 obj->SetIndexedPropertyHandler(IndexedGetK, NULL, NULL, NULL, IndexedEnum);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007068 LocalContext context;
7069 context->Global()->Set(v8_str("k"), obj->NewInstance());
7070 v8::Handle<v8::Array> result = v8::Handle<v8::Array>::Cast(CompileRun(
ager@chromium.org65dad4b2009-04-23 08:48:43 +00007071 "k[10] = 0;"
7072 "k.a = 0;"
7073 "k[5] = 0;"
7074 "k.b = 0;"
7075 "k[4294967295] = 0;"
7076 "k.c = 0;"
7077 "k[4294967296] = 0;"
7078 "k.d = 0;"
7079 "k[140000] = 0;"
7080 "k.e = 0;"
7081 "k[30000000000] = 0;"
7082 "k.f = 0;"
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007083 "var result = [];"
7084 "for (var prop in k) {"
7085 " result.push(prop);"
7086 "}"
7087 "result"));
ager@chromium.org65dad4b2009-04-23 08:48:43 +00007088 // Check that we get all the property names returned including the
7089 // ones from the enumerators in the right order: indexed properties
7090 // in numerical order, indexed interceptor properties, named
7091 // properties in insertion order, named interceptor properties.
7092 // This order is not mandated by the spec, so this test is just
7093 // documenting our behavior.
7094 CHECK_EQ(17, result->Length());
7095 // Indexed properties in numerical order.
7096 CHECK_EQ(v8_str("5"), result->Get(v8::Integer::New(0)));
7097 CHECK_EQ(v8_str("10"), result->Get(v8::Integer::New(1)));
7098 CHECK_EQ(v8_str("140000"), result->Get(v8::Integer::New(2)));
7099 CHECK_EQ(v8_str("4294967295"), result->Get(v8::Integer::New(3)));
7100 // Indexed interceptor properties in the order they are returned
7101 // from the enumerator interceptor.
7102 CHECK_EQ(v8_str("0"), result->Get(v8::Integer::New(4)));
7103 CHECK_EQ(v8_str("1"), result->Get(v8::Integer::New(5)));
7104 // Named properties in insertion order.
7105 CHECK_EQ(v8_str("a"), result->Get(v8::Integer::New(6)));
7106 CHECK_EQ(v8_str("b"), result->Get(v8::Integer::New(7)));
7107 CHECK_EQ(v8_str("c"), result->Get(v8::Integer::New(8)));
7108 CHECK_EQ(v8_str("4294967296"), result->Get(v8::Integer::New(9)));
7109 CHECK_EQ(v8_str("d"), result->Get(v8::Integer::New(10)));
7110 CHECK_EQ(v8_str("e"), result->Get(v8::Integer::New(11)));
7111 CHECK_EQ(v8_str("30000000000"), result->Get(v8::Integer::New(12)));
7112 CHECK_EQ(v8_str("f"), result->Get(v8::Integer::New(13)));
7113 // Named interceptor properties.
7114 CHECK_EQ(v8_str("foo"), result->Get(v8::Integer::New(14)));
7115 CHECK_EQ(v8_str("bar"), result->Get(v8::Integer::New(15)));
7116 CHECK_EQ(v8_str("baz"), result->Get(v8::Integer::New(16)));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007117}
7118
7119
7120int p_getter_count;
7121int p_getter_count2;
7122
7123
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007124static void PGetter(Local<String> name,
7125 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007126 ApiTestFuzzer::Fuzz();
7127 p_getter_count++;
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007128 v8::Handle<v8::Object> global =
7129 info.GetIsolate()->GetCurrentContext()->Global();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007130 CHECK_EQ(info.Holder(), global->Get(v8_str("o1")));
7131 if (name->Equals(v8_str("p1"))) {
7132 CHECK_EQ(info.This(), global->Get(v8_str("o1")));
7133 } else if (name->Equals(v8_str("p2"))) {
7134 CHECK_EQ(info.This(), global->Get(v8_str("o2")));
7135 } else if (name->Equals(v8_str("p3"))) {
7136 CHECK_EQ(info.This(), global->Get(v8_str("o3")));
7137 } else if (name->Equals(v8_str("p4"))) {
7138 CHECK_EQ(info.This(), global->Get(v8_str("o4")));
7139 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007140}
7141
7142
7143static void RunHolderTest(v8::Handle<v8::ObjectTemplate> obj) {
7144 ApiTestFuzzer::Fuzz();
7145 LocalContext context;
7146 context->Global()->Set(v8_str("o1"), obj->NewInstance());
7147 CompileRun(
7148 "o1.__proto__ = { };"
7149 "var o2 = { __proto__: o1 };"
7150 "var o3 = { __proto__: o2 };"
7151 "var o4 = { __proto__: o3 };"
7152 "for (var i = 0; i < 10; i++) o4.p4;"
7153 "for (var i = 0; i < 10; i++) o3.p3;"
7154 "for (var i = 0; i < 10; i++) o2.p2;"
7155 "for (var i = 0; i < 10; i++) o1.p1;");
7156}
7157
7158
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007159static void PGetter2(Local<String> name,
7160 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007161 ApiTestFuzzer::Fuzz();
7162 p_getter_count2++;
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007163 v8::Handle<v8::Object> global =
7164 info.GetIsolate()->GetCurrentContext()->Global();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007165 CHECK_EQ(info.Holder(), global->Get(v8_str("o1")));
7166 if (name->Equals(v8_str("p1"))) {
7167 CHECK_EQ(info.This(), global->Get(v8_str("o1")));
7168 } else if (name->Equals(v8_str("p2"))) {
7169 CHECK_EQ(info.This(), global->Get(v8_str("o2")));
7170 } else if (name->Equals(v8_str("p3"))) {
7171 CHECK_EQ(info.This(), global->Get(v8_str("o3")));
7172 } else if (name->Equals(v8_str("p4"))) {
7173 CHECK_EQ(info.This(), global->Get(v8_str("o4")));
7174 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007175}
7176
7177
7178THREADED_TEST(GetterHolders) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007179 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007180 v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
7181 obj->SetAccessor(v8_str("p1"), PGetter);
7182 obj->SetAccessor(v8_str("p2"), PGetter);
7183 obj->SetAccessor(v8_str("p3"), PGetter);
7184 obj->SetAccessor(v8_str("p4"), PGetter);
7185 p_getter_count = 0;
7186 RunHolderTest(obj);
7187 CHECK_EQ(40, p_getter_count);
7188}
7189
7190
7191THREADED_TEST(PreInterceptorHolders) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007192 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007193 v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
7194 obj->SetNamedPropertyHandler(PGetter2);
7195 p_getter_count2 = 0;
7196 RunHolderTest(obj);
7197 CHECK_EQ(40, p_getter_count2);
7198}
7199
7200
7201THREADED_TEST(ObjectInstantiation) {
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00007202 v8::Isolate* isolate = CcTest::isolate();
7203 v8::HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007204 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
7205 templ->SetAccessor(v8_str("t"), PGetter2);
7206 LocalContext context;
7207 context->Global()->Set(v8_str("o"), templ->NewInstance());
7208 for (int i = 0; i < 100; i++) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007209 v8::HandleScope inner_scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007210 v8::Handle<v8::Object> obj = templ->NewInstance();
7211 CHECK_NE(obj, context->Global()->Get(v8_str("o")));
7212 context->Global()->Set(v8_str("o2"), obj);
7213 v8::Handle<Value> value =
7214 Script::Compile(v8_str("o.__proto__ === o2.__proto__"))->Run();
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00007215 CHECK_EQ(v8::True(isolate), value);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007216 context->Global()->Set(v8_str("o"), obj);
7217 }
7218}
7219
7220
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007221static int StrCmp16(uint16_t* a, uint16_t* b) {
7222 while (true) {
7223 if (*a == 0 && *b == 0) return 0;
7224 if (*a != *b) return 0 + *a - *b;
7225 a++;
7226 b++;
7227 }
7228}
7229
7230
7231static int StrNCmp16(uint16_t* a, uint16_t* b, int n) {
7232 while (true) {
7233 if (n-- == 0) return 0;
7234 if (*a == 0 && *b == 0) return 0;
7235 if (*a != *b) return 0 + *a - *b;
7236 a++;
7237 b++;
7238 }
7239}
7240
7241
yangguo@chromium.org154ff992012-03-13 08:09:54 +00007242int GetUtf8Length(Handle<String> str) {
7243 int len = str->Utf8Length();
7244 if (len < 0) {
7245 i::Handle<i::String> istr(v8::Utils::OpenHandle(*str));
7246 i::FlattenString(istr);
7247 len = str->Utf8Length();
7248 }
7249 return len;
7250}
7251
7252
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007253THREADED_TEST(StringWrite) {
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007254 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00007255 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007256 v8::Handle<String> str = v8_str("abcde");
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007257 // abc<Icelandic eth><Unicode snowman>.
7258 v8::Handle<String> str2 = v8_str("abc\303\260\342\230\203");
yangguo@chromium.org304cc332012-07-24 07:59:48 +00007259 v8::Handle<String> str3 = v8::String::New("abc\0def", 7);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007260 const int kStride = 4; // Must match stride in for loops in JS below.
7261 CompileRun(
7262 "var left = '';"
7263 "for (var i = 0; i < 0xd800; i += 4) {"
7264 " left = left + String.fromCharCode(i);"
7265 "}");
7266 CompileRun(
7267 "var right = '';"
7268 "for (var i = 0; i < 0xd800; i += 4) {"
7269 " right = String.fromCharCode(i) + right;"
7270 "}");
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007271 v8::Handle<v8::Object> global = context->Global();
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007272 Handle<String> left_tree = global->Get(v8_str("left")).As<String>();
7273 Handle<String> right_tree = global->Get(v8_str("right")).As<String>();
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007274
7275 CHECK_EQ(5, str2->Length());
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007276 CHECK_EQ(0xd800 / kStride, left_tree->Length());
7277 CHECK_EQ(0xd800 / kStride, right_tree->Length());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007278
7279 char buf[100];
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007280 char utf8buf[0xd800 * 3];
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007281 uint16_t wbuf[100];
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007282 int len;
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007283 int charlen;
7284
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007285 memset(utf8buf, 0x1, 1000);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007286 len = str2->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007287 CHECK_EQ(9, len);
7288 CHECK_EQ(5, charlen);
7289 CHECK_EQ(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007290
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007291 memset(utf8buf, 0x1, 1000);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007292 len = str2->WriteUtf8(utf8buf, 8, &charlen);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007293 CHECK_EQ(8, len);
7294 CHECK_EQ(5, charlen);
7295 CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\342\230\203\1", 9));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007296
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007297 memset(utf8buf, 0x1, 1000);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007298 len = str2->WriteUtf8(utf8buf, 7, &charlen);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007299 CHECK_EQ(5, len);
7300 CHECK_EQ(4, charlen);
7301 CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007302
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007303 memset(utf8buf, 0x1, 1000);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007304 len = str2->WriteUtf8(utf8buf, 6, &charlen);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007305 CHECK_EQ(5, len);
7306 CHECK_EQ(4, charlen);
7307 CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007308
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007309 memset(utf8buf, 0x1, 1000);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007310 len = str2->WriteUtf8(utf8buf, 5, &charlen);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007311 CHECK_EQ(5, len);
7312 CHECK_EQ(4, charlen);
7313 CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007314
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007315 memset(utf8buf, 0x1, 1000);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007316 len = str2->WriteUtf8(utf8buf, 4, &charlen);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007317 CHECK_EQ(3, len);
7318 CHECK_EQ(3, charlen);
7319 CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007320
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007321 memset(utf8buf, 0x1, 1000);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007322 len = str2->WriteUtf8(utf8buf, 3, &charlen);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007323 CHECK_EQ(3, len);
7324 CHECK_EQ(3, charlen);
7325 CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007326
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007327 memset(utf8buf, 0x1, 1000);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007328 len = str2->WriteUtf8(utf8buf, 2, &charlen);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007329 CHECK_EQ(2, len);
7330 CHECK_EQ(2, charlen);
7331 CHECK_EQ(0, strncmp(utf8buf, "ab\1", 3));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007332
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007333 memset(utf8buf, 0x1, sizeof(utf8buf));
yangguo@chromium.org154ff992012-03-13 08:09:54 +00007334 len = GetUtf8Length(left_tree);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007335 int utf8_expected =
7336 (0x80 + (0x800 - 0x80) * 2 + (0xd800 - 0x800) * 3) / kStride;
7337 CHECK_EQ(utf8_expected, len);
7338 len = left_tree->WriteUtf8(utf8buf, utf8_expected, &charlen);
7339 CHECK_EQ(utf8_expected, len);
7340 CHECK_EQ(0xd800 / kStride, charlen);
7341 CHECK_EQ(0xed, static_cast<unsigned char>(utf8buf[utf8_expected - 3]));
7342 CHECK_EQ(0x9f, static_cast<unsigned char>(utf8buf[utf8_expected - 2]));
7343 CHECK_EQ(0xc0 - kStride,
7344 static_cast<unsigned char>(utf8buf[utf8_expected - 1]));
7345 CHECK_EQ(1, utf8buf[utf8_expected]);
7346
7347 memset(utf8buf, 0x1, sizeof(utf8buf));
yangguo@chromium.org154ff992012-03-13 08:09:54 +00007348 len = GetUtf8Length(right_tree);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007349 CHECK_EQ(utf8_expected, len);
7350 len = right_tree->WriteUtf8(utf8buf, utf8_expected, &charlen);
7351 CHECK_EQ(utf8_expected, len);
7352 CHECK_EQ(0xd800 / kStride, charlen);
7353 CHECK_EQ(0xed, static_cast<unsigned char>(utf8buf[0]));
7354 CHECK_EQ(0x9f, static_cast<unsigned char>(utf8buf[1]));
7355 CHECK_EQ(0xc0 - kStride, static_cast<unsigned char>(utf8buf[2]));
7356 CHECK_EQ(1, utf8buf[utf8_expected]);
7357
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007358 memset(buf, 0x1, sizeof(buf));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007359 memset(wbuf, 0x1, sizeof(wbuf));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007360 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf));
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007361 CHECK_EQ(5, len);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007362 len = str->Write(wbuf);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007363 CHECK_EQ(5, len);
7364 CHECK_EQ(0, strcmp("abcde", buf));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007365 uint16_t answer1[] = {'a', 'b', 'c', 'd', 'e', '\0'};
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007366 CHECK_EQ(0, StrCmp16(answer1, wbuf));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007367
7368 memset(buf, 0x1, sizeof(buf));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007369 memset(wbuf, 0x1, sizeof(wbuf));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007370 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 4);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007371 CHECK_EQ(4, len);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007372 len = str->Write(wbuf, 0, 4);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007373 CHECK_EQ(4, len);
7374 CHECK_EQ(0, strncmp("abcd\1", buf, 5));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007375 uint16_t answer2[] = {'a', 'b', 'c', 'd', 0x101};
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007376 CHECK_EQ(0, StrNCmp16(answer2, wbuf, 5));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007377
7378 memset(buf, 0x1, sizeof(buf));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007379 memset(wbuf, 0x1, sizeof(wbuf));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007380 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 5);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007381 CHECK_EQ(5, len);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007382 len = str->Write(wbuf, 0, 5);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007383 CHECK_EQ(5, len);
7384 CHECK_EQ(0, strncmp("abcde\1", buf, 6));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007385 uint16_t answer3[] = {'a', 'b', 'c', 'd', 'e', 0x101};
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007386 CHECK_EQ(0, StrNCmp16(answer3, wbuf, 6));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007387
7388 memset(buf, 0x1, sizeof(buf));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007389 memset(wbuf, 0x1, sizeof(wbuf));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007390 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 6);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007391 CHECK_EQ(5, len);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007392 len = str->Write(wbuf, 0, 6);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007393 CHECK_EQ(5, len);
7394 CHECK_EQ(0, strcmp("abcde", buf));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007395 uint16_t answer4[] = {'a', 'b', 'c', 'd', 'e', '\0'};
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007396 CHECK_EQ(0, StrCmp16(answer4, wbuf));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007397
7398 memset(buf, 0x1, sizeof(buf));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007399 memset(wbuf, 0x1, sizeof(wbuf));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007400 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, -1);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007401 CHECK_EQ(1, len);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007402 len = str->Write(wbuf, 4, -1);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007403 CHECK_EQ(1, len);
7404 CHECK_EQ(0, strcmp("e", buf));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007405 uint16_t answer5[] = {'e', '\0'};
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007406 CHECK_EQ(0, StrCmp16(answer5, wbuf));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007407
7408 memset(buf, 0x1, sizeof(buf));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007409 memset(wbuf, 0x1, sizeof(wbuf));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007410 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, 6);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007411 CHECK_EQ(1, len);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007412 len = str->Write(wbuf, 4, 6);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007413 CHECK_EQ(1, len);
7414 CHECK_EQ(0, strcmp("e", buf));
7415 CHECK_EQ(0, StrCmp16(answer5, wbuf));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007416
7417 memset(buf, 0x1, sizeof(buf));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007418 memset(wbuf, 0x1, sizeof(wbuf));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007419 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, 1);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007420 CHECK_EQ(1, len);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007421 len = str->Write(wbuf, 4, 1);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007422 CHECK_EQ(1, len);
7423 CHECK_EQ(0, strncmp("e\1", buf, 2));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007424 uint16_t answer6[] = {'e', 0x101};
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007425 CHECK_EQ(0, StrNCmp16(answer6, wbuf, 2));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007426
7427 memset(buf, 0x1, sizeof(buf));
7428 memset(wbuf, 0x1, sizeof(wbuf));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007429 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 3, 1);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007430 CHECK_EQ(1, len);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007431 len = str->Write(wbuf, 3, 1);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007432 CHECK_EQ(1, len);
7433 CHECK_EQ(0, strncmp("d\1", buf, 2));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007434 uint16_t answer7[] = {'d', 0x101};
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007435 CHECK_EQ(0, StrNCmp16(answer7, wbuf, 2));
ricow@chromium.orgddd545c2011-08-24 12:02:41 +00007436
7437 memset(wbuf, 0x1, sizeof(wbuf));
7438 wbuf[5] = 'X';
7439 len = str->Write(wbuf, 0, 6, String::NO_NULL_TERMINATION);
7440 CHECK_EQ(5, len);
7441 CHECK_EQ('X', wbuf[5]);
7442 uint16_t answer8a[] = {'a', 'b', 'c', 'd', 'e'};
7443 uint16_t answer8b[] = {'a', 'b', 'c', 'd', 'e', '\0'};
7444 CHECK_EQ(0, StrNCmp16(answer8a, wbuf, 5));
7445 CHECK_NE(0, StrCmp16(answer8b, wbuf));
7446 wbuf[5] = '\0';
7447 CHECK_EQ(0, StrCmp16(answer8b, wbuf));
7448
7449 memset(buf, 0x1, sizeof(buf));
7450 buf[5] = 'X';
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007451 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf),
7452 0,
7453 6,
7454 String::NO_NULL_TERMINATION);
ricow@chromium.orgddd545c2011-08-24 12:02:41 +00007455 CHECK_EQ(5, len);
7456 CHECK_EQ('X', buf[5]);
7457 CHECK_EQ(0, strncmp("abcde", buf, 5));
7458 CHECK_NE(0, strcmp("abcde", buf));
7459 buf[5] = '\0';
7460 CHECK_EQ(0, strcmp("abcde", buf));
7461
7462 memset(utf8buf, 0x1, sizeof(utf8buf));
7463 utf8buf[8] = 'X';
7464 len = str2->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen,
7465 String::NO_NULL_TERMINATION);
7466 CHECK_EQ(8, len);
7467 CHECK_EQ('X', utf8buf[8]);
7468 CHECK_EQ(5, charlen);
7469 CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\342\230\203", 8));
7470 CHECK_NE(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
7471 utf8buf[8] = '\0';
7472 CHECK_EQ(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
yangguo@chromium.org304cc332012-07-24 07:59:48 +00007473
7474 memset(utf8buf, 0x1, sizeof(utf8buf));
7475 utf8buf[5] = 'X';
7476 len = str->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen,
7477 String::NO_NULL_TERMINATION);
7478 CHECK_EQ(5, len);
7479 CHECK_EQ('X', utf8buf[5]); // Test that the sixth character is untouched.
7480 CHECK_EQ(5, charlen);
7481 utf8buf[5] = '\0';
7482 CHECK_EQ(0, strcmp(utf8buf, "abcde"));
7483
7484 memset(buf, 0x1, sizeof(buf));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007485 len = str3->WriteOneByte(reinterpret_cast<uint8_t*>(buf));
yangguo@chromium.org304cc332012-07-24 07:59:48 +00007486 CHECK_EQ(7, len);
7487 CHECK_EQ(0, strcmp("abc", buf));
7488 CHECK_EQ(0, buf[3]);
7489 CHECK_EQ(0, strcmp("def", buf + 4));
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00007490
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007491 CHECK_EQ(0, str->WriteOneByte(NULL, 0, 0, String::NO_NULL_TERMINATION));
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00007492 CHECK_EQ(0, str->WriteUtf8(NULL, 0, 0, String::NO_NULL_TERMINATION));
7493 CHECK_EQ(0, str->Write(NULL, 0, 0, String::NO_NULL_TERMINATION));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007494}
7495
7496
yangguo@chromium.org154ff992012-03-13 08:09:54 +00007497static void Utf16Helper(
7498 LocalContext& context,
7499 const char* name,
7500 const char* lengths_name,
7501 int len) {
7502 Local<v8::Array> a =
7503 Local<v8::Array>::Cast(context->Global()->Get(v8_str(name)));
7504 Local<v8::Array> alens =
7505 Local<v8::Array>::Cast(context->Global()->Get(v8_str(lengths_name)));
7506 for (int i = 0; i < len; i++) {
7507 Local<v8::String> string =
7508 Local<v8::String>::Cast(a->Get(i));
7509 Local<v8::Number> expected_len =
7510 Local<v8::Number>::Cast(alens->Get(i));
7511 int length = GetUtf8Length(string);
7512 CHECK_EQ(static_cast<int>(expected_len->Value()), length);
7513 }
7514}
7515
7516
7517static uint16_t StringGet(Handle<String> str, int index) {
7518 i::Handle<i::String> istring =
7519 v8::Utils::OpenHandle(String::Cast(*str));
7520 return istring->Get(index);
7521}
7522
7523
7524static void WriteUtf8Helper(
7525 LocalContext& context,
7526 const char* name,
7527 const char* lengths_name,
7528 int len) {
7529 Local<v8::Array> b =
7530 Local<v8::Array>::Cast(context->Global()->Get(v8_str(name)));
7531 Local<v8::Array> alens =
7532 Local<v8::Array>::Cast(context->Global()->Get(v8_str(lengths_name)));
7533 char buffer[1000];
7534 char buffer2[1000];
7535 for (int i = 0; i < len; i++) {
7536 Local<v8::String> string =
7537 Local<v8::String>::Cast(b->Get(i));
7538 Local<v8::Number> expected_len =
7539 Local<v8::Number>::Cast(alens->Get(i));
7540 int utf8_length = static_cast<int>(expected_len->Value());
7541 for (int j = utf8_length + 1; j >= 0; j--) {
7542 memset(reinterpret_cast<void*>(&buffer), 42, sizeof(buffer));
7543 memset(reinterpret_cast<void*>(&buffer2), 42, sizeof(buffer2));
7544 int nchars;
7545 int utf8_written =
7546 string->WriteUtf8(buffer, j, &nchars, String::NO_OPTIONS);
7547 int utf8_written2 =
7548 string->WriteUtf8(buffer2, j, &nchars, String::NO_NULL_TERMINATION);
7549 CHECK_GE(utf8_length + 1, utf8_written);
7550 CHECK_GE(utf8_length, utf8_written2);
7551 for (int k = 0; k < utf8_written2; k++) {
7552 CHECK_EQ(buffer[k], buffer2[k]);
7553 }
7554 CHECK(nchars * 3 >= utf8_written - 1);
7555 CHECK(nchars <= utf8_written);
7556 if (j == utf8_length + 1) {
7557 CHECK_EQ(utf8_written2, utf8_length);
7558 CHECK_EQ(utf8_written2 + 1, utf8_written);
7559 }
7560 CHECK_EQ(buffer[utf8_written], 42);
7561 if (j > utf8_length) {
7562 if (utf8_written != 0) CHECK_EQ(buffer[utf8_written - 1], 0);
7563 if (utf8_written > 1) CHECK_NE(buffer[utf8_written - 2], 42);
7564 Handle<String> roundtrip = v8_str(buffer);
7565 CHECK(roundtrip->Equals(string));
7566 } else {
7567 if (utf8_written != 0) CHECK_NE(buffer[utf8_written - 1], 42);
7568 }
7569 if (utf8_written2 != 0) CHECK_NE(buffer[utf8_written - 1], 42);
7570 if (nchars >= 2) {
7571 uint16_t trail = StringGet(string, nchars - 1);
7572 uint16_t lead = StringGet(string, nchars - 2);
7573 if (((lead & 0xfc00) == 0xd800) &&
7574 ((trail & 0xfc00) == 0xdc00)) {
7575 unsigned char u1 = buffer2[utf8_written2 - 4];
7576 unsigned char u2 = buffer2[utf8_written2 - 3];
7577 unsigned char u3 = buffer2[utf8_written2 - 2];
7578 unsigned char u4 = buffer2[utf8_written2 - 1];
7579 CHECK_EQ((u1 & 0xf8), 0xf0);
7580 CHECK_EQ((u2 & 0xc0), 0x80);
7581 CHECK_EQ((u3 & 0xc0), 0x80);
7582 CHECK_EQ((u4 & 0xc0), 0x80);
7583 uint32_t c = 0x10000 + ((lead & 0x3ff) << 10) + (trail & 0x3ff);
7584 CHECK_EQ((u4 & 0x3f), (c & 0x3f));
7585 CHECK_EQ((u3 & 0x3f), ((c >> 6) & 0x3f));
7586 CHECK_EQ((u2 & 0x3f), ((c >> 12) & 0x3f));
7587 CHECK_EQ((u1 & 0x3), c >> 18);
7588 }
7589 }
7590 }
7591 }
7592}
7593
7594
7595THREADED_TEST(Utf16) {
7596 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00007597 v8::HandleScope scope(context->GetIsolate());
yangguo@chromium.org154ff992012-03-13 08:09:54 +00007598 CompileRun(
7599 "var pad = '01234567890123456789';"
7600 "var p = [];"
7601 "var plens = [20, 3, 3];"
7602 "p.push('01234567890123456789');"
7603 "var lead = 0xd800;"
7604 "var trail = 0xdc00;"
7605 "p.push(String.fromCharCode(0xd800));"
7606 "p.push(String.fromCharCode(0xdc00));"
7607 "var a = [];"
7608 "var b = [];"
danno@chromium.org88aa0582012-03-23 15:11:57 +00007609 "var c = [];"
yangguo@chromium.org154ff992012-03-13 08:09:54 +00007610 "var alens = [];"
7611 "for (var i = 0; i < 3; i++) {"
7612 " p[1] = String.fromCharCode(lead++);"
7613 " for (var j = 0; j < 3; j++) {"
7614 " p[2] = String.fromCharCode(trail++);"
7615 " a.push(p[i] + p[j]);"
7616 " b.push(p[i] + p[j]);"
danno@chromium.org88aa0582012-03-23 15:11:57 +00007617 " c.push(p[i] + p[j]);"
yangguo@chromium.org154ff992012-03-13 08:09:54 +00007618 " alens.push(plens[i] + plens[j]);"
7619 " }"
7620 "}"
7621 "alens[5] -= 2;" // Here the surrogate pairs match up.
7622 "var a2 = [];"
7623 "var b2 = [];"
danno@chromium.org88aa0582012-03-23 15:11:57 +00007624 "var c2 = [];"
yangguo@chromium.org154ff992012-03-13 08:09:54 +00007625 "var a2lens = [];"
7626 "for (var m = 0; m < 9; m++) {"
7627 " for (var n = 0; n < 9; n++) {"
7628 " a2.push(a[m] + a[n]);"
7629 " b2.push(b[m] + b[n]);"
danno@chromium.org88aa0582012-03-23 15:11:57 +00007630 " var newc = 'x' + c[m] + c[n] + 'y';"
7631 " c2.push(newc.substring(1, newc.length - 1));"
yangguo@chromium.org154ff992012-03-13 08:09:54 +00007632 " var utf = alens[m] + alens[n];" // And here.
7633 // The 'n's that start with 0xdc.. are 6-8
7634 // The 'm's that end with 0xd8.. are 1, 4 and 7
7635 " if ((m % 3) == 1 && n >= 6) utf -= 2;"
7636 " a2lens.push(utf);"
7637 " }"
7638 "}");
7639 Utf16Helper(context, "a", "alens", 9);
7640 Utf16Helper(context, "a2", "a2lens", 81);
7641 WriteUtf8Helper(context, "b", "alens", 9);
7642 WriteUtf8Helper(context, "b2", "a2lens", 81);
danno@chromium.org88aa0582012-03-23 15:11:57 +00007643 WriteUtf8Helper(context, "c2", "a2lens", 81);
yangguo@chromium.org154ff992012-03-13 08:09:54 +00007644}
7645
7646
7647static bool SameSymbol(Handle<String> s1, Handle<String> s2) {
7648 i::Handle<i::String> is1(v8::Utils::OpenHandle(*s1));
7649 i::Handle<i::String> is2(v8::Utils::OpenHandle(*s2));
7650 return *is1 == *is2;
7651}
7652
7653
7654static void SameSymbolHelper(const char* a, const char* b) {
7655 Handle<String> symbol1 = v8::String::NewSymbol(a);
7656 Handle<String> symbol2 = v8::String::NewSymbol(b);
7657 CHECK(SameSymbol(symbol1, symbol2));
7658}
7659
7660
7661THREADED_TEST(Utf16Symbol) {
7662 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00007663 v8::HandleScope scope(context->GetIsolate());
yangguo@chromium.org154ff992012-03-13 08:09:54 +00007664
7665 Handle<String> symbol1 = v8::String::NewSymbol("abc");
7666 Handle<String> symbol2 = v8::String::NewSymbol("abc");
7667 CHECK(SameSymbol(symbol1, symbol2));
7668
7669 SameSymbolHelper("\360\220\220\205", // 4 byte encoding.
7670 "\355\240\201\355\260\205"); // 2 3-byte surrogates.
7671 SameSymbolHelper("\355\240\201\355\260\206", // 2 3-byte surrogates.
7672 "\360\220\220\206"); // 4 byte encoding.
7673 SameSymbolHelper("x\360\220\220\205", // 4 byte encoding.
7674 "x\355\240\201\355\260\205"); // 2 3-byte surrogates.
7675 SameSymbolHelper("x\355\240\201\355\260\206", // 2 3-byte surrogates.
7676 "x\360\220\220\206"); // 4 byte encoding.
7677 CompileRun(
7678 "var sym0 = 'benedictus';"
7679 "var sym0b = 'S\303\270ren';"
7680 "var sym1 = '\355\240\201\355\260\207';"
7681 "var sym2 = '\360\220\220\210';"
7682 "var sym3 = 'x\355\240\201\355\260\207';"
7683 "var sym4 = 'x\360\220\220\210';"
7684 "if (sym1.length != 2) throw sym1;"
7685 "if (sym1.charCodeAt(1) != 0xdc07) throw sym1.charCodeAt(1);"
7686 "if (sym2.length != 2) throw sym2;"
7687 "if (sym2.charCodeAt(1) != 0xdc08) throw sym2.charCodeAt(2);"
7688 "if (sym3.length != 3) throw sym3;"
7689 "if (sym3.charCodeAt(2) != 0xdc07) throw sym1.charCodeAt(2);"
7690 "if (sym4.length != 3) throw sym4;"
7691 "if (sym4.charCodeAt(2) != 0xdc08) throw sym2.charCodeAt(2);");
7692 Handle<String> sym0 = v8::String::NewSymbol("benedictus");
7693 Handle<String> sym0b = v8::String::NewSymbol("S\303\270ren");
7694 Handle<String> sym1 = v8::String::NewSymbol("\355\240\201\355\260\207");
7695 Handle<String> sym2 = v8::String::NewSymbol("\360\220\220\210");
7696 Handle<String> sym3 = v8::String::NewSymbol("x\355\240\201\355\260\207");
7697 Handle<String> sym4 = v8::String::NewSymbol("x\360\220\220\210");
7698 v8::Local<v8::Object> global = context->Global();
7699 Local<Value> s0 = global->Get(v8_str("sym0"));
7700 Local<Value> s0b = global->Get(v8_str("sym0b"));
7701 Local<Value> s1 = global->Get(v8_str("sym1"));
7702 Local<Value> s2 = global->Get(v8_str("sym2"));
7703 Local<Value> s3 = global->Get(v8_str("sym3"));
7704 Local<Value> s4 = global->Get(v8_str("sym4"));
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00007705 CHECK(SameSymbol(sym0, Handle<String>::Cast(s0)));
7706 CHECK(SameSymbol(sym0b, Handle<String>::Cast(s0b)));
7707 CHECK(SameSymbol(sym1, Handle<String>::Cast(s1)));
7708 CHECK(SameSymbol(sym2, Handle<String>::Cast(s2)));
7709 CHECK(SameSymbol(sym3, Handle<String>::Cast(s3)));
7710 CHECK(SameSymbol(sym4, Handle<String>::Cast(s4)));
yangguo@chromium.org154ff992012-03-13 08:09:54 +00007711}
7712
7713
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007714THREADED_TEST(ToArrayIndex) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007715 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00007716 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007717
7718 v8::Handle<String> str = v8_str("42");
7719 v8::Handle<v8::Uint32> index = str->ToArrayIndex();
7720 CHECK(!index.IsEmpty());
7721 CHECK_EQ(42.0, index->Uint32Value());
7722 str = v8_str("42asdf");
7723 index = str->ToArrayIndex();
7724 CHECK(index.IsEmpty());
7725 str = v8_str("-42");
7726 index = str->ToArrayIndex();
7727 CHECK(index.IsEmpty());
7728 str = v8_str("4294967295");
7729 index = str->ToArrayIndex();
7730 CHECK(!index.IsEmpty());
7731 CHECK_EQ(4294967295.0, index->Uint32Value());
7732 v8::Handle<v8::Number> num = v8::Number::New(1);
7733 index = num->ToArrayIndex();
7734 CHECK(!index.IsEmpty());
7735 CHECK_EQ(1.0, index->Uint32Value());
7736 num = v8::Number::New(-1);
7737 index = num->ToArrayIndex();
7738 CHECK(index.IsEmpty());
7739 v8::Handle<v8::Object> obj = v8::Object::New();
7740 index = obj->ToArrayIndex();
7741 CHECK(index.IsEmpty());
7742}
7743
7744
7745THREADED_TEST(ErrorConstruction) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007746 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00007747 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007748
7749 v8::Handle<String> foo = v8_str("foo");
7750 v8::Handle<String> message = v8_str("message");
7751 v8::Handle<Value> range_error = v8::Exception::RangeError(foo);
7752 CHECK(range_error->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00007753 CHECK(range_error.As<v8::Object>()->Get(message)->Equals(foo));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007754 v8::Handle<Value> reference_error = v8::Exception::ReferenceError(foo);
7755 CHECK(reference_error->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00007756 CHECK(reference_error.As<v8::Object>()->Get(message)->Equals(foo));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007757 v8::Handle<Value> syntax_error = v8::Exception::SyntaxError(foo);
7758 CHECK(syntax_error->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00007759 CHECK(syntax_error.As<v8::Object>()->Get(message)->Equals(foo));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007760 v8::Handle<Value> type_error = v8::Exception::TypeError(foo);
7761 CHECK(type_error->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00007762 CHECK(type_error.As<v8::Object>()->Get(message)->Equals(foo));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007763 v8::Handle<Value> error = v8::Exception::Error(foo);
7764 CHECK(error->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00007765 CHECK(error.As<v8::Object>()->Get(message)->Equals(foo));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007766}
7767
7768
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007769static void YGetter(Local<String> name,
7770 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007771 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007772 info.GetReturnValue().Set(v8_num(10));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007773}
7774
7775
7776static void YSetter(Local<String> name,
7777 Local<Value> value,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007778 const v8::PropertyCallbackInfo<void>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007779 if (info.This()->Has(name)) {
7780 info.This()->Delete(name);
7781 }
7782 info.This()->Set(name, value);
7783}
7784
7785
7786THREADED_TEST(DeleteAccessor) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007787 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007788 v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
7789 obj->SetAccessor(v8_str("y"), YGetter, YSetter);
7790 LocalContext context;
7791 v8::Handle<v8::Object> holder = obj->NewInstance();
7792 context->Global()->Set(v8_str("holder"), holder);
7793 v8::Handle<Value> result = CompileRun(
7794 "holder.y = 11; holder.y = 12; holder.y");
7795 CHECK_EQ(12, result->Uint32Value());
7796}
7797
7798
7799THREADED_TEST(TypeSwitch) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007800 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007801 v8::Handle<v8::FunctionTemplate> templ1 = v8::FunctionTemplate::New();
7802 v8::Handle<v8::FunctionTemplate> templ2 = v8::FunctionTemplate::New();
7803 v8::Handle<v8::FunctionTemplate> templ3 = v8::FunctionTemplate::New();
7804 v8::Handle<v8::FunctionTemplate> templs[3] = { templ1, templ2, templ3 };
7805 v8::Handle<v8::TypeSwitch> type_switch = v8::TypeSwitch::New(3, templs);
7806 LocalContext context;
7807 v8::Handle<v8::Object> obj0 = v8::Object::New();
7808 v8::Handle<v8::Object> obj1 = templ1->GetFunction()->NewInstance();
7809 v8::Handle<v8::Object> obj2 = templ2->GetFunction()->NewInstance();
7810 v8::Handle<v8::Object> obj3 = templ3->GetFunction()->NewInstance();
7811 for (int i = 0; i < 10; i++) {
7812 CHECK_EQ(0, type_switch->match(obj0));
7813 CHECK_EQ(1, type_switch->match(obj1));
7814 CHECK_EQ(2, type_switch->match(obj2));
7815 CHECK_EQ(3, type_switch->match(obj3));
7816 CHECK_EQ(3, type_switch->match(obj3));
7817 CHECK_EQ(2, type_switch->match(obj2));
7818 CHECK_EQ(1, type_switch->match(obj1));
7819 CHECK_EQ(0, type_switch->match(obj0));
7820 }
7821}
7822
7823
7824// For use within the TestSecurityHandler() test.
7825static bool g_security_callback_result = false;
7826static bool NamedSecurityTestCallback(Local<v8::Object> global,
7827 Local<Value> name,
7828 v8::AccessType type,
7829 Local<Value> data) {
7830 // Always allow read access.
7831 if (type == v8::ACCESS_GET)
7832 return true;
7833
7834 // Sometimes allow other access.
7835 return g_security_callback_result;
7836}
7837
7838
7839static bool IndexedSecurityTestCallback(Local<v8::Object> global,
7840 uint32_t key,
7841 v8::AccessType type,
7842 Local<Value> data) {
7843 // Always allow read access.
7844 if (type == v8::ACCESS_GET)
7845 return true;
7846
7847 // Sometimes allow other access.
7848 return g_security_callback_result;
7849}
7850
7851
7852static int trouble_nesting = 0;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007853static void TroubleCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007854 ApiTestFuzzer::Fuzz();
7855 trouble_nesting++;
7856
7857 // Call a JS function that throws an uncaught exception.
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007858 Local<v8::Object> arg_this =
7859 args.GetIsolate()->GetCurrentContext()->Global();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007860 Local<Value> trouble_callee = (trouble_nesting == 3) ?
7861 arg_this->Get(v8_str("trouble_callee")) :
7862 arg_this->Get(v8_str("trouble_caller"));
7863 CHECK(trouble_callee->IsFunction());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007864 args.GetReturnValue().Set(
7865 Function::Cast(*trouble_callee)->Call(arg_this, 0, NULL));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007866}
7867
7868
7869static int report_count = 0;
7870static void ApiUncaughtExceptionTestListener(v8::Handle<v8::Message>,
7871 v8::Handle<Value>) {
7872 report_count++;
7873}
7874
7875
7876// Counts uncaught exceptions, but other tests running in parallel
7877// also have uncaught exceptions.
7878TEST(ApiUncaughtException) {
ager@chromium.org8bb60582008-12-11 12:02:20 +00007879 report_count = 0;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007880 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00007881 v8::HandleScope scope(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007882 v8::V8::AddMessageListener(ApiUncaughtExceptionTestListener);
7883
7884 Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(TroubleCallback);
7885 v8::Local<v8::Object> global = env->Global();
7886 global->Set(v8_str("trouble"), fun->GetFunction());
7887
7888 Script::Compile(v8_str("function trouble_callee() {"
7889 " var x = null;"
7890 " return x.foo;"
7891 "};"
7892 "function trouble_caller() {"
7893 " trouble();"
7894 "};"))->Run();
7895 Local<Value> trouble = global->Get(v8_str("trouble"));
7896 CHECK(trouble->IsFunction());
7897 Local<Value> trouble_callee = global->Get(v8_str("trouble_callee"));
7898 CHECK(trouble_callee->IsFunction());
7899 Local<Value> trouble_caller = global->Get(v8_str("trouble_caller"));
7900 CHECK(trouble_caller->IsFunction());
7901 Function::Cast(*trouble_caller)->Call(global, 0, NULL);
7902 CHECK_EQ(1, report_count);
ager@chromium.org8bb60582008-12-11 12:02:20 +00007903 v8::V8::RemoveMessageListeners(ApiUncaughtExceptionTestListener);
7904}
7905
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00007906static const char* script_resource_name = "ExceptionInNativeScript.js";
7907static void ExceptionInNativeScriptTestListener(v8::Handle<v8::Message> message,
7908 v8::Handle<Value>) {
7909 v8::Handle<v8::Value> name_val = message->GetScriptResourceName();
7910 CHECK(!name_val.IsEmpty() && name_val->IsString());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00007911 v8::String::Utf8Value name(message->GetScriptResourceName());
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00007912 CHECK_EQ(script_resource_name, *name);
7913 CHECK_EQ(3, message->GetLineNumber());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00007914 v8::String::Utf8Value source_line(message->GetSourceLine());
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00007915 CHECK_EQ(" new o.foo();", *source_line);
7916}
7917
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00007918
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00007919TEST(ExceptionInNativeScript) {
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00007920 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00007921 v8::HandleScope scope(env->GetIsolate());
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00007922 v8::V8::AddMessageListener(ExceptionInNativeScriptTestListener);
7923
7924 Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(TroubleCallback);
7925 v8::Local<v8::Object> global = env->Global();
7926 global->Set(v8_str("trouble"), fun->GetFunction());
7927
7928 Script::Compile(v8_str("function trouble() {\n"
7929 " var o = {};\n"
7930 " new o.foo();\n"
7931 "};"), v8::String::New(script_resource_name))->Run();
7932 Local<Value> trouble = global->Get(v8_str("trouble"));
7933 CHECK(trouble->IsFunction());
7934 Function::Cast(*trouble)->Call(global, 0, NULL);
7935 v8::V8::RemoveMessageListeners(ExceptionInNativeScriptTestListener);
7936}
7937
ager@chromium.org8bb60582008-12-11 12:02:20 +00007938
7939TEST(CompilationErrorUsingTryCatchHandler) {
ager@chromium.org8bb60582008-12-11 12:02:20 +00007940 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00007941 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org8bb60582008-12-11 12:02:20 +00007942 v8::TryCatch try_catch;
7943 Script::Compile(v8_str("This doesn't &*&@#$&*^ compile."));
7944 CHECK_NE(NULL, *try_catch.Exception());
7945 CHECK(try_catch.HasCaught());
7946}
7947
7948
7949TEST(TryCatchFinallyUsingTryCatchHandler) {
ager@chromium.org8bb60582008-12-11 12:02:20 +00007950 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00007951 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org8bb60582008-12-11 12:02:20 +00007952 v8::TryCatch try_catch;
7953 Script::Compile(v8_str("try { throw ''; } catch (e) {}"))->Run();
7954 CHECK(!try_catch.HasCaught());
7955 Script::Compile(v8_str("try { throw ''; } finally {}"))->Run();
7956 CHECK(try_catch.HasCaught());
7957 try_catch.Reset();
7958 Script::Compile(v8_str("(function() {"
7959 "try { throw ''; } finally { return; }"
7960 "})()"))->Run();
7961 CHECK(!try_catch.HasCaught());
7962 Script::Compile(v8_str("(function()"
7963 " { try { throw ''; } finally { throw 0; }"
7964 "})()"))->Run();
7965 CHECK(try_catch.HasCaught());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007966}
7967
7968
7969// SecurityHandler can't be run twice
7970TEST(SecurityHandler) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007971 v8::HandleScope scope0(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007972 v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
7973 global_template->SetAccessCheckCallbacks(NamedSecurityTestCallback,
7974 IndexedSecurityTestCallback);
7975 // Create an environment
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007976 v8::Handle<Context> context0 =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007977 Context::New(CcTest::isolate(), NULL, global_template);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007978 context0->Enter();
7979
7980 v8::Handle<v8::Object> global0 = context0->Global();
7981 v8::Handle<Script> script0 = v8_compile("foo = 111");
7982 script0->Run();
7983 global0->Set(v8_str("0"), v8_num(999));
7984 v8::Handle<Value> foo0 = global0->Get(v8_str("foo"));
7985 CHECK_EQ(111, foo0->Int32Value());
7986 v8::Handle<Value> z0 = global0->Get(v8_str("0"));
7987 CHECK_EQ(999, z0->Int32Value());
7988
7989 // Create another environment, should fail security checks.
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007990 v8::HandleScope scope1(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007991
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007992 v8::Handle<Context> context1 =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007993 Context::New(CcTest::isolate(), NULL, global_template);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007994 context1->Enter();
7995
7996 v8::Handle<v8::Object> global1 = context1->Global();
7997 global1->Set(v8_str("othercontext"), global0);
7998 // This set will fail the security check.
7999 v8::Handle<Script> script1 =
8000 v8_compile("othercontext.foo = 222; othercontext[0] = 888;");
8001 script1->Run();
8002 // This read will pass the security check.
8003 v8::Handle<Value> foo1 = global0->Get(v8_str("foo"));
8004 CHECK_EQ(111, foo1->Int32Value());
8005 // This read will pass the security check.
8006 v8::Handle<Value> z1 = global0->Get(v8_str("0"));
8007 CHECK_EQ(999, z1->Int32Value());
8008
8009 // Create another environment, should pass security checks.
8010 { g_security_callback_result = true; // allow security handler to pass.
machenbach@chromium.org528ce022013-09-23 14:09:36 +00008011 v8::HandleScope scope2(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008012 LocalContext context2;
8013 v8::Handle<v8::Object> global2 = context2->Global();
8014 global2->Set(v8_str("othercontext"), global0);
8015 v8::Handle<Script> script2 =
8016 v8_compile("othercontext.foo = 333; othercontext[0] = 888;");
8017 script2->Run();
8018 v8::Handle<Value> foo2 = global0->Get(v8_str("foo"));
8019 CHECK_EQ(333, foo2->Int32Value());
8020 v8::Handle<Value> z2 = global0->Get(v8_str("0"));
8021 CHECK_EQ(888, z2->Int32Value());
8022 }
8023
8024 context1->Exit();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008025 context0->Exit();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008026}
8027
8028
8029THREADED_TEST(SecurityChecks) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008030 LocalContext env1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008031 v8::HandleScope handle_scope(env1->GetIsolate());
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008032 v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008033
8034 Local<Value> foo = v8_str("foo");
8035 Local<Value> bar = v8_str("bar");
8036
8037 // Set to the same domain.
8038 env1->SetSecurityToken(foo);
8039
8040 // Create a function in env1.
8041 Script::Compile(v8_str("spy=function(){return spy;}"))->Run();
8042 Local<Value> spy = env1->Global()->Get(v8_str("spy"));
8043 CHECK(spy->IsFunction());
8044
8045 // Create another function accessing global objects.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00008046 Script::Compile(v8_str("spy2=function(){return new this.Array();}"))->Run();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008047 Local<Value> spy2 = env1->Global()->Get(v8_str("spy2"));
8048 CHECK(spy2->IsFunction());
8049
8050 // Switch to env2 in the same domain and invoke spy on env2.
8051 {
8052 env2->SetSecurityToken(foo);
8053 // Enter env2
8054 Context::Scope scope_env2(env2);
8055 Local<Value> result = Function::Cast(*spy)->Call(env2->Global(), 0, NULL);
8056 CHECK(result->IsFunction());
8057 }
8058
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008059 {
8060 env2->SetSecurityToken(bar);
8061 Context::Scope scope_env2(env2);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008062
8063 // Call cross_domain_call, it should throw an exception
8064 v8::TryCatch try_catch;
8065 Function::Cast(*spy2)->Call(env2->Global(), 0, NULL);
8066 CHECK(try_catch.HasCaught());
8067 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008068}
8069
8070
8071// Regression test case for issue 1183439.
8072THREADED_TEST(SecurityChecksForPrototypeChain) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008073 LocalContext current;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008074 v8::HandleScope scope(current->GetIsolate());
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008075 v8::Handle<Context> other = Context::New(current->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008076
8077 // Change context to be able to get to the Object function in the
8078 // other context without hitting the security checks.
8079 v8::Local<Value> other_object;
8080 { Context::Scope scope(other);
8081 other_object = other->Global()->Get(v8_str("Object"));
8082 other->Global()->Set(v8_num(42), v8_num(87));
8083 }
8084
8085 current->Global()->Set(v8_str("other"), other->Global());
8086 CHECK(v8_compile("other")->Run()->Equals(other->Global()));
8087
8088 // Make sure the security check fails here and we get an undefined
8089 // result instead of getting the Object function. Repeat in a loop
8090 // to make sure to exercise the IC code.
8091 v8::Local<Script> access_other0 = v8_compile("other.Object");
8092 v8::Local<Script> access_other1 = v8_compile("other[42]");
8093 for (int i = 0; i < 5; i++) {
8094 CHECK(!access_other0->Run()->Equals(other_object));
8095 CHECK(access_other0->Run()->IsUndefined());
8096 CHECK(!access_other1->Run()->Equals(v8_num(87)));
8097 CHECK(access_other1->Run()->IsUndefined());
8098 }
8099
8100 // Create an object that has 'other' in its prototype chain and make
8101 // sure we cannot access the Object function indirectly through
8102 // that. Repeat in a loop to make sure to exercise the IC code.
8103 v8_compile("function F() { };"
8104 "F.prototype = other;"
8105 "var f = new F();")->Run();
8106 v8::Local<Script> access_f0 = v8_compile("f.Object");
8107 v8::Local<Script> access_f1 = v8_compile("f[42]");
8108 for (int j = 0; j < 5; j++) {
8109 CHECK(!access_f0->Run()->Equals(other_object));
8110 CHECK(access_f0->Run()->IsUndefined());
8111 CHECK(!access_f1->Run()->Equals(v8_num(87)));
8112 CHECK(access_f1->Run()->IsUndefined());
8113 }
8114
8115 // Now it gets hairy: Set the prototype for the other global object
8116 // to be the current global object. The prototype chain for 'f' now
8117 // goes through 'other' but ends up in the current global object.
8118 { Context::Scope scope(other);
8119 other->Global()->Set(v8_str("__proto__"), current->Global());
8120 }
8121 // Set a named and an index property on the current global
8122 // object. To force the lookup to go through the other global object,
8123 // the properties must not exist in the other global object.
8124 current->Global()->Set(v8_str("foo"), v8_num(100));
8125 current->Global()->Set(v8_num(99), v8_num(101));
8126 // Try to read the properties from f and make sure that the access
8127 // gets stopped by the security checks on the other global object.
8128 Local<Script> access_f2 = v8_compile("f.foo");
8129 Local<Script> access_f3 = v8_compile("f[99]");
8130 for (int k = 0; k < 5; k++) {
8131 CHECK(!access_f2->Run()->Equals(v8_num(100)));
8132 CHECK(access_f2->Run()->IsUndefined());
8133 CHECK(!access_f3->Run()->Equals(v8_num(101)));
8134 CHECK(access_f3->Run()->IsUndefined());
8135 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008136}
8137
8138
8139THREADED_TEST(CrossDomainDelete) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008140 LocalContext env1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008141 v8::HandleScope handle_scope(env1->GetIsolate());
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008142 v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008143
8144 Local<Value> foo = v8_str("foo");
8145 Local<Value> bar = v8_str("bar");
8146
8147 // Set to the same domain.
8148 env1->SetSecurityToken(foo);
8149 env2->SetSecurityToken(foo);
8150
8151 env1->Global()->Set(v8_str("prop"), v8_num(3));
8152 env2->Global()->Set(v8_str("env1"), env1->Global());
8153
8154 // Change env2 to a different domain and delete env1.prop.
8155 env2->SetSecurityToken(bar);
8156 {
8157 Context::Scope scope_env2(env2);
8158 Local<Value> result =
8159 Script::Compile(v8_str("delete env1.prop"))->Run();
8160 CHECK(result->IsFalse());
8161 }
8162
8163 // Check that env1.prop still exists.
8164 Local<Value> v = env1->Global()->Get(v8_str("prop"));
8165 CHECK(v->IsNumber());
8166 CHECK_EQ(3, v->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008167}
8168
8169
ager@chromium.org870a0b62008-11-04 11:43:05 +00008170THREADED_TEST(CrossDomainIsPropertyEnumerable) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00008171 LocalContext env1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008172 v8::HandleScope handle_scope(env1->GetIsolate());
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008173 v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
ager@chromium.org870a0b62008-11-04 11:43:05 +00008174
8175 Local<Value> foo = v8_str("foo");
8176 Local<Value> bar = v8_str("bar");
8177
8178 // Set to the same domain.
8179 env1->SetSecurityToken(foo);
8180 env2->SetSecurityToken(foo);
8181
8182 env1->Global()->Set(v8_str("prop"), v8_num(3));
8183 env2->Global()->Set(v8_str("env1"), env1->Global());
8184
8185 // env1.prop is enumerable in env2.
8186 Local<String> test = v8_str("propertyIsEnumerable.call(env1, 'prop')");
8187 {
8188 Context::Scope scope_env2(env2);
8189 Local<Value> result = Script::Compile(test)->Run();
8190 CHECK(result->IsTrue());
8191 }
8192
8193 // Change env2 to a different domain and test again.
8194 env2->SetSecurityToken(bar);
8195 {
8196 Context::Scope scope_env2(env2);
8197 Local<Value> result = Script::Compile(test)->Run();
8198 CHECK(result->IsFalse());
8199 }
ager@chromium.org870a0b62008-11-04 11:43:05 +00008200}
8201
8202
ager@chromium.org236ad962008-09-25 09:45:57 +00008203THREADED_TEST(CrossDomainForIn) {
ager@chromium.org236ad962008-09-25 09:45:57 +00008204 LocalContext env1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008205 v8::HandleScope handle_scope(env1->GetIsolate());
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008206 v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
ager@chromium.org236ad962008-09-25 09:45:57 +00008207
8208 Local<Value> foo = v8_str("foo");
8209 Local<Value> bar = v8_str("bar");
8210
8211 // Set to the same domain.
8212 env1->SetSecurityToken(foo);
8213 env2->SetSecurityToken(foo);
8214
8215 env1->Global()->Set(v8_str("prop"), v8_num(3));
8216 env2->Global()->Set(v8_str("env1"), env1->Global());
8217
8218 // Change env2 to a different domain and set env1's global object
8219 // as the __proto__ of an object in env2 and enumerate properties
8220 // in for-in. It shouldn't enumerate properties on env1's global
8221 // object.
8222 env2->SetSecurityToken(bar);
8223 {
8224 Context::Scope scope_env2(env2);
8225 Local<Value> result =
8226 CompileRun("(function(){var obj = {'__proto__':env1};"
8227 "for (var p in obj)"
8228 " if (p == 'prop') return false;"
8229 "return true;})()");
8230 CHECK(result->IsTrue());
8231 }
ager@chromium.org236ad962008-09-25 09:45:57 +00008232}
8233
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008234
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00008235TEST(ContextDetachGlobal) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00008236 LocalContext env1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008237 v8::HandleScope handle_scope(env1->GetIsolate());
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008238 v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00008239
8240 Local<v8::Object> global1 = env1->Global();
8241
8242 Local<Value> foo = v8_str("foo");
8243
8244 // Set to the same domain.
8245 env1->SetSecurityToken(foo);
8246 env2->SetSecurityToken(foo);
8247
8248 // Enter env2
8249 env2->Enter();
8250
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +00008251 // Create a function in env2 and add a reference to it in env1.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00008252 Local<v8::Object> global2 = env2->Global();
8253 global2->Set(v8_str("prop"), v8::Integer::New(1));
8254 CompileRun("function getProp() {return prop;}");
8255
8256 env1->Global()->Set(v8_str("getProp"),
8257 global2->Get(v8_str("getProp")));
8258
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +00008259 // Detach env2's global, and reuse the global object of env2
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00008260 env2->Exit();
8261 env2->DetachGlobal();
8262 // env2 has a new global object.
8263 CHECK(!env2->Global()->Equals(global2));
8264
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008265 v8::Handle<Context> env3 = Context::New(env1->GetIsolate(),
8266 0,
8267 v8::Handle<v8::ObjectTemplate>(),
8268 global2);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00008269 env3->SetSecurityToken(v8_str("bar"));
8270 env3->Enter();
8271
8272 Local<v8::Object> global3 = env3->Global();
8273 CHECK_EQ(global2, global3);
8274 CHECK(global3->Get(v8_str("prop"))->IsUndefined());
8275 CHECK(global3->Get(v8_str("getProp"))->IsUndefined());
8276 global3->Set(v8_str("prop"), v8::Integer::New(-1));
8277 global3->Set(v8_str("prop2"), v8::Integer::New(2));
8278 env3->Exit();
8279
8280 // Call getProp in env1, and it should return the value 1
8281 {
8282 Local<Value> get_prop = global1->Get(v8_str("getProp"));
8283 CHECK(get_prop->IsFunction());
8284 v8::TryCatch try_catch;
8285 Local<Value> r = Function::Cast(*get_prop)->Call(global1, 0, NULL);
8286 CHECK(!try_catch.HasCaught());
8287 CHECK_EQ(1, r->Int32Value());
8288 }
8289
8290 // Check that env3 is not accessible from env1
8291 {
8292 Local<Value> r = global3->Get(v8_str("prop2"));
8293 CHECK(r->IsUndefined());
8294 }
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00008295}
8296
8297
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +00008298TEST(DetachAndReattachGlobal) {
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +00008299 LocalContext env1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008300 v8::HandleScope scope(env1->GetIsolate());
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +00008301
8302 // Create second environment.
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008303 v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +00008304
8305 Local<Value> foo = v8_str("foo");
8306
8307 // Set same security token for env1 and env2.
8308 env1->SetSecurityToken(foo);
8309 env2->SetSecurityToken(foo);
8310
8311 // Create a property on the global object in env2.
8312 {
8313 v8::Context::Scope scope(env2);
8314 env2->Global()->Set(v8_str("p"), v8::Integer::New(42));
8315 }
8316
8317 // Create a reference to env2 global from env1 global.
8318 env1->Global()->Set(v8_str("other"), env2->Global());
8319
8320 // Check that we have access to other.p in env2 from env1.
8321 Local<Value> result = CompileRun("other.p");
8322 CHECK(result->IsInt32());
8323 CHECK_EQ(42, result->Int32Value());
8324
8325 // Hold on to global from env2 and detach global from env2.
8326 Local<v8::Object> global2 = env2->Global();
8327 env2->DetachGlobal();
8328
8329 // Check that the global has been detached. No other.p property can
8330 // be found.
8331 result = CompileRun("other.p");
8332 CHECK(result->IsUndefined());
8333
8334 // Reuse global2 for env3.
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008335 v8::Handle<Context> env3 = Context::New(env1->GetIsolate(),
8336 0,
8337 v8::Handle<v8::ObjectTemplate>(),
8338 global2);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +00008339 CHECK_EQ(global2, env3->Global());
8340
8341 // Start by using the same security token for env3 as for env1 and env2.
8342 env3->SetSecurityToken(foo);
8343
8344 // Create a property on the global object in env3.
8345 {
8346 v8::Context::Scope scope(env3);
8347 env3->Global()->Set(v8_str("p"), v8::Integer::New(24));
8348 }
8349
8350 // Check that other.p is now the property in env3 and that we have access.
8351 result = CompileRun("other.p");
8352 CHECK(result->IsInt32());
8353 CHECK_EQ(24, result->Int32Value());
8354
8355 // Change security token for env3 to something different from env1 and env2.
8356 env3->SetSecurityToken(v8_str("bar"));
8357
8358 // Check that we do not have access to other.p in env1. |other| is now
8359 // the global object for env3 which has a different security token,
8360 // so access should be blocked.
8361 result = CompileRun("other.p");
8362 CHECK(result->IsUndefined());
8363
8364 // Detach the global for env3 and reattach it to env2.
8365 env3->DetachGlobal();
8366 env2->ReattachGlobal(global2);
8367
8368 // Check that we have access to other.p again in env1. |other| is now
8369 // the global object for env2 which has the same security token as env1.
8370 result = CompileRun("other.p");
8371 CHECK(result->IsInt32());
8372 CHECK_EQ(42, result->Int32Value());
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +00008373}
8374
8375
ricow@chromium.org83aa5492011-02-07 12:42:56 +00008376static bool allowed_access_type[v8::ACCESS_KEYS + 1] = { false };
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008377static bool NamedAccessBlocker(Local<v8::Object> global,
8378 Local<Value> name,
8379 v8::AccessType type,
8380 Local<Value> data) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00008381 return CcTest::isolate()->GetCurrentContext()->Global()->Equals(global) ||
ricow@chromium.org83aa5492011-02-07 12:42:56 +00008382 allowed_access_type[type];
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008383}
8384
8385
8386static bool IndexedAccessBlocker(Local<v8::Object> global,
8387 uint32_t key,
8388 v8::AccessType type,
8389 Local<Value> data) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00008390 return CcTest::isolate()->GetCurrentContext()->Global()->Equals(global) ||
ricow@chromium.org83aa5492011-02-07 12:42:56 +00008391 allowed_access_type[type];
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008392}
8393
8394
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00008395static int g_echo_value_1 = -1;
8396static int g_echo_value_2 = -1;
8397
8398
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00008399static void EchoGetter(
8400 Local<String> name,
8401 const v8::PropertyCallbackInfo<v8::Value>& info) {
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00008402 info.GetReturnValue().Set(v8_num(g_echo_value_1));
8403}
8404
8405
8406static void EchoGetter(const v8::FunctionCallbackInfo<v8::Value>& info) {
8407 info.GetReturnValue().Set(v8_num(g_echo_value_2));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008408}
8409
8410
8411static void EchoSetter(Local<String> name,
8412 Local<Value> value,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00008413 const v8::PropertyCallbackInfo<void>&) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008414 if (value->IsNumber())
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00008415 g_echo_value_1 = value->Int32Value();
8416}
8417
8418
8419static void EchoSetter(const v8::FunctionCallbackInfo<v8::Value>& info) {
8420 v8::Handle<v8::Value> value = info[0];
8421 if (value->IsNumber())
8422 g_echo_value_2 = value->Int32Value();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008423}
8424
8425
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00008426static void UnreachableGetter(
8427 Local<String> name,
8428 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008429 CHECK(false); // This function should not be called..
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008430}
8431
8432
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00008433static void UnreachableSetter(Local<String>,
8434 Local<Value>,
8435 const v8::PropertyCallbackInfo<void>&) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008436 CHECK(false); // This function should nto be called.
8437}
8438
8439
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00008440static void UnreachableFunction(
8441 const v8::FunctionCallbackInfo<v8::Value>& info) {
8442 CHECK(false); // This function should not be called..
8443}
8444
8445
ricow@chromium.org83aa5492011-02-07 12:42:56 +00008446TEST(AccessControl) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00008447 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008448 v8::HandleScope handle_scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008449 v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
8450
8451 global_template->SetAccessCheckCallbacks(NamedAccessBlocker,
8452 IndexedAccessBlocker);
8453
8454 // Add an accessor accessible by cross-domain JS code.
8455 global_template->SetAccessor(
8456 v8_str("accessible_prop"),
8457 EchoGetter, EchoSetter,
8458 v8::Handle<Value>(),
8459 v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
8460
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00008461
8462 global_template->SetAccessorProperty(
8463 v8_str("accessible_js_prop"),
8464 v8::FunctionTemplate::New(EchoGetter),
8465 v8::FunctionTemplate::New(EchoSetter),
8466 v8::None,
8467 v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
8468
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008469 // Add an accessor that is not accessible by cross-domain JS code.
ager@chromium.org870a0b62008-11-04 11:43:05 +00008470 global_template->SetAccessor(v8_str("blocked_prop"),
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008471 UnreachableGetter, UnreachableSetter,
8472 v8::Handle<Value>(),
8473 v8::DEFAULT);
8474
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00008475 global_template->SetAccessorProperty(
8476 v8_str("blocked_js_prop"),
8477 v8::FunctionTemplate::New(UnreachableFunction),
8478 v8::FunctionTemplate::New(UnreachableFunction),
8479 v8::None,
8480 v8::DEFAULT);
8481
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008482 // Create an environment
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008483 v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008484 context0->Enter();
8485
8486 v8::Handle<v8::Object> global0 = context0->Global();
8487
ricow@chromium.org83aa5492011-02-07 12:42:56 +00008488 // Define a property with JS getter and setter.
8489 CompileRun(
8490 "function getter() { return 'getter'; };\n"
8491 "function setter() { return 'setter'; }\n"
8492 "Object.defineProperty(this, 'js_accessor_p', {get:getter, set:setter})");
8493
8494 Local<Value> getter = global0->Get(v8_str("getter"));
8495 Local<Value> setter = global0->Get(v8_str("setter"));
8496
8497 // And define normal element.
8498 global0->Set(239, v8_str("239"));
8499
8500 // Define an element with JS getter and setter.
8501 CompileRun(
8502 "function el_getter() { return 'el_getter'; };\n"
8503 "function el_setter() { return 'el_setter'; };\n"
8504 "Object.defineProperty(this, '42', {get: el_getter, set: el_setter});");
8505
8506 Local<Value> el_getter = global0->Get(v8_str("el_getter"));
8507 Local<Value> el_setter = global0->Get(v8_str("el_setter"));
8508
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008509 v8::HandleScope scope1(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008510
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008511 v8::Local<Context> context1 = Context::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008512 context1->Enter();
8513
8514 v8::Handle<v8::Object> global1 = context1->Global();
8515 global1->Set(v8_str("other"), global0);
8516
ricow@chromium.org83aa5492011-02-07 12:42:56 +00008517 // Access blocked property.
8518 CompileRun("other.blocked_prop = 1");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008519
ricow@chromium.org83aa5492011-02-07 12:42:56 +00008520 ExpectUndefined("other.blocked_prop");
8521 ExpectUndefined(
8522 "Object.getOwnPropertyDescriptor(other, 'blocked_prop')");
8523 ExpectFalse("propertyIsEnumerable.call(other, 'blocked_prop')");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008524
ricow@chromium.org83aa5492011-02-07 12:42:56 +00008525 // Enable ACCESS_HAS
8526 allowed_access_type[v8::ACCESS_HAS] = true;
8527 ExpectUndefined("other.blocked_prop");
8528 // ... and now we can get the descriptor...
8529 ExpectUndefined(
antonm@chromium.orgdca01352011-01-31 17:15:05 +00008530 "Object.getOwnPropertyDescriptor(other, 'blocked_prop').value");
ricow@chromium.org83aa5492011-02-07 12:42:56 +00008531 // ... and enumerate the property.
8532 ExpectTrue("propertyIsEnumerable.call(other, 'blocked_prop')");
8533 allowed_access_type[v8::ACCESS_HAS] = false;
antonm@chromium.orgdca01352011-01-31 17:15:05 +00008534
ricow@chromium.org83aa5492011-02-07 12:42:56 +00008535 // Access blocked element.
8536 CompileRun("other[239] = 1");
8537
8538 ExpectUndefined("other[239]");
8539 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '239')");
8540 ExpectFalse("propertyIsEnumerable.call(other, '239')");
8541
8542 // Enable ACCESS_HAS
8543 allowed_access_type[v8::ACCESS_HAS] = true;
8544 ExpectUndefined("other[239]");
8545 // ... and now we can get the descriptor...
8546 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '239').value");
8547 // ... and enumerate the property.
8548 ExpectTrue("propertyIsEnumerable.call(other, '239')");
8549 allowed_access_type[v8::ACCESS_HAS] = false;
8550
8551 // Access a property with JS accessor.
8552 CompileRun("other.js_accessor_p = 2");
8553
8554 ExpectUndefined("other.js_accessor_p");
8555 ExpectUndefined(
8556 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p')");
8557
8558 // Enable ACCESS_HAS.
8559 allowed_access_type[v8::ACCESS_HAS] = true;
8560 ExpectUndefined("other.js_accessor_p");
8561 ExpectUndefined(
8562 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get");
8563 ExpectUndefined(
8564 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set");
8565 ExpectUndefined(
8566 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
8567 allowed_access_type[v8::ACCESS_HAS] = false;
8568
8569 // Enable both ACCESS_HAS and ACCESS_GET.
8570 allowed_access_type[v8::ACCESS_HAS] = true;
8571 allowed_access_type[v8::ACCESS_GET] = true;
8572
8573 ExpectString("other.js_accessor_p", "getter");
8574 ExpectObject(
8575 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get", getter);
8576 ExpectUndefined(
8577 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set");
8578 ExpectUndefined(
8579 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
8580
8581 allowed_access_type[v8::ACCESS_GET] = false;
8582 allowed_access_type[v8::ACCESS_HAS] = false;
8583
8584 // Enable both ACCESS_HAS and ACCESS_SET.
8585 allowed_access_type[v8::ACCESS_HAS] = true;
8586 allowed_access_type[v8::ACCESS_SET] = true;
8587
8588 ExpectUndefined("other.js_accessor_p");
8589 ExpectUndefined(
8590 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get");
8591 ExpectObject(
8592 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set", setter);
8593 ExpectUndefined(
8594 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
8595
8596 allowed_access_type[v8::ACCESS_SET] = false;
8597 allowed_access_type[v8::ACCESS_HAS] = false;
8598
8599 // Enable both ACCESS_HAS, ACCESS_GET and ACCESS_SET.
8600 allowed_access_type[v8::ACCESS_HAS] = true;
8601 allowed_access_type[v8::ACCESS_GET] = true;
8602 allowed_access_type[v8::ACCESS_SET] = true;
8603
8604 ExpectString("other.js_accessor_p", "getter");
8605 ExpectObject(
8606 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get", getter);
8607 ExpectObject(
8608 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set", setter);
8609 ExpectUndefined(
8610 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
8611
8612 allowed_access_type[v8::ACCESS_SET] = false;
8613 allowed_access_type[v8::ACCESS_GET] = false;
8614 allowed_access_type[v8::ACCESS_HAS] = false;
8615
8616 // Access an element with JS accessor.
8617 CompileRun("other[42] = 2");
8618
8619 ExpectUndefined("other[42]");
8620 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42')");
8621
8622 // Enable ACCESS_HAS.
8623 allowed_access_type[v8::ACCESS_HAS] = true;
8624 ExpectUndefined("other[42]");
8625 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').get");
8626 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').set");
8627 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
8628 allowed_access_type[v8::ACCESS_HAS] = false;
8629
8630 // Enable both ACCESS_HAS and ACCESS_GET.
8631 allowed_access_type[v8::ACCESS_HAS] = true;
8632 allowed_access_type[v8::ACCESS_GET] = true;
8633
8634 ExpectString("other[42]", "el_getter");
8635 ExpectObject("Object.getOwnPropertyDescriptor(other, '42').get", el_getter);
8636 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').set");
8637 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
8638
8639 allowed_access_type[v8::ACCESS_GET] = false;
8640 allowed_access_type[v8::ACCESS_HAS] = false;
8641
8642 // Enable both ACCESS_HAS and ACCESS_SET.
8643 allowed_access_type[v8::ACCESS_HAS] = true;
8644 allowed_access_type[v8::ACCESS_SET] = true;
8645
8646 ExpectUndefined("other[42]");
8647 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').get");
8648 ExpectObject("Object.getOwnPropertyDescriptor(other, '42').set", el_setter);
8649 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
8650
8651 allowed_access_type[v8::ACCESS_SET] = false;
8652 allowed_access_type[v8::ACCESS_HAS] = false;
8653
8654 // Enable both ACCESS_HAS, ACCESS_GET and ACCESS_SET.
8655 allowed_access_type[v8::ACCESS_HAS] = true;
8656 allowed_access_type[v8::ACCESS_GET] = true;
8657 allowed_access_type[v8::ACCESS_SET] = true;
8658
8659 ExpectString("other[42]", "el_getter");
8660 ExpectObject("Object.getOwnPropertyDescriptor(other, '42').get", el_getter);
8661 ExpectObject("Object.getOwnPropertyDescriptor(other, '42').set", el_setter);
8662 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
8663
8664 allowed_access_type[v8::ACCESS_SET] = false;
8665 allowed_access_type[v8::ACCESS_GET] = false;
8666 allowed_access_type[v8::ACCESS_HAS] = false;
8667
8668 v8::Handle<Value> value;
ager@chromium.org870a0b62008-11-04 11:43:05 +00008669
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008670 // Access accessible property
antonm@chromium.orgdca01352011-01-31 17:15:05 +00008671 value = CompileRun("other.accessible_prop = 3");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008672 CHECK(value->IsNumber());
8673 CHECK_EQ(3, value->Int32Value());
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00008674 CHECK_EQ(3, g_echo_value_1);
8675
8676 // Access accessible js property
8677 value = CompileRun("other.accessible_js_prop = 3");
8678 CHECK(value->IsNumber());
8679 CHECK_EQ(3, value->Int32Value());
8680 CHECK_EQ(3, g_echo_value_2);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008681
antonm@chromium.orgdca01352011-01-31 17:15:05 +00008682 value = CompileRun("other.accessible_prop");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008683 CHECK(value->IsNumber());
8684 CHECK_EQ(3, value->Int32Value());
8685
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00008686 value = CompileRun("other.accessible_js_prop");
8687 CHECK(value->IsNumber());
8688 CHECK_EQ(3, value->Int32Value());
8689
antonm@chromium.orgdca01352011-01-31 17:15:05 +00008690 value = CompileRun(
8691 "Object.getOwnPropertyDescriptor(other, 'accessible_prop').value");
8692 CHECK(value->IsNumber());
8693 CHECK_EQ(3, value->Int32Value());
8694
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00008695 value = CompileRun(
8696 "Object.getOwnPropertyDescriptor(other, 'accessible_js_prop').get()");
8697 CHECK(value->IsNumber());
8698 CHECK_EQ(3, value->Int32Value());
8699
antonm@chromium.orgdca01352011-01-31 17:15:05 +00008700 value = CompileRun("propertyIsEnumerable.call(other, 'accessible_prop')");
ager@chromium.org870a0b62008-11-04 11:43:05 +00008701 CHECK(value->IsTrue());
8702
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00008703 value = CompileRun("propertyIsEnumerable.call(other, 'accessible_js_prop')");
8704 CHECK(value->IsTrue());
8705
ager@chromium.org870a0b62008-11-04 11:43:05 +00008706 // Enumeration doesn't enumerate accessors from inaccessible objects in
8707 // the prototype chain even if the accessors are in themselves accessible.
antonm@chromium.orgdca01352011-01-31 17:15:05 +00008708 value =
ager@chromium.org870a0b62008-11-04 11:43:05 +00008709 CompileRun("(function(){var obj = {'__proto__':other};"
8710 "for (var p in obj)"
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00008711 " if (p == 'accessible_prop' ||"
8712 " p == 'accessible_js_prop' ||"
8713 " p == 'blocked_js_prop' ||"
8714 " p == 'blocked_js_prop') {"
ager@chromium.org870a0b62008-11-04 11:43:05 +00008715 " return false;"
8716 " }"
8717 "return true;})()");
antonm@chromium.orgdca01352011-01-31 17:15:05 +00008718 CHECK(value->IsTrue());
ager@chromium.org870a0b62008-11-04 11:43:05 +00008719
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008720 context1->Exit();
8721 context0->Exit();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008722}
8723
8724
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00008725TEST(AccessControlES5) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00008726 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008727 v8::HandleScope handle_scope(isolate);
ricow@chromium.org65001782011-02-15 13:36:41 +00008728 v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
8729
8730 global_template->SetAccessCheckCallbacks(NamedAccessBlocker,
8731 IndexedAccessBlocker);
8732
ricow@chromium.orgf5a18a22011-03-15 10:00:20 +00008733 // Add accessible accessor.
8734 global_template->SetAccessor(
8735 v8_str("accessible_prop"),
8736 EchoGetter, EchoSetter,
8737 v8::Handle<Value>(),
8738 v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
8739
8740
ricow@chromium.org65001782011-02-15 13:36:41 +00008741 // Add an accessor that is not accessible by cross-domain JS code.
8742 global_template->SetAccessor(v8_str("blocked_prop"),
8743 UnreachableGetter, UnreachableSetter,
8744 v8::Handle<Value>(),
8745 v8::DEFAULT);
8746
8747 // Create an environment
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008748 v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
ricow@chromium.org65001782011-02-15 13:36:41 +00008749 context0->Enter();
8750
8751 v8::Handle<v8::Object> global0 = context0->Global();
8752
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008753 v8::Local<Context> context1 = Context::New(isolate);
ricow@chromium.org65001782011-02-15 13:36:41 +00008754 context1->Enter();
8755 v8::Handle<v8::Object> global1 = context1->Global();
8756 global1->Set(v8_str("other"), global0);
8757
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00008758 // Regression test for issue 1154.
ricow@chromium.org65001782011-02-15 13:36:41 +00008759 ExpectTrue("Object.keys(other).indexOf('blocked_prop') == -1");
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00008760
8761 ExpectUndefined("other.blocked_prop");
8762
8763 // Regression test for issue 1027.
8764 CompileRun("Object.defineProperty(\n"
8765 " other, 'blocked_prop', {configurable: false})");
8766 ExpectUndefined("other.blocked_prop");
8767 ExpectUndefined(
8768 "Object.getOwnPropertyDescriptor(other, 'blocked_prop')");
8769
8770 // Regression test for issue 1171.
8771 ExpectTrue("Object.isExtensible(other)");
8772 CompileRun("Object.preventExtensions(other)");
8773 ExpectTrue("Object.isExtensible(other)");
8774
8775 // Object.seal and Object.freeze.
8776 CompileRun("Object.freeze(other)");
8777 ExpectTrue("Object.isExtensible(other)");
8778
8779 CompileRun("Object.seal(other)");
8780 ExpectTrue("Object.isExtensible(other)");
ricow@chromium.orgf5a18a22011-03-15 10:00:20 +00008781
8782 // Regression test for issue 1250.
8783 // Make sure that we can set the accessible accessors value using normal
8784 // assignment.
8785 CompileRun("other.accessible_prop = 42");
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00008786 CHECK_EQ(42, g_echo_value_1);
ricow@chromium.orgf5a18a22011-03-15 10:00:20 +00008787
8788 v8::Handle<Value> value;
8789 // We follow Safari in ignoring assignments to host object accessors.
8790 CompileRun("Object.defineProperty(other, 'accessible_prop', {value: -1})");
8791 value = CompileRun("other.accessible_prop == 42");
8792 CHECK(value->IsTrue());
ricow@chromium.org65001782011-02-15 13:36:41 +00008793}
8794
8795
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00008796static bool GetOwnPropertyNamesNamedBlocker(Local<v8::Object> global,
8797 Local<Value> name,
8798 v8::AccessType type,
8799 Local<Value> data) {
8800 return false;
8801}
8802
8803
8804static bool GetOwnPropertyNamesIndexedBlocker(Local<v8::Object> global,
8805 uint32_t key,
8806 v8::AccessType type,
8807 Local<Value> data) {
8808 return false;
8809}
8810
8811
8812THREADED_TEST(AccessControlGetOwnPropertyNames) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00008813 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008814 v8::HandleScope handle_scope(isolate);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00008815 v8::Handle<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New();
8816
8817 obj_template->Set(v8_str("x"), v8::Integer::New(42));
8818 obj_template->SetAccessCheckCallbacks(GetOwnPropertyNamesNamedBlocker,
8819 GetOwnPropertyNamesIndexedBlocker);
8820
8821 // Create an environment
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008822 v8::Local<Context> context0 = Context::New(isolate, NULL, obj_template);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00008823 context0->Enter();
8824
8825 v8::Handle<v8::Object> global0 = context0->Global();
8826
machenbach@chromium.org528ce022013-09-23 14:09:36 +00008827 v8::HandleScope scope1(CcTest::isolate());
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00008828
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008829 v8::Local<Context> context1 = Context::New(isolate);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00008830 context1->Enter();
8831
8832 v8::Handle<v8::Object> global1 = context1->Global();
8833 global1->Set(v8_str("other"), global0);
8834 global1->Set(v8_str("object"), obj_template->NewInstance());
8835
8836 v8::Handle<Value> value;
8837
8838 // Attempt to get the property names of the other global object and
8839 // of an object that requires access checks. Accessing the other
8840 // global object should be blocked by access checks on the global
8841 // proxy object. Accessing the object that requires access checks
8842 // is blocked by the access checks on the object itself.
8843 value = CompileRun("Object.getOwnPropertyNames(other).length == 0");
8844 CHECK(value->IsTrue());
8845
8846 value = CompileRun("Object.getOwnPropertyNames(object).length == 0");
8847 CHECK(value->IsTrue());
8848
8849 context1->Exit();
8850 context0->Exit();
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00008851}
8852
8853
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00008854static void IndexedPropertyEnumerator(
8855 const v8::PropertyCallbackInfo<v8::Array>& info) {
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +00008856 v8::Handle<v8::Array> result = v8::Array::New(2);
8857 result->Set(0, v8::Integer::New(7));
8858 result->Set(1, v8::Object::New());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00008859 info.GetReturnValue().Set(result);
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +00008860}
8861
8862
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00008863static void NamedPropertyEnumerator(
8864 const v8::PropertyCallbackInfo<v8::Array>& info) {
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +00008865 v8::Handle<v8::Array> result = v8::Array::New(2);
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00008866 result->Set(0, v8_str("x"));
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +00008867 result->Set(1, v8::Object::New());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00008868 info.GetReturnValue().Set(result);
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00008869}
8870
8871
8872THREADED_TEST(GetOwnPropertyNamesWithInterceptor) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00008873 v8::HandleScope handle_scope(CcTest::isolate());
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00008874 v8::Handle<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New();
8875
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +00008876 obj_template->Set(v8_str("7"), v8::Integer::New(7));
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00008877 obj_template->Set(v8_str("x"), v8::Integer::New(42));
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +00008878 obj_template->SetIndexedPropertyHandler(NULL, NULL, NULL, NULL,
8879 IndexedPropertyEnumerator);
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00008880 obj_template->SetNamedPropertyHandler(NULL, NULL, NULL, NULL,
8881 NamedPropertyEnumerator);
8882
8883 LocalContext context;
8884 v8::Handle<v8::Object> global = context->Global();
8885 global->Set(v8_str("object"), obj_template->NewInstance());
8886
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +00008887 v8::Handle<v8::Value> result =
8888 CompileRun("Object.getOwnPropertyNames(object)");
8889 CHECK(result->IsArray());
8890 v8::Handle<v8::Array> result_array = v8::Handle<v8::Array>::Cast(result);
8891 CHECK_EQ(3, result_array->Length());
8892 CHECK(result_array->Get(0)->IsString());
8893 CHECK(result_array->Get(1)->IsString());
8894 CHECK(result_array->Get(2)->IsString());
8895 CHECK_EQ(v8_str("7"), result_array->Get(0));
8896 CHECK_EQ(v8_str("[object Object]"), result_array->Get(1));
8897 CHECK_EQ(v8_str("x"), result_array->Get(2));
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00008898}
8899
8900
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00008901static void ConstTenGetter(Local<String> name,
8902 const v8::PropertyCallbackInfo<v8::Value>& info) {
8903 info.GetReturnValue().Set(v8_num(10));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008904}
8905
8906
8907THREADED_TEST(CrossDomainAccessors) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00008908 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008909 v8::HandleScope handle_scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008910
8911 v8::Handle<v8::FunctionTemplate> func_template = v8::FunctionTemplate::New();
8912
8913 v8::Handle<v8::ObjectTemplate> global_template =
8914 func_template->InstanceTemplate();
8915
8916 v8::Handle<v8::ObjectTemplate> proto_template =
8917 func_template->PrototypeTemplate();
8918
8919 // Add an accessor to proto that's accessible by cross-domain JS code.
8920 proto_template->SetAccessor(v8_str("accessible"),
8921 ConstTenGetter, 0,
8922 v8::Handle<Value>(),
8923 v8::ALL_CAN_READ);
8924
8925 // Add an accessor that is not accessible by cross-domain JS code.
8926 global_template->SetAccessor(v8_str("unreachable"),
8927 UnreachableGetter, 0,
8928 v8::Handle<Value>(),
8929 v8::DEFAULT);
8930
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008931 v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008932 context0->Enter();
8933
8934 Local<v8::Object> global = context0->Global();
8935 // Add a normal property that shadows 'accessible'
8936 global->Set(v8_str("accessible"), v8_num(11));
8937
8938 // Enter a new context.
machenbach@chromium.org528ce022013-09-23 14:09:36 +00008939 v8::HandleScope scope1(CcTest::isolate());
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008940 v8::Local<Context> context1 = Context::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008941 context1->Enter();
8942
8943 v8::Handle<v8::Object> global1 = context1->Global();
8944 global1->Set(v8_str("other"), global);
8945
8946 // Should return 10, instead of 11
8947 v8::Handle<Value> value = v8_compile("other.accessible")->Run();
8948 CHECK(value->IsNumber());
8949 CHECK_EQ(10, value->Int32Value());
8950
8951 value = v8_compile("other.unreachable")->Run();
8952 CHECK(value->IsUndefined());
8953
8954 context1->Exit();
8955 context0->Exit();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008956}
8957
8958
8959static int named_access_count = 0;
8960static int indexed_access_count = 0;
8961
8962static bool NamedAccessCounter(Local<v8::Object> global,
8963 Local<Value> name,
8964 v8::AccessType type,
8965 Local<Value> data) {
8966 named_access_count++;
8967 return true;
8968}
8969
8970
8971static bool IndexedAccessCounter(Local<v8::Object> global,
8972 uint32_t key,
8973 v8::AccessType type,
8974 Local<Value> data) {
8975 indexed_access_count++;
8976 return true;
8977}
8978
8979
8980// This one is too easily disturbed by other tests.
8981TEST(AccessControlIC) {
8982 named_access_count = 0;
8983 indexed_access_count = 0;
8984
machenbach@chromium.org528ce022013-09-23 14:09:36 +00008985 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008986 v8::HandleScope handle_scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008987
8988 // Create an environment.
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008989 v8::Local<Context> context0 = Context::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008990 context0->Enter();
8991
8992 // Create an object that requires access-check functions to be
8993 // called for cross-domain access.
8994 v8::Handle<v8::ObjectTemplate> object_template = v8::ObjectTemplate::New();
8995 object_template->SetAccessCheckCallbacks(NamedAccessCounter,
8996 IndexedAccessCounter);
8997 Local<v8::Object> object = object_template->NewInstance();
8998
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008999 v8::HandleScope scope1(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009000
9001 // Create another environment.
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009002 v8::Local<Context> context1 = Context::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009003 context1->Enter();
9004
9005 // Make easy access to the object from the other environment.
9006 v8::Handle<v8::Object> global1 = context1->Global();
9007 global1->Set(v8_str("obj"), object);
9008
9009 v8::Handle<Value> value;
9010
9011 // Check that the named access-control function is called every time.
ager@chromium.org8bb60582008-12-11 12:02:20 +00009012 CompileRun("function testProp(obj) {"
9013 " for (var i = 0; i < 10; i++) obj.prop = 1;"
9014 " for (var j = 0; j < 10; j++) obj.prop;"
9015 " return obj.prop"
9016 "}");
9017 value = CompileRun("testProp(obj)");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009018 CHECK(value->IsNumber());
9019 CHECK_EQ(1, value->Int32Value());
9020 CHECK_EQ(21, named_access_count);
9021
9022 // Check that the named access-control function is called every time.
ager@chromium.org8bb60582008-12-11 12:02:20 +00009023 CompileRun("var p = 'prop';"
9024 "function testKeyed(obj) {"
9025 " for (var i = 0; i < 10; i++) obj[p] = 1;"
9026 " for (var j = 0; j < 10; j++) obj[p];"
9027 " return obj[p];"
9028 "}");
9029 // Use obj which requires access checks. No inline caching is used
9030 // in that case.
9031 value = CompileRun("testKeyed(obj)");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009032 CHECK(value->IsNumber());
9033 CHECK_EQ(1, value->Int32Value());
9034 CHECK_EQ(42, named_access_count);
ager@chromium.org8bb60582008-12-11 12:02:20 +00009035 // Force the inline caches into generic state and try again.
9036 CompileRun("testKeyed({ a: 0 })");
9037 CompileRun("testKeyed({ b: 0 })");
9038 value = CompileRun("testKeyed(obj)");
9039 CHECK(value->IsNumber());
9040 CHECK_EQ(1, value->Int32Value());
9041 CHECK_EQ(63, named_access_count);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009042
9043 // Check that the indexed access-control function is called every time.
ager@chromium.org8bb60582008-12-11 12:02:20 +00009044 CompileRun("function testIndexed(obj) {"
9045 " for (var i = 0; i < 10; i++) obj[0] = 1;"
9046 " for (var j = 0; j < 10; j++) obj[0];"
9047 " return obj[0]"
9048 "}");
9049 value = CompileRun("testIndexed(obj)");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009050 CHECK(value->IsNumber());
9051 CHECK_EQ(1, value->Int32Value());
9052 CHECK_EQ(21, indexed_access_count);
ager@chromium.org8bb60582008-12-11 12:02:20 +00009053 // Force the inline caches into generic state.
9054 CompileRun("testIndexed(new Array(1))");
9055 // Test that the indexed access check is called.
9056 value = CompileRun("testIndexed(obj)");
9057 CHECK(value->IsNumber());
9058 CHECK_EQ(1, value->Int32Value());
9059 CHECK_EQ(42, indexed_access_count);
9060
9061 // Check that the named access check is called when invoking
9062 // functions on an object that requires access checks.
9063 CompileRun("obj.f = function() {}");
9064 CompileRun("function testCallNormal(obj) {"
9065 " for (var i = 0; i < 10; i++) obj.f();"
9066 "}");
9067 CompileRun("testCallNormal(obj)");
9068 CHECK_EQ(74, named_access_count);
9069
9070 // Force obj into slow case.
9071 value = CompileRun("delete obj.prop");
9072 CHECK(value->BooleanValue());
9073 // Force inline caches into dictionary probing mode.
9074 CompileRun("var o = { x: 0 }; delete o.x; testProp(o);");
9075 // Test that the named access check is called.
9076 value = CompileRun("testProp(obj);");
9077 CHECK(value->IsNumber());
9078 CHECK_EQ(1, value->Int32Value());
9079 CHECK_EQ(96, named_access_count);
9080
9081 // Force the call inline cache into dictionary probing mode.
9082 CompileRun("o.f = function() {}; testCallNormal(o)");
9083 // Test that the named access check is still called for each
9084 // invocation of the function.
9085 value = CompileRun("testCallNormal(obj)");
9086 CHECK_EQ(106, named_access_count);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009087
9088 context1->Exit();
9089 context0->Exit();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009090}
9091
9092
9093static bool NamedAccessFlatten(Local<v8::Object> global,
9094 Local<Value> name,
9095 v8::AccessType type,
9096 Local<Value> data) {
9097 char buf[100];
9098 int len;
9099
9100 CHECK(name->IsString());
9101
9102 memset(buf, 0x1, sizeof(buf));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009103 len = name.As<String>()->WriteOneByte(reinterpret_cast<uint8_t*>(buf));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009104 CHECK_EQ(4, len);
9105
9106 uint16_t buf2[100];
9107
9108 memset(buf, 0x1, sizeof(buf));
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00009109 len = name.As<String>()->Write(buf2);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009110 CHECK_EQ(4, len);
9111
9112 return true;
9113}
9114
9115
9116static bool IndexedAccessFlatten(Local<v8::Object> global,
9117 uint32_t key,
9118 v8::AccessType type,
9119 Local<Value> data) {
9120 return true;
9121}
9122
9123
9124// Regression test. In access checks, operations that may cause
9125// garbage collection are not allowed. It used to be the case that
9126// using the Write operation on a string could cause a garbage
9127// collection due to flattening of the string. This is no longer the
9128// case.
9129THREADED_TEST(AccessControlFlatten) {
9130 named_access_count = 0;
9131 indexed_access_count = 0;
9132
machenbach@chromium.org528ce022013-09-23 14:09:36 +00009133 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009134 v8::HandleScope handle_scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009135
9136 // Create an environment.
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009137 v8::Local<Context> context0 = Context::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009138 context0->Enter();
9139
9140 // Create an object that requires access-check functions to be
9141 // called for cross-domain access.
9142 v8::Handle<v8::ObjectTemplate> object_template = v8::ObjectTemplate::New();
9143 object_template->SetAccessCheckCallbacks(NamedAccessFlatten,
9144 IndexedAccessFlatten);
9145 Local<v8::Object> object = object_template->NewInstance();
9146
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009147 v8::HandleScope scope1(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009148
9149 // Create another environment.
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009150 v8::Local<Context> context1 = Context::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009151 context1->Enter();
9152
9153 // Make easy access to the object from the other environment.
9154 v8::Handle<v8::Object> global1 = context1->Global();
9155 global1->Set(v8_str("obj"), object);
9156
9157 v8::Handle<Value> value;
9158
9159 value = v8_compile("var p = 'as' + 'df';")->Run();
9160 value = v8_compile("obj[p];")->Run();
9161
9162 context1->Exit();
9163 context0->Exit();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009164}
9165
9166
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009167static void AccessControlNamedGetter(
9168 Local<String>,
9169 const v8::PropertyCallbackInfo<v8::Value>& info) {
9170 info.GetReturnValue().Set(42);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009171}
9172
9173
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009174static void AccessControlNamedSetter(
9175 Local<String>,
9176 Local<Value> value,
9177 const v8::PropertyCallbackInfo<v8::Value>& info) {
9178 info.GetReturnValue().Set(value);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009179}
9180
9181
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009182static void AccessControlIndexedGetter(
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009183 uint32_t index,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009184 const v8::PropertyCallbackInfo<v8::Value>& info) {
9185 info.GetReturnValue().Set(v8_num(42));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009186}
9187
9188
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009189static void AccessControlIndexedSetter(
9190 uint32_t,
9191 Local<Value> value,
9192 const v8::PropertyCallbackInfo<v8::Value>& info) {
9193 info.GetReturnValue().Set(value);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009194}
9195
9196
9197THREADED_TEST(AccessControlInterceptorIC) {
9198 named_access_count = 0;
9199 indexed_access_count = 0;
9200
machenbach@chromium.org528ce022013-09-23 14:09:36 +00009201 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009202 v8::HandleScope handle_scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009203
9204 // Create an environment.
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009205 v8::Local<Context> context0 = Context::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009206 context0->Enter();
9207
9208 // Create an object that requires access-check functions to be
9209 // called for cross-domain access. The object also has interceptors
9210 // interceptor.
9211 v8::Handle<v8::ObjectTemplate> object_template = v8::ObjectTemplate::New();
9212 object_template->SetAccessCheckCallbacks(NamedAccessCounter,
9213 IndexedAccessCounter);
9214 object_template->SetNamedPropertyHandler(AccessControlNamedGetter,
9215 AccessControlNamedSetter);
9216 object_template->SetIndexedPropertyHandler(AccessControlIndexedGetter,
9217 AccessControlIndexedSetter);
9218 Local<v8::Object> object = object_template->NewInstance();
9219
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009220 v8::HandleScope scope1(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009221
9222 // Create another environment.
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009223 v8::Local<Context> context1 = Context::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009224 context1->Enter();
9225
9226 // Make easy access to the object from the other environment.
9227 v8::Handle<v8::Object> global1 = context1->Global();
9228 global1->Set(v8_str("obj"), object);
9229
9230 v8::Handle<Value> value;
9231
9232 // Check that the named access-control function is called every time
9233 // eventhough there is an interceptor on the object.
9234 value = v8_compile("for (var i = 0; i < 10; i++) obj.x = 1;")->Run();
9235 value = v8_compile("for (var i = 0; i < 10; i++) obj.x;"
9236 "obj.x")->Run();
9237 CHECK(value->IsNumber());
9238 CHECK_EQ(42, value->Int32Value());
9239 CHECK_EQ(21, named_access_count);
9240
9241 value = v8_compile("var p = 'x';")->Run();
9242 value = v8_compile("for (var i = 0; i < 10; i++) obj[p] = 1;")->Run();
9243 value = v8_compile("for (var i = 0; i < 10; i++) obj[p];"
9244 "obj[p]")->Run();
9245 CHECK(value->IsNumber());
9246 CHECK_EQ(42, value->Int32Value());
9247 CHECK_EQ(42, named_access_count);
9248
9249 // Check that the indexed access-control function is called every
9250 // time eventhough there is an interceptor on the object.
9251 value = v8_compile("for (var i = 0; i < 10; i++) obj[0] = 1;")->Run();
9252 value = v8_compile("for (var i = 0; i < 10; i++) obj[0];"
9253 "obj[0]")->Run();
9254 CHECK(value->IsNumber());
9255 CHECK_EQ(42, value->Int32Value());
9256 CHECK_EQ(21, indexed_access_count);
9257
9258 context1->Exit();
9259 context0->Exit();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009260}
9261
9262
9263THREADED_TEST(Version) {
9264 v8::V8::GetVersion();
9265}
9266
9267
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009268static void InstanceFunctionCallback(
9269 const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009270 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009271 args.GetReturnValue().Set(v8_num(12));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009272}
9273
9274
9275THREADED_TEST(InstanceProperties) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009276 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00009277 v8::HandleScope handle_scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009278
9279 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
9280 Local<ObjectTemplate> instance = t->InstanceTemplate();
9281
9282 instance->Set(v8_str("x"), v8_num(42));
9283 instance->Set(v8_str("f"),
9284 v8::FunctionTemplate::New(InstanceFunctionCallback));
9285
9286 Local<Value> o = t->GetFunction()->NewInstance();
9287
9288 context->Global()->Set(v8_str("i"), o);
9289 Local<Value> value = Script::Compile(v8_str("i.x"))->Run();
9290 CHECK_EQ(42, value->Int32Value());
9291
9292 value = Script::Compile(v8_str("i.f()"))->Run();
9293 CHECK_EQ(12, value->Int32Value());
9294}
9295
9296
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009297static void GlobalObjectInstancePropertiesGet(
9298 Local<String> key,
9299 const v8::PropertyCallbackInfo<v8::Value>&) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009300 ApiTestFuzzer::Fuzz();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009301}
9302
9303
9304THREADED_TEST(GlobalObjectInstanceProperties) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00009305 v8::HandleScope handle_scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009306
9307 Local<Value> global_object;
9308
9309 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
9310 t->InstanceTemplate()->SetNamedPropertyHandler(
9311 GlobalObjectInstancePropertiesGet);
9312 Local<ObjectTemplate> instance_template = t->InstanceTemplate();
9313 instance_template->Set(v8_str("x"), v8_num(42));
9314 instance_template->Set(v8_str("f"),
9315 v8::FunctionTemplate::New(InstanceFunctionCallback));
9316
kasperl@chromium.orga5551262010-12-07 12:49:48 +00009317 // The script to check how Crankshaft compiles missing global function
9318 // invocations. function g is not defined and should throw on call.
9319 const char* script =
9320 "function wrapper(call) {"
9321 " var x = 0, y = 1;"
9322 " for (var i = 0; i < 1000; i++) {"
9323 " x += i * 100;"
9324 " y += i * 100;"
9325 " }"
9326 " if (call) g();"
9327 "}"
9328 "for (var i = 0; i < 17; i++) wrapper(false);"
9329 "var thrown = 0;"
9330 "try { wrapper(true); } catch (e) { thrown = 1; };"
9331 "thrown";
9332
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009333 {
9334 LocalContext env(NULL, instance_template);
9335 // Hold on to the global object so it can be used again in another
9336 // environment initialization.
9337 global_object = env->Global();
9338
9339 Local<Value> value = Script::Compile(v8_str("x"))->Run();
9340 CHECK_EQ(42, value->Int32Value());
9341 value = Script::Compile(v8_str("f()"))->Run();
9342 CHECK_EQ(12, value->Int32Value());
kasperl@chromium.orga5551262010-12-07 12:49:48 +00009343 value = Script::Compile(v8_str(script))->Run();
9344 CHECK_EQ(1, value->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009345 }
9346
9347 {
9348 // Create new environment reusing the global object.
9349 LocalContext env(NULL, instance_template, global_object);
9350 Local<Value> value = Script::Compile(v8_str("x"))->Run();
9351 CHECK_EQ(42, value->Int32Value());
9352 value = Script::Compile(v8_str("f()"))->Run();
9353 CHECK_EQ(12, value->Int32Value());
kasperl@chromium.orga5551262010-12-07 12:49:48 +00009354 value = Script::Compile(v8_str(script))->Run();
9355 CHECK_EQ(1, value->Int32Value());
9356 }
9357}
9358
9359
9360THREADED_TEST(CallKnownGlobalReceiver) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00009361 v8::HandleScope handle_scope(CcTest::isolate());
kasperl@chromium.orga5551262010-12-07 12:49:48 +00009362
9363 Local<Value> global_object;
9364
9365 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
9366 Local<ObjectTemplate> instance_template = t->InstanceTemplate();
9367
9368 // The script to check that we leave global object not
9369 // global object proxy on stack when we deoptimize from inside
9370 // arguments evaluation.
9371 // To provoke error we need to both force deoptimization
9372 // from arguments evaluation and to force CallIC to take
9373 // CallIC_Miss code path that can't cope with global proxy.
9374 const char* script =
9375 "function bar(x, y) { try { } finally { } }"
9376 "function baz(x) { try { } finally { } }"
9377 "function bom(x) { try { } finally { } }"
9378 "function foo(x) { bar([x], bom(2)); }"
9379 "for (var i = 0; i < 10000; i++) foo(1);"
9380 "foo";
9381
9382 Local<Value> foo;
9383 {
9384 LocalContext env(NULL, instance_template);
9385 // Hold on to the global object so it can be used again in another
9386 // environment initialization.
9387 global_object = env->Global();
9388 foo = Script::Compile(v8_str(script))->Run();
9389 }
9390
9391 {
9392 // Create new environment reusing the global object.
9393 LocalContext env(NULL, instance_template, global_object);
9394 env->Global()->Set(v8_str("foo"), foo);
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00009395 Script::Compile(v8_str("foo()"))->Run();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009396 }
9397}
9398
9399
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009400static void ShadowFunctionCallback(
9401 const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009402 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009403 args.GetReturnValue().Set(v8_num(42));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009404}
9405
9406
9407static int shadow_y;
9408static int shadow_y_setter_call_count;
9409static int shadow_y_getter_call_count;
9410
9411
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009412static void ShadowYSetter(Local<String>,
9413 Local<Value>,
9414 const v8::PropertyCallbackInfo<void>&) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009415 shadow_y_setter_call_count++;
9416 shadow_y = 42;
9417}
9418
9419
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009420static void ShadowYGetter(Local<String> name,
9421 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009422 ApiTestFuzzer::Fuzz();
9423 shadow_y_getter_call_count++;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009424 info.GetReturnValue().Set(v8_num(shadow_y));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009425}
9426
9427
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009428static void ShadowIndexedGet(uint32_t index,
9429 const v8::PropertyCallbackInfo<v8::Value>&) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009430}
9431
9432
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009433static void ShadowNamedGet(Local<String> key,
9434 const v8::PropertyCallbackInfo<v8::Value>&) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009435}
9436
9437
9438THREADED_TEST(ShadowObject) {
9439 shadow_y = shadow_y_setter_call_count = shadow_y_getter_call_count = 0;
machenbach@chromium.org528ce022013-09-23 14:09:36 +00009440 v8::HandleScope handle_scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009441
9442 Local<ObjectTemplate> global_template = v8::ObjectTemplate::New();
9443 LocalContext context(NULL, global_template);
9444
9445 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
9446 t->InstanceTemplate()->SetNamedPropertyHandler(ShadowNamedGet);
9447 t->InstanceTemplate()->SetIndexedPropertyHandler(ShadowIndexedGet);
9448 Local<ObjectTemplate> proto = t->PrototypeTemplate();
9449 Local<ObjectTemplate> instance = t->InstanceTemplate();
9450
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009451 proto->Set(v8_str("f"),
mmassi@chromium.org49a44672012-12-04 13:52:03 +00009452 v8::FunctionTemplate::New(ShadowFunctionCallback, Local<Value>()));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009453 proto->Set(v8_str("x"), v8_num(12));
9454
9455 instance->SetAccessor(v8_str("y"), ShadowYGetter, ShadowYSetter);
9456
9457 Local<Value> o = t->GetFunction()->NewInstance();
9458 context->Global()->Set(v8_str("__proto__"), o);
9459
9460 Local<Value> value =
ricow@chromium.orgd2be9012011-06-01 06:00:58 +00009461 Script::Compile(v8_str("this.propertyIsEnumerable(0)"))->Run();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009462 CHECK(value->IsBoolean());
9463 CHECK(!value->BooleanValue());
9464
9465 value = Script::Compile(v8_str("x"))->Run();
9466 CHECK_EQ(12, value->Int32Value());
9467
9468 value = Script::Compile(v8_str("f()"))->Run();
9469 CHECK_EQ(42, value->Int32Value());
9470
mmassi@chromium.org7028c052012-06-13 11:51:58 +00009471 Script::Compile(v8_str("y = 43"))->Run();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009472 CHECK_EQ(1, shadow_y_setter_call_count);
9473 value = Script::Compile(v8_str("y"))->Run();
9474 CHECK_EQ(1, shadow_y_getter_call_count);
9475 CHECK_EQ(42, value->Int32Value());
9476}
9477
9478
9479THREADED_TEST(HiddenPrototype) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009480 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00009481 v8::HandleScope handle_scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009482
9483 Local<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New();
9484 t0->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
9485 Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New();
9486 t1->SetHiddenPrototype(true);
9487 t1->InstanceTemplate()->Set(v8_str("y"), v8_num(1));
9488 Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New();
9489 t2->SetHiddenPrototype(true);
9490 t2->InstanceTemplate()->Set(v8_str("z"), v8_num(2));
9491 Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New();
9492 t3->InstanceTemplate()->Set(v8_str("u"), v8_num(3));
9493
9494 Local<v8::Object> o0 = t0->GetFunction()->NewInstance();
9495 Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
9496 Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
9497 Local<v8::Object> o3 = t3->GetFunction()->NewInstance();
9498
9499 // Setting the prototype on an object skips hidden prototypes.
9500 CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
9501 o0->Set(v8_str("__proto__"), o1);
9502 CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
9503 CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
9504 o0->Set(v8_str("__proto__"), o2);
9505 CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
9506 CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
9507 CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
9508 o0->Set(v8_str("__proto__"), o3);
9509 CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
9510 CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
9511 CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
9512 CHECK_EQ(3, o0->Get(v8_str("u"))->Int32Value());
9513
9514 // Getting the prototype of o0 should get the first visible one
9515 // which is o3. Therefore, z should not be defined on the prototype
9516 // object.
9517 Local<Value> proto = o0->Get(v8_str("__proto__"));
9518 CHECK(proto->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00009519 CHECK(proto.As<v8::Object>()->Get(v8_str("z"))->IsUndefined());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009520}
9521
9522
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00009523THREADED_TEST(HiddenPrototypeSet) {
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00009524 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00009525 v8::HandleScope handle_scope(context->GetIsolate());
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00009526
9527 Local<v8::FunctionTemplate> ot = v8::FunctionTemplate::New();
9528 Local<v8::FunctionTemplate> ht = v8::FunctionTemplate::New();
9529 ht->SetHiddenPrototype(true);
9530 Local<v8::FunctionTemplate> pt = v8::FunctionTemplate::New();
9531 ht->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
9532
9533 Local<v8::Object> o = ot->GetFunction()->NewInstance();
9534 Local<v8::Object> h = ht->GetFunction()->NewInstance();
9535 Local<v8::Object> p = pt->GetFunction()->NewInstance();
9536 o->Set(v8_str("__proto__"), h);
9537 h->Set(v8_str("__proto__"), p);
9538
9539 // Setting a property that exists on the hidden prototype goes there.
9540 o->Set(v8_str("x"), v8_num(7));
9541 CHECK_EQ(7, o->Get(v8_str("x"))->Int32Value());
9542 CHECK_EQ(7, h->Get(v8_str("x"))->Int32Value());
9543 CHECK(p->Get(v8_str("x"))->IsUndefined());
9544
9545 // Setting a new property should not be forwarded to the hidden prototype.
9546 o->Set(v8_str("y"), v8_num(6));
9547 CHECK_EQ(6, o->Get(v8_str("y"))->Int32Value());
9548 CHECK(h->Get(v8_str("y"))->IsUndefined());
9549 CHECK(p->Get(v8_str("y"))->IsUndefined());
9550
9551 // Setting a property that only exists on a prototype of the hidden prototype
9552 // is treated normally again.
9553 p->Set(v8_str("z"), v8_num(8));
9554 CHECK_EQ(8, o->Get(v8_str("z"))->Int32Value());
9555 CHECK_EQ(8, h->Get(v8_str("z"))->Int32Value());
9556 CHECK_EQ(8, p->Get(v8_str("z"))->Int32Value());
9557 o->Set(v8_str("z"), v8_num(9));
9558 CHECK_EQ(9, o->Get(v8_str("z"))->Int32Value());
9559 CHECK_EQ(8, h->Get(v8_str("z"))->Int32Value());
9560 CHECK_EQ(8, p->Get(v8_str("z"))->Int32Value());
9561}
9562
9563
9564// Regression test for issue 2457.
9565THREADED_TEST(HiddenPrototypeIdentityHash) {
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00009566 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00009567 v8::HandleScope handle_scope(context->GetIsolate());
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00009568
9569 Handle<FunctionTemplate> t = FunctionTemplate::New();
9570 t->SetHiddenPrototype(true);
9571 t->InstanceTemplate()->Set(v8_str("foo"), v8_num(75));
9572 Handle<Object> p = t->GetFunction()->NewInstance();
9573 Handle<Object> o = Object::New();
9574 o->SetPrototype(p);
9575
9576 int hash = o->GetIdentityHash();
9577 USE(hash);
9578 o->Set(v8_str("foo"), v8_num(42));
9579 ASSERT_EQ(hash, o->GetIdentityHash());
9580}
9581
9582
ager@chromium.org5c838252010-02-19 08:53:10 +00009583THREADED_TEST(SetPrototype) {
ager@chromium.org5c838252010-02-19 08:53:10 +00009584 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00009585 v8::HandleScope handle_scope(context->GetIsolate());
ager@chromium.org5c838252010-02-19 08:53:10 +00009586
9587 Local<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New();
9588 t0->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
9589 Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New();
9590 t1->SetHiddenPrototype(true);
9591 t1->InstanceTemplate()->Set(v8_str("y"), v8_num(1));
9592 Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New();
9593 t2->SetHiddenPrototype(true);
9594 t2->InstanceTemplate()->Set(v8_str("z"), v8_num(2));
9595 Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New();
9596 t3->InstanceTemplate()->Set(v8_str("u"), v8_num(3));
9597
9598 Local<v8::Object> o0 = t0->GetFunction()->NewInstance();
9599 Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
9600 Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
9601 Local<v8::Object> o3 = t3->GetFunction()->NewInstance();
9602
9603 // Setting the prototype on an object does not skip hidden prototypes.
9604 CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
9605 CHECK(o0->SetPrototype(o1));
9606 CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
9607 CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
9608 CHECK(o1->SetPrototype(o2));
9609 CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
9610 CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
9611 CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
9612 CHECK(o2->SetPrototype(o3));
9613 CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
9614 CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
9615 CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
9616 CHECK_EQ(3, o0->Get(v8_str("u"))->Int32Value());
9617
9618 // Getting the prototype of o0 should get the first visible one
9619 // which is o3. Therefore, z should not be defined on the prototype
9620 // object.
9621 Local<Value> proto = o0->Get(v8_str("__proto__"));
9622 CHECK(proto->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00009623 CHECK_EQ(proto.As<v8::Object>(), o3);
ager@chromium.org5c838252010-02-19 08:53:10 +00009624
9625 // However, Object::GetPrototype ignores hidden prototype.
9626 Local<Value> proto0 = o0->GetPrototype();
9627 CHECK(proto0->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00009628 CHECK_EQ(proto0.As<v8::Object>(), o1);
ager@chromium.org5c838252010-02-19 08:53:10 +00009629
9630 Local<Value> proto1 = o1->GetPrototype();
9631 CHECK(proto1->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00009632 CHECK_EQ(proto1.As<v8::Object>(), o2);
ager@chromium.org5c838252010-02-19 08:53:10 +00009633
9634 Local<Value> proto2 = o2->GetPrototype();
9635 CHECK(proto2->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00009636 CHECK_EQ(proto2.As<v8::Object>(), o3);
ager@chromium.org5c838252010-02-19 08:53:10 +00009637}
9638
9639
ricow@chromium.org27bf2882011-11-17 08:34:43 +00009640// Getting property names of an object with a prototype chain that
9641// triggers dictionary elements in GetLocalPropertyNames() shouldn't
9642// crash the runtime.
9643THREADED_TEST(Regress91517) {
9644 i::FLAG_allow_natives_syntax = true;
ricow@chromium.org27bf2882011-11-17 08:34:43 +00009645 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00009646 v8::HandleScope handle_scope(context->GetIsolate());
ricow@chromium.org27bf2882011-11-17 08:34:43 +00009647
9648 Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New();
9649 t1->SetHiddenPrototype(true);
9650 t1->InstanceTemplate()->Set(v8_str("foo"), v8_num(1));
9651 Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New();
9652 t2->SetHiddenPrototype(true);
9653 t2->InstanceTemplate()->Set(v8_str("fuz1"), v8_num(2));
9654 t2->InstanceTemplate()->Set(v8_str("objects"), v8::Object::New());
9655 t2->InstanceTemplate()->Set(v8_str("fuz2"), v8_num(2));
9656 Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New();
9657 t3->SetHiddenPrototype(true);
9658 t3->InstanceTemplate()->Set(v8_str("boo"), v8_num(3));
9659 Local<v8::FunctionTemplate> t4 = v8::FunctionTemplate::New();
9660 t4->InstanceTemplate()->Set(v8_str("baz"), v8_num(4));
9661
9662 // Force dictionary-based properties.
9663 i::ScopedVector<char> name_buf(1024);
9664 for (int i = 1; i <= 1000; i++) {
9665 i::OS::SNPrintF(name_buf, "sdf%d", i);
9666 t2->InstanceTemplate()->Set(v8_str(name_buf.start()), v8_num(2));
9667 }
9668
9669 Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
9670 Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
9671 Local<v8::Object> o3 = t3->GetFunction()->NewInstance();
9672 Local<v8::Object> o4 = t4->GetFunction()->NewInstance();
9673
9674 // Create prototype chain of hidden prototypes.
9675 CHECK(o4->SetPrototype(o3));
9676 CHECK(o3->SetPrototype(o2));
9677 CHECK(o2->SetPrototype(o1));
9678
9679 // Call the runtime version of GetLocalPropertyNames() on the natively
9680 // created object through JavaScript.
9681 context->Global()->Set(v8_str("obj"), o4);
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +00009682 CompileRun("var names = %GetLocalPropertyNames(obj, true);");
ricow@chromium.org27bf2882011-11-17 08:34:43 +00009683
9684 ExpectInt32("names.length", 1006);
9685 ExpectTrue("names.indexOf(\"baz\") >= 0");
9686 ExpectTrue("names.indexOf(\"boo\") >= 0");
9687 ExpectTrue("names.indexOf(\"foo\") >= 0");
9688 ExpectTrue("names.indexOf(\"fuz1\") >= 0");
9689 ExpectTrue("names.indexOf(\"fuz2\") >= 0");
9690 ExpectFalse("names[1005] == undefined");
9691}
9692
9693
ricow@chromium.org2c99e282011-07-28 09:15:17 +00009694THREADED_TEST(FunctionReadOnlyPrototype) {
ager@chromium.org04921a82011-06-27 13:21:41 +00009695 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00009696 v8::HandleScope handle_scope(context->GetIsolate());
ager@chromium.org04921a82011-06-27 13:21:41 +00009697
9698 Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New();
ricow@chromium.org2c99e282011-07-28 09:15:17 +00009699 t1->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(42));
9700 t1->ReadOnlyPrototype();
ager@chromium.org04921a82011-06-27 13:21:41 +00009701 context->Global()->Set(v8_str("func1"), t1->GetFunction());
ricow@chromium.org2c99e282011-07-28 09:15:17 +00009702 // Configured value of ReadOnly flag.
ager@chromium.org04921a82011-06-27 13:21:41 +00009703 CHECK(CompileRun(
9704 "(function() {"
9705 " descriptor = Object.getOwnPropertyDescriptor(func1, 'prototype');"
ricow@chromium.org2c99e282011-07-28 09:15:17 +00009706 " return (descriptor['writable'] == false);"
ager@chromium.org04921a82011-06-27 13:21:41 +00009707 "})()")->BooleanValue());
ricow@chromium.org2c99e282011-07-28 09:15:17 +00009708 CHECK_EQ(42, CompileRun("func1.prototype.x")->Int32Value());
9709 CHECK_EQ(42,
9710 CompileRun("func1.prototype = {}; func1.prototype.x")->Int32Value());
ager@chromium.org04921a82011-06-27 13:21:41 +00009711
9712 Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New();
ricow@chromium.org2c99e282011-07-28 09:15:17 +00009713 t2->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(42));
ager@chromium.org04921a82011-06-27 13:21:41 +00009714 context->Global()->Set(v8_str("func2"), t2->GetFunction());
ricow@chromium.org2c99e282011-07-28 09:15:17 +00009715 // Default value of ReadOnly flag.
ager@chromium.org04921a82011-06-27 13:21:41 +00009716 CHECK(CompileRun(
9717 "(function() {"
9718 " descriptor = Object.getOwnPropertyDescriptor(func2, 'prototype');"
ricow@chromium.org2c99e282011-07-28 09:15:17 +00009719 " return (descriptor['writable'] == true);"
ager@chromium.org04921a82011-06-27 13:21:41 +00009720 "})()")->BooleanValue());
ricow@chromium.org2c99e282011-07-28 09:15:17 +00009721 CHECK_EQ(42, CompileRun("func2.prototype.x")->Int32Value());
ager@chromium.org04921a82011-06-27 13:21:41 +00009722}
9723
9724
ager@chromium.org5c838252010-02-19 08:53:10 +00009725THREADED_TEST(SetPrototypeThrows) {
ager@chromium.org5c838252010-02-19 08:53:10 +00009726 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00009727 v8::HandleScope handle_scope(context->GetIsolate());
ager@chromium.org5c838252010-02-19 08:53:10 +00009728
9729 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
9730
9731 Local<v8::Object> o0 = t->GetFunction()->NewInstance();
9732 Local<v8::Object> o1 = t->GetFunction()->NewInstance();
9733
9734 CHECK(o0->SetPrototype(o1));
9735 // If setting the prototype leads to the cycle, SetPrototype should
9736 // return false and keep VM in sane state.
9737 v8::TryCatch try_catch;
9738 CHECK(!o1->SetPrototype(o0));
9739 CHECK(!try_catch.HasCaught());
machenbach@chromium.org528ce022013-09-23 14:09:36 +00009740 ASSERT(!CcTest::i_isolate()->has_pending_exception());
ager@chromium.org5c838252010-02-19 08:53:10 +00009741
9742 CHECK_EQ(42, CompileRun("function f() { return 42; }; f()")->Int32Value());
9743}
9744
9745
verwaest@chromium.org662436e2013-08-28 08:41:27 +00009746THREADED_TEST(FunctionRemovePrototype) {
9747 LocalContext context;
9748 v8::HandleScope handle_scope(context->GetIsolate());
9749
9750 Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New();
9751 t1->RemovePrototype();
9752 Local<v8::Function> fun = t1->GetFunction();
9753 context->Global()->Set(v8_str("fun"), fun);
9754 CHECK(!CompileRun("'prototype' in fun")->BooleanValue());
9755
9756 v8::TryCatch try_catch;
9757 CompileRun("new fun()");
9758 CHECK(try_catch.HasCaught());
9759
9760 try_catch.Reset();
9761 fun->NewInstance();
9762 CHECK(try_catch.HasCaught());
9763}
9764
9765
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009766THREADED_TEST(GetterSetterExceptions) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009767 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00009768 v8::HandleScope handle_scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009769 CompileRun(
9770 "function Foo() { };"
9771 "function Throw() { throw 5; };"
9772 "var x = { };"
9773 "x.__defineSetter__('set', Throw);"
9774 "x.__defineGetter__('get', Throw);");
9775 Local<v8::Object> x =
9776 Local<v8::Object>::Cast(context->Global()->Get(v8_str("x")));
9777 v8::TryCatch try_catch;
9778 x->Set(v8_str("set"), v8::Integer::New(8));
9779 x->Get(v8_str("get"));
9780 x->Set(v8_str("set"), v8::Integer::New(8));
9781 x->Get(v8_str("get"));
9782 x->Set(v8_str("set"), v8::Integer::New(8));
9783 x->Get(v8_str("get"));
9784 x->Set(v8_str("set"), v8::Integer::New(8));
9785 x->Get(v8_str("get"));
9786}
9787
9788
9789THREADED_TEST(Constructor) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009790 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00009791 v8::HandleScope handle_scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009792 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
9793 templ->SetClassName(v8_str("Fun"));
9794 Local<Function> cons = templ->GetFunction();
9795 context->Global()->Set(v8_str("Fun"), cons);
9796 Local<v8::Object> inst = cons->NewInstance();
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00009797 i::Handle<i::JSObject> obj(v8::Utils::OpenHandle(*inst));
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00009798 CHECK(obj->IsJSObject());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009799 Local<Value> value = CompileRun("(new Fun()).constructor === Fun");
9800 CHECK(value->BooleanValue());
9801}
9802
lrn@chromium.org1c092762011-05-09 09:42:16 +00009803
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009804static void ConstructorCallback(
9805 const v8::FunctionCallbackInfo<v8::Value>& args) {
lrn@chromium.org1c092762011-05-09 09:42:16 +00009806 ApiTestFuzzer::Fuzz();
9807 Local<Object> This;
9808
9809 if (args.IsConstructCall()) {
9810 Local<Object> Holder = args.Holder();
9811 This = Object::New();
9812 Local<Value> proto = Holder->GetPrototype();
9813 if (proto->IsObject()) {
9814 This->SetPrototype(proto);
9815 }
9816 } else {
9817 This = args.This();
9818 }
9819
9820 This->Set(v8_str("a"), args[0]);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009821 args.GetReturnValue().Set(This);
lrn@chromium.org1c092762011-05-09 09:42:16 +00009822}
9823
9824
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009825static void FakeConstructorCallback(
9826 const v8::FunctionCallbackInfo<v8::Value>& args) {
lrn@chromium.org1c092762011-05-09 09:42:16 +00009827 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009828 args.GetReturnValue().Set(args[0]);
lrn@chromium.org1c092762011-05-09 09:42:16 +00009829}
9830
9831
9832THREADED_TEST(ConstructorForObject) {
lrn@chromium.org1c092762011-05-09 09:42:16 +00009833 LocalContext context;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00009834 v8::Isolate* isolate = context->GetIsolate();
9835 v8::HandleScope handle_scope(isolate);
lrn@chromium.org1c092762011-05-09 09:42:16 +00009836
9837 { Local<ObjectTemplate> instance_template = ObjectTemplate::New();
9838 instance_template->SetCallAsFunctionHandler(ConstructorCallback);
9839 Local<Object> instance = instance_template->NewInstance();
9840 context->Global()->Set(v8_str("obj"), instance);
9841 v8::TryCatch try_catch;
9842 Local<Value> value;
9843 CHECK(!try_catch.HasCaught());
9844
9845 // Call the Object's constructor with a 32-bit signed integer.
9846 value = CompileRun("(function() { var o = new obj(28); return o.a; })()");
9847 CHECK(!try_catch.HasCaught());
9848 CHECK(value->IsInt32());
9849 CHECK_EQ(28, value->Int32Value());
9850
9851 Local<Value> args1[] = { v8_num(28) };
9852 Local<Value> value_obj1 = instance->CallAsConstructor(1, args1);
9853 CHECK(value_obj1->IsObject());
9854 Local<Object> object1 = Local<Object>::Cast(value_obj1);
9855 value = object1->Get(v8_str("a"));
9856 CHECK(value->IsInt32());
9857 CHECK(!try_catch.HasCaught());
9858 CHECK_EQ(28, value->Int32Value());
9859
9860 // Call the Object's constructor with a String.
9861 value = CompileRun(
9862 "(function() { var o = new obj('tipli'); return o.a; })()");
9863 CHECK(!try_catch.HasCaught());
9864 CHECK(value->IsString());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00009865 String::Utf8Value string_value1(value->ToString());
lrn@chromium.org1c092762011-05-09 09:42:16 +00009866 CHECK_EQ("tipli", *string_value1);
9867
9868 Local<Value> args2[] = { v8_str("tipli") };
9869 Local<Value> value_obj2 = instance->CallAsConstructor(1, args2);
9870 CHECK(value_obj2->IsObject());
9871 Local<Object> object2 = Local<Object>::Cast(value_obj2);
9872 value = object2->Get(v8_str("a"));
9873 CHECK(!try_catch.HasCaught());
9874 CHECK(value->IsString());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00009875 String::Utf8Value string_value2(value->ToString());
lrn@chromium.org1c092762011-05-09 09:42:16 +00009876 CHECK_EQ("tipli", *string_value2);
9877
9878 // Call the Object's constructor with a Boolean.
9879 value = CompileRun("(function() { var o = new obj(true); return o.a; })()");
9880 CHECK(!try_catch.HasCaught());
9881 CHECK(value->IsBoolean());
9882 CHECK_EQ(true, value->BooleanValue());
9883
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00009884 Handle<Value> args3[] = { v8::True(isolate) };
lrn@chromium.org1c092762011-05-09 09:42:16 +00009885 Local<Value> value_obj3 = instance->CallAsConstructor(1, args3);
9886 CHECK(value_obj3->IsObject());
9887 Local<Object> object3 = Local<Object>::Cast(value_obj3);
9888 value = object3->Get(v8_str("a"));
9889 CHECK(!try_catch.HasCaught());
9890 CHECK(value->IsBoolean());
9891 CHECK_EQ(true, value->BooleanValue());
9892
9893 // Call the Object's constructor with undefined.
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00009894 Handle<Value> args4[] = { v8::Undefined(isolate) };
lrn@chromium.org1c092762011-05-09 09:42:16 +00009895 Local<Value> value_obj4 = instance->CallAsConstructor(1, args4);
9896 CHECK(value_obj4->IsObject());
9897 Local<Object> object4 = Local<Object>::Cast(value_obj4);
9898 value = object4->Get(v8_str("a"));
9899 CHECK(!try_catch.HasCaught());
9900 CHECK(value->IsUndefined());
9901
9902 // Call the Object's constructor with null.
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00009903 Handle<Value> args5[] = { v8::Null(isolate) };
lrn@chromium.org1c092762011-05-09 09:42:16 +00009904 Local<Value> value_obj5 = instance->CallAsConstructor(1, args5);
9905 CHECK(value_obj5->IsObject());
9906 Local<Object> object5 = Local<Object>::Cast(value_obj5);
9907 value = object5->Get(v8_str("a"));
9908 CHECK(!try_catch.HasCaught());
9909 CHECK(value->IsNull());
9910 }
9911
9912 // Check exception handling when there is no constructor set for the Object.
9913 { Local<ObjectTemplate> instance_template = ObjectTemplate::New();
9914 Local<Object> instance = instance_template->NewInstance();
9915 context->Global()->Set(v8_str("obj2"), instance);
9916 v8::TryCatch try_catch;
9917 Local<Value> value;
9918 CHECK(!try_catch.HasCaught());
9919
9920 value = CompileRun("new obj2(28)");
9921 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00009922 String::Utf8Value exception_value1(try_catch.Exception());
lrn@chromium.org1c092762011-05-09 09:42:16 +00009923 CHECK_EQ("TypeError: object is not a function", *exception_value1);
9924 try_catch.Reset();
9925
9926 Local<Value> args[] = { v8_num(29) };
9927 value = instance->CallAsConstructor(1, args);
9928 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00009929 String::Utf8Value exception_value2(try_catch.Exception());
lrn@chromium.org1c092762011-05-09 09:42:16 +00009930 CHECK_EQ("TypeError: #<Object> is not a function", *exception_value2);
9931 try_catch.Reset();
9932 }
9933
9934 // Check the case when constructor throws exception.
9935 { Local<ObjectTemplate> instance_template = ObjectTemplate::New();
9936 instance_template->SetCallAsFunctionHandler(ThrowValue);
9937 Local<Object> instance = instance_template->NewInstance();
9938 context->Global()->Set(v8_str("obj3"), instance);
9939 v8::TryCatch try_catch;
9940 Local<Value> value;
9941 CHECK(!try_catch.HasCaught());
9942
9943 value = CompileRun("new obj3(22)");
9944 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00009945 String::Utf8Value exception_value1(try_catch.Exception());
lrn@chromium.org1c092762011-05-09 09:42:16 +00009946 CHECK_EQ("22", *exception_value1);
9947 try_catch.Reset();
9948
9949 Local<Value> args[] = { v8_num(23) };
9950 value = instance->CallAsConstructor(1, args);
9951 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00009952 String::Utf8Value exception_value2(try_catch.Exception());
lrn@chromium.org1c092762011-05-09 09:42:16 +00009953 CHECK_EQ("23", *exception_value2);
9954 try_catch.Reset();
9955 }
9956
9957 // Check whether constructor returns with an object or non-object.
9958 { Local<FunctionTemplate> function_template =
9959 FunctionTemplate::New(FakeConstructorCallback);
9960 Local<Function> function = function_template->GetFunction();
9961 Local<Object> instance1 = function;
9962 context->Global()->Set(v8_str("obj4"), instance1);
9963 v8::TryCatch try_catch;
9964 Local<Value> value;
9965 CHECK(!try_catch.HasCaught());
9966
9967 CHECK(instance1->IsObject());
9968 CHECK(instance1->IsFunction());
9969
9970 value = CompileRun("new obj4(28)");
9971 CHECK(!try_catch.HasCaught());
9972 CHECK(value->IsObject());
9973
9974 Local<Value> args1[] = { v8_num(28) };
9975 value = instance1->CallAsConstructor(1, args1);
9976 CHECK(!try_catch.HasCaught());
9977 CHECK(value->IsObject());
9978
9979 Local<ObjectTemplate> instance_template = ObjectTemplate::New();
9980 instance_template->SetCallAsFunctionHandler(FakeConstructorCallback);
9981 Local<Object> instance2 = instance_template->NewInstance();
9982 context->Global()->Set(v8_str("obj5"), instance2);
9983 CHECK(!try_catch.HasCaught());
9984
9985 CHECK(instance2->IsObject());
9986 CHECK(!instance2->IsFunction());
9987
9988 value = CompileRun("new obj5(28)");
9989 CHECK(!try_catch.HasCaught());
9990 CHECK(!value->IsObject());
9991
9992 Local<Value> args2[] = { v8_num(28) };
9993 value = instance2->CallAsConstructor(1, args2);
9994 CHECK(!try_catch.HasCaught());
9995 CHECK(!value->IsObject());
9996 }
9997}
9998
9999
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010000THREADED_TEST(FunctionDescriptorException) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010001 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000010002 v8::HandleScope handle_scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010003 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
10004 templ->SetClassName(v8_str("Fun"));
10005 Local<Function> cons = templ->GetFunction();
10006 context->Global()->Set(v8_str("Fun"), cons);
10007 Local<Value> value = CompileRun(
10008 "function test() {"
10009 " try {"
10010 " (new Fun()).blah()"
10011 " } catch (e) {"
10012 " var str = String(e);"
10013 " if (str.indexOf('TypeError') == -1) return 1;"
10014 " if (str.indexOf('[object Fun]') != -1) return 2;"
whesse@chromium.org7a392b32011-01-31 11:30:36 +000010015 " if (str.indexOf('#<Fun>') == -1) return 3;"
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010016 " return 0;"
10017 " }"
10018 " return 4;"
10019 "}"
10020 "test();");
10021 CHECK_EQ(0, value->Int32Value());
10022}
10023
10024
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010025THREADED_TEST(EvalAliasedDynamic) {
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010026 LocalContext current;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000010027 v8::HandleScope scope(current->GetIsolate());
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010028
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010029 // Tests where aliased eval can only be resolved dynamically.
10030 Local<Script> script =
10031 Script::Compile(v8_str("function f(x) { "
10032 " var foo = 2;"
10033 " with (x) { return eval('foo'); }"
10034 "}"
10035 "foo = 0;"
10036 "result1 = f(new Object());"
ager@chromium.orge2902be2009-06-08 12:21:35 +000010037 "result2 = f(this);"
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010038 "var x = new Object();"
10039 "x.eval = function(x) { return 1; };"
10040 "result3 = f(x);"));
10041 script->Run();
10042 CHECK_EQ(2, current->Global()->Get(v8_str("result1"))->Int32Value());
10043 CHECK_EQ(0, current->Global()->Get(v8_str("result2"))->Int32Value());
10044 CHECK_EQ(1, current->Global()->Get(v8_str("result3"))->Int32Value());
10045
10046 v8::TryCatch try_catch;
10047 script =
10048 Script::Compile(v8_str("function f(x) { "
10049 " var bar = 2;"
10050 " with (x) { return eval('bar'); }"
10051 "}"
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000010052 "result4 = f(this)"));
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010053 script->Run();
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000010054 CHECK(!try_catch.HasCaught());
10055 CHECK_EQ(2, current->Global()->Get(v8_str("result4"))->Int32Value());
10056
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010057 try_catch.Reset();
10058}
10059
10060
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010061THREADED_TEST(CrossEval) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000010062 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010063 LocalContext other;
10064 LocalContext current;
10065
10066 Local<String> token = v8_str("<security token>");
10067 other->SetSecurityToken(token);
10068 current->SetSecurityToken(token);
10069
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000010070 // Set up reference from current to other.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010071 current->Global()->Set(v8_str("other"), other->Global());
10072
10073 // Check that new variables are introduced in other context.
10074 Local<Script> script =
10075 Script::Compile(v8_str("other.eval('var foo = 1234')"));
10076 script->Run();
10077 Local<Value> foo = other->Global()->Get(v8_str("foo"));
10078 CHECK_EQ(1234, foo->Int32Value());
10079 CHECK(!current->Global()->Has(v8_str("foo")));
10080
10081 // Check that writing to non-existing properties introduces them in
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010082 // the other context.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010083 script =
10084 Script::Compile(v8_str("other.eval('na = 1234')"));
10085 script->Run();
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010086 CHECK_EQ(1234, other->Global()->Get(v8_str("na"))->Int32Value());
10087 CHECK(!current->Global()->Has(v8_str("na")));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010088
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010089 // Check that global variables in current context are not visible in other
10090 // context.
10091 v8::TryCatch try_catch;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010092 script =
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010093 Script::Compile(v8_str("var bar = 42; other.eval('bar');"));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010094 Local<Value> result = script->Run();
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010095 CHECK(try_catch.HasCaught());
10096 try_catch.Reset();
10097
10098 // Check that local variables in current context are not visible in other
10099 // context.
10100 script =
10101 Script::Compile(v8_str("(function() { "
10102 " var baz = 87;"
10103 " return other.eval('baz');"
10104 "})();"));
10105 result = script->Run();
10106 CHECK(try_catch.HasCaught());
10107 try_catch.Reset();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010108
10109 // Check that global variables in the other environment are visible
10110 // when evaluting code.
10111 other->Global()->Set(v8_str("bis"), v8_num(1234));
10112 script = Script::Compile(v8_str("other.eval('bis')"));
10113 CHECK_EQ(1234, script->Run()->Int32Value());
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010114 CHECK(!try_catch.HasCaught());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010115
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010116 // Check that the 'this' pointer points to the global object evaluating
10117 // code.
10118 other->Global()->Set(v8_str("t"), other->Global());
10119 script = Script::Compile(v8_str("other.eval('this == t')"));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010120 result = script->Run();
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010121 CHECK(result->IsTrue());
10122 CHECK(!try_catch.HasCaught());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010123
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010124 // Check that variables introduced in with-statement are not visible in
10125 // other context.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010126 script =
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010127 Script::Compile(v8_str("with({x:2}){other.eval('x')}"));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010128 result = script->Run();
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010129 CHECK(try_catch.HasCaught());
10130 try_catch.Reset();
ager@chromium.org3bf7b912008-11-17 09:09:45 +000010131
10132 // Check that you cannot use 'eval.call' with another object than the
10133 // current global object.
ager@chromium.org3bf7b912008-11-17 09:09:45 +000010134 script =
10135 Script::Compile(v8_str("other.y = 1; eval.call(other, 'y')"));
10136 result = script->Run();
10137 CHECK(try_catch.HasCaught());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010138}
10139
10140
ager@chromium.orge2902be2009-06-08 12:21:35 +000010141// Test that calling eval in a context which has been detached from
10142// its global throws an exception. This behavior is consistent with
10143// other JavaScript implementations.
10144THREADED_TEST(EvalInDetachedGlobal) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000010145 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000010146 v8::HandleScope scope(isolate);
ager@chromium.orge2902be2009-06-08 12:21:35 +000010147
ulan@chromium.org57ff8812013-05-10 08:16:55 +000010148 v8::Local<Context> context0 = Context::New(isolate);
10149 v8::Local<Context> context1 = Context::New(isolate);
ager@chromium.orge2902be2009-06-08 12:21:35 +000010150
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000010151 // Set up function in context0 that uses eval from context0.
ager@chromium.orge2902be2009-06-08 12:21:35 +000010152 context0->Enter();
10153 v8::Handle<v8::Value> fun =
10154 CompileRun("var x = 42;"
10155 "(function() {"
10156 " var e = eval;"
10157 " return function(s) { return e(s); }"
10158 "})()");
10159 context0->Exit();
10160
10161 // Put the function into context1 and call it before and after
10162 // detaching the global. Before detaching, the call succeeds and
10163 // after detaching and exception is thrown.
10164 context1->Enter();
10165 context1->Global()->Set(v8_str("fun"), fun);
10166 v8::Handle<v8::Value> x_value = CompileRun("fun('x')");
10167 CHECK_EQ(42, x_value->Int32Value());
10168 context0->DetachGlobal();
10169 v8::TryCatch catcher;
10170 x_value = CompileRun("fun('x')");
10171 CHECK(x_value.IsEmpty());
10172 CHECK(catcher.HasCaught());
10173 context1->Exit();
ager@chromium.orge2902be2009-06-08 12:21:35 +000010174}
10175
10176
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010177THREADED_TEST(CrossLazyLoad) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000010178 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010179 LocalContext other;
10180 LocalContext current;
10181
10182 Local<String> token = v8_str("<security token>");
10183 other->SetSecurityToken(token);
10184 current->SetSecurityToken(token);
10185
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000010186 // Set up reference from current to other.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010187 current->Global()->Set(v8_str("other"), other->Global());
10188
10189 // Trigger lazy loading in other context.
10190 Local<Script> script =
10191 Script::Compile(v8_str("other.eval('new Date(42)')"));
10192 Local<Value> value = script->Run();
10193 CHECK_EQ(42.0, value->NumberValue());
10194}
10195
10196
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010197static void call_as_function(const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010198 ApiTestFuzzer::Fuzz();
sgjesse@chromium.org05521fc2009-05-21 07:37:44 +000010199 if (args.IsConstructCall()) {
10200 if (args[0]->IsInt32()) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010201 args.GetReturnValue().Set(v8_num(-args[0]->Int32Value()));
10202 return;
sgjesse@chromium.org05521fc2009-05-21 07:37:44 +000010203 }
10204 }
10205
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010206 args.GetReturnValue().Set(args[0]);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010207}
10208
10209
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +000010210static void ReturnThis(const v8::FunctionCallbackInfo<v8::Value>& args) {
10211 args.GetReturnValue().Set(args.This());
10212}
10213
10214
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010215// Test that a call handler can be set for objects which will allow
10216// non-function objects created through the API to be called as
10217// functions.
10218THREADED_TEST(CallAsFunction) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010219 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000010220 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010221
lrn@chromium.org1c092762011-05-09 09:42:16 +000010222 { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
10223 Local<ObjectTemplate> instance_template = t->InstanceTemplate();
10224 instance_template->SetCallAsFunctionHandler(call_as_function);
10225 Local<v8::Object> instance = t->GetFunction()->NewInstance();
10226 context->Global()->Set(v8_str("obj"), instance);
10227 v8::TryCatch try_catch;
10228 Local<Value> value;
10229 CHECK(!try_catch.HasCaught());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010230
lrn@chromium.org1c092762011-05-09 09:42:16 +000010231 value = CompileRun("obj(42)");
10232 CHECK(!try_catch.HasCaught());
10233 CHECK_EQ(42, value->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010234
lrn@chromium.org1c092762011-05-09 09:42:16 +000010235 value = CompileRun("(function(o){return o(49)})(obj)");
10236 CHECK(!try_catch.HasCaught());
10237 CHECK_EQ(49, value->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010238
lrn@chromium.org1c092762011-05-09 09:42:16 +000010239 // test special case of call as function
10240 value = CompileRun("[obj]['0'](45)");
10241 CHECK(!try_catch.HasCaught());
10242 CHECK_EQ(45, value->Int32Value());
ager@chromium.org9258b6b2008-09-11 09:11:10 +000010243
lrn@chromium.org1c092762011-05-09 09:42:16 +000010244 value = CompileRun("obj.call = Function.prototype.call;"
10245 "obj.call(null, 87)");
10246 CHECK(!try_catch.HasCaught());
10247 CHECK_EQ(87, value->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010248
lrn@chromium.org1c092762011-05-09 09:42:16 +000010249 // Regression tests for bug #1116356: Calling call through call/apply
10250 // must work for non-function receivers.
10251 const char* apply_99 = "Function.prototype.call.apply(obj, [this, 99])";
10252 value = CompileRun(apply_99);
10253 CHECK(!try_catch.HasCaught());
10254 CHECK_EQ(99, value->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010255
lrn@chromium.org1c092762011-05-09 09:42:16 +000010256 const char* call_17 = "Function.prototype.call.call(obj, this, 17)";
10257 value = CompileRun(call_17);
10258 CHECK(!try_catch.HasCaught());
10259 CHECK_EQ(17, value->Int32Value());
ager@chromium.org9085a012009-05-11 19:22:57 +000010260
lrn@chromium.org1c092762011-05-09 09:42:16 +000010261 // Check that the call-as-function handler can be called through
10262 // new.
10263 value = CompileRun("new obj(43)");
10264 CHECK(!try_catch.HasCaught());
10265 CHECK_EQ(-43, value->Int32Value());
10266
10267 // Check that the call-as-function handler can be called through
10268 // the API.
10269 v8::Handle<Value> args[] = { v8_num(28) };
10270 value = instance->CallAsFunction(instance, 1, args);
10271 CHECK(!try_catch.HasCaught());
10272 CHECK_EQ(28, value->Int32Value());
10273 }
10274
10275 { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000010276 Local<ObjectTemplate> instance_template(t->InstanceTemplate());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000010277 USE(instance_template);
lrn@chromium.org1c092762011-05-09 09:42:16 +000010278 Local<v8::Object> instance = t->GetFunction()->NewInstance();
10279 context->Global()->Set(v8_str("obj2"), instance);
10280 v8::TryCatch try_catch;
10281 Local<Value> value;
10282 CHECK(!try_catch.HasCaught());
10283
10284 // Call an object without call-as-function handler through the JS
10285 value = CompileRun("obj2(28)");
10286 CHECK(value.IsEmpty());
10287 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000010288 String::Utf8Value exception_value1(try_catch.Exception());
lrn@chromium.org1c092762011-05-09 09:42:16 +000010289 CHECK_EQ("TypeError: Property 'obj2' of object #<Object> is not a function",
10290 *exception_value1);
10291 try_catch.Reset();
10292
10293 // Call an object without call-as-function handler through the API
10294 value = CompileRun("obj2(28)");
10295 v8::Handle<Value> args[] = { v8_num(28) };
10296 value = instance->CallAsFunction(instance, 1, args);
10297 CHECK(value.IsEmpty());
10298 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000010299 String::Utf8Value exception_value2(try_catch.Exception());
lrn@chromium.org1c092762011-05-09 09:42:16 +000010300 CHECK_EQ("TypeError: [object Object] is not a function", *exception_value2);
10301 try_catch.Reset();
10302 }
10303
10304 { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
10305 Local<ObjectTemplate> instance_template = t->InstanceTemplate();
10306 instance_template->SetCallAsFunctionHandler(ThrowValue);
10307 Local<v8::Object> instance = t->GetFunction()->NewInstance();
10308 context->Global()->Set(v8_str("obj3"), instance);
10309 v8::TryCatch try_catch;
10310 Local<Value> value;
10311 CHECK(!try_catch.HasCaught());
10312
10313 // Catch the exception which is thrown by call-as-function handler
10314 value = CompileRun("obj3(22)");
10315 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000010316 String::Utf8Value exception_value1(try_catch.Exception());
lrn@chromium.org1c092762011-05-09 09:42:16 +000010317 CHECK_EQ("22", *exception_value1);
10318 try_catch.Reset();
10319
10320 v8::Handle<Value> args[] = { v8_num(23) };
10321 value = instance->CallAsFunction(instance, 1, args);
10322 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000010323 String::Utf8Value exception_value2(try_catch.Exception());
lrn@chromium.org1c092762011-05-09 09:42:16 +000010324 CHECK_EQ("23", *exception_value2);
10325 try_catch.Reset();
10326 }
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +000010327
10328 { v8::Isolate* isolate = context->GetIsolate();
10329 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
10330 Local<ObjectTemplate> instance_template = t->InstanceTemplate();
10331 instance_template->SetCallAsFunctionHandler(ReturnThis);
10332 Local<v8::Object> instance = t->GetFunction()->NewInstance();
10333
10334 Local<v8::Value> a1 =
10335 instance->CallAsFunction(v8::Undefined(isolate), 0, NULL);
10336 CHECK(a1->StrictEquals(instance));
10337 Local<v8::Value> a2 =
10338 instance->CallAsFunction(v8::Null(isolate), 0, NULL);
10339 CHECK(a2->StrictEquals(instance));
10340 Local<v8::Value> a3 =
10341 instance->CallAsFunction(v8_num(42), 0, NULL);
10342 CHECK(a3->StrictEquals(instance));
10343 Local<v8::Value> a4 =
10344 instance->CallAsFunction(v8_str("hello"), 0, NULL);
10345 CHECK(a4->StrictEquals(instance));
10346 Local<v8::Value> a5 =
10347 instance->CallAsFunction(v8::True(isolate), 0, NULL);
10348 CHECK(a5->StrictEquals(instance));
10349 }
10350
10351 { v8::Isolate* isolate = context->GetIsolate();
10352 CompileRun(
10353 "function ReturnThisSloppy() {"
10354 " return this;"
10355 "}"
10356 "function ReturnThisStrict() {"
10357 " 'use strict';"
10358 " return this;"
10359 "}");
10360 Local<Function> ReturnThisSloppy =
10361 Local<Function>::Cast(
10362 context->Global()->Get(v8_str("ReturnThisSloppy")));
10363 Local<Function> ReturnThisStrict =
10364 Local<Function>::Cast(
10365 context->Global()->Get(v8_str("ReturnThisStrict")));
10366
10367 Local<v8::Value> a1 =
10368 ReturnThisSloppy->CallAsFunction(v8::Undefined(isolate), 0, NULL);
10369 CHECK(a1->StrictEquals(context->Global()));
10370 Local<v8::Value> a2 =
10371 ReturnThisSloppy->CallAsFunction(v8::Null(isolate), 0, NULL);
10372 CHECK(a2->StrictEquals(context->Global()));
10373 Local<v8::Value> a3 =
10374 ReturnThisSloppy->CallAsFunction(v8_num(42), 0, NULL);
10375 CHECK(a3->IsNumberObject());
10376 CHECK_EQ(42.0, a3.As<v8::NumberObject>()->ValueOf());
10377 Local<v8::Value> a4 =
10378 ReturnThisSloppy->CallAsFunction(v8_str("hello"), 0, NULL);
10379 CHECK(a4->IsStringObject());
10380 CHECK(a4.As<v8::StringObject>()->ValueOf()->StrictEquals(v8_str("hello")));
10381 Local<v8::Value> a5 =
10382 ReturnThisSloppy->CallAsFunction(v8::True(isolate), 0, NULL);
10383 CHECK(a5->IsBooleanObject());
10384 CHECK(a5.As<v8::BooleanObject>()->ValueOf());
10385
10386 Local<v8::Value> a6 =
10387 ReturnThisStrict->CallAsFunction(v8::Undefined(isolate), 0, NULL);
10388 CHECK(a6->IsUndefined());
10389 Local<v8::Value> a7 =
10390 ReturnThisStrict->CallAsFunction(v8::Null(isolate), 0, NULL);
10391 CHECK(a7->IsNull());
10392 Local<v8::Value> a8 =
10393 ReturnThisStrict->CallAsFunction(v8_num(42), 0, NULL);
10394 CHECK(a8->StrictEquals(v8_num(42)));
10395 Local<v8::Value> a9 =
10396 ReturnThisStrict->CallAsFunction(v8_str("hello"), 0, NULL);
10397 CHECK(a9->StrictEquals(v8_str("hello")));
10398 Local<v8::Value> a10 =
10399 ReturnThisStrict->CallAsFunction(v8::True(isolate), 0, NULL);
10400 CHECK(a10->StrictEquals(v8::True(isolate)));
10401 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010402}
10403
10404
karlklose@chromium.org83a47282011-05-11 11:54:09 +000010405// Check whether a non-function object is callable.
10406THREADED_TEST(CallableObject) {
karlklose@chromium.org83a47282011-05-11 11:54:09 +000010407 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000010408 v8::HandleScope scope(context->GetIsolate());
karlklose@chromium.org83a47282011-05-11 11:54:09 +000010409
10410 { Local<ObjectTemplate> instance_template = ObjectTemplate::New();
10411 instance_template->SetCallAsFunctionHandler(call_as_function);
10412 Local<Object> instance = instance_template->NewInstance();
10413 v8::TryCatch try_catch;
10414
10415 CHECK(instance->IsCallable());
10416 CHECK(!try_catch.HasCaught());
10417 }
10418
10419 { Local<ObjectTemplate> instance_template = ObjectTemplate::New();
10420 Local<Object> instance = instance_template->NewInstance();
10421 v8::TryCatch try_catch;
10422
10423 CHECK(!instance->IsCallable());
10424 CHECK(!try_catch.HasCaught());
10425 }
10426
10427 { Local<FunctionTemplate> function_template =
10428 FunctionTemplate::New(call_as_function);
10429 Local<Function> function = function_template->GetFunction();
10430 Local<Object> instance = function;
10431 v8::TryCatch try_catch;
10432
10433 CHECK(instance->IsCallable());
10434 CHECK(!try_catch.HasCaught());
10435 }
10436
10437 { Local<FunctionTemplate> function_template = FunctionTemplate::New();
10438 Local<Function> function = function_template->GetFunction();
10439 Local<Object> instance = function;
10440 v8::TryCatch try_catch;
10441
10442 CHECK(instance->IsCallable());
10443 CHECK(!try_catch.HasCaught());
10444 }
10445}
10446
10447
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010448static int CountHandles() {
10449 return v8::HandleScope::NumberOfHandles();
10450}
10451
10452
10453static int Recurse(int depth, int iterations) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000010454 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010455 if (depth == 0) return CountHandles();
10456 for (int i = 0; i < iterations; i++) {
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000010457 Local<v8::Number> n(v8::Integer::New(42));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010458 }
10459 return Recurse(depth - 1, iterations);
10460}
10461
10462
10463THREADED_TEST(HandleIteration) {
10464 static const int kIterations = 500;
10465 static const int kNesting = 200;
10466 CHECK_EQ(0, CountHandles());
10467 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000010468 v8::HandleScope scope1(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010469 CHECK_EQ(0, CountHandles());
10470 for (int i = 0; i < kIterations; i++) {
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000010471 Local<v8::Number> n(v8::Integer::New(42));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010472 CHECK_EQ(i + 1, CountHandles());
10473 }
10474
10475 CHECK_EQ(kIterations, CountHandles());
10476 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000010477 v8::HandleScope scope2(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010478 for (int j = 0; j < kIterations; j++) {
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000010479 Local<v8::Number> n(v8::Integer::New(42));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010480 CHECK_EQ(j + 1 + kIterations, CountHandles());
10481 }
10482 }
10483 CHECK_EQ(kIterations, CountHandles());
10484 }
10485 CHECK_EQ(0, CountHandles());
10486 CHECK_EQ(kNesting * kIterations, Recurse(kNesting, kIterations));
10487}
10488
10489
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010490static void InterceptorHasOwnPropertyGetter(
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010491 Local<String> name,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010492 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010493 ApiTestFuzzer::Fuzz();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010494}
10495
10496
10497THREADED_TEST(InterceptorHasOwnProperty) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010498 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000010499 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010500 Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
10501 Local<v8::ObjectTemplate> instance_templ = fun_templ->InstanceTemplate();
10502 instance_templ->SetNamedPropertyHandler(InterceptorHasOwnPropertyGetter);
10503 Local<Function> function = fun_templ->GetFunction();
10504 context->Global()->Set(v8_str("constructor"), function);
10505 v8::Handle<Value> value = CompileRun(
10506 "var o = new constructor();"
10507 "o.hasOwnProperty('ostehaps');");
10508 CHECK_EQ(false, value->BooleanValue());
10509 value = CompileRun(
10510 "o.ostehaps = 42;"
10511 "o.hasOwnProperty('ostehaps');");
10512 CHECK_EQ(true, value->BooleanValue());
10513 value = CompileRun(
10514 "var p = new constructor();"
10515 "p.hasOwnProperty('ostehaps');");
10516 CHECK_EQ(false, value->BooleanValue());
10517}
10518
10519
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010520static void InterceptorHasOwnPropertyGetterGC(
ager@chromium.org9085a012009-05-11 19:22:57 +000010521 Local<String> name,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010522 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.org9085a012009-05-11 19:22:57 +000010523 ApiTestFuzzer::Fuzz();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000010524 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org9085a012009-05-11 19:22:57 +000010525}
10526
10527
10528THREADED_TEST(InterceptorHasOwnPropertyCausingGC) {
ager@chromium.org9085a012009-05-11 19:22:57 +000010529 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000010530 v8::HandleScope scope(context->GetIsolate());
ager@chromium.org9085a012009-05-11 19:22:57 +000010531 Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
10532 Local<v8::ObjectTemplate> instance_templ = fun_templ->InstanceTemplate();
10533 instance_templ->SetNamedPropertyHandler(InterceptorHasOwnPropertyGetterGC);
10534 Local<Function> function = fun_templ->GetFunction();
10535 context->Global()->Set(v8_str("constructor"), function);
10536 // Let's first make some stuff so we can be sure to get a good GC.
10537 CompileRun(
10538 "function makestr(size) {"
10539 " switch (size) {"
10540 " case 1: return 'f';"
10541 " case 2: return 'fo';"
10542 " case 3: return 'foo';"
10543 " }"
10544 " return makestr(size >> 1) + makestr((size + 1) >> 1);"
10545 "}"
10546 "var x = makestr(12345);"
10547 "x = makestr(31415);"
10548 "x = makestr(23456);");
10549 v8::Handle<Value> value = CompileRun(
10550 "var o = new constructor();"
10551 "o.__proto__ = new String(x);"
10552 "o.hasOwnProperty('ostehaps');");
10553 CHECK_EQ(false, value->BooleanValue());
10554}
10555
10556
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010557typedef void (*NamedPropertyGetter)(
10558 Local<String> property,
10559 const v8::PropertyCallbackInfo<v8::Value>& info);
ager@chromium.orge2902be2009-06-08 12:21:35 +000010560
10561
10562static void CheckInterceptorLoadIC(NamedPropertyGetter getter,
10563 const char* source,
10564 int expected) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000010565 v8::HandleScope scope(CcTest::isolate());
ager@chromium.orge2902be2009-06-08 12:21:35 +000010566 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
vegorov@chromium.org21b5e952010-11-23 10:24:40 +000010567 templ->SetNamedPropertyHandler(getter, 0, 0, 0, 0, v8_str("data"));
ager@chromium.orge2902be2009-06-08 12:21:35 +000010568 LocalContext context;
10569 context->Global()->Set(v8_str("o"), templ->NewInstance());
10570 v8::Handle<Value> value = CompileRun(source);
10571 CHECK_EQ(expected, value->Int32Value());
10572}
10573
10574
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010575static void InterceptorLoadICGetter(
10576 Local<String> name,
10577 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010578 ApiTestFuzzer::Fuzz();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000010579 v8::Isolate* isolate = CcTest::isolate();
jkummerow@chromium.org28faa982012-04-13 09:58:30 +000010580 CHECK_EQ(isolate, info.GetIsolate());
vegorov@chromium.org21b5e952010-11-23 10:24:40 +000010581 CHECK_EQ(v8_str("data"), info.Data());
10582 CHECK_EQ(v8_str("x"), name);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010583 info.GetReturnValue().Set(v8::Integer::New(42));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010584}
10585
10586
10587// This test should hit the load IC for the interceptor case.
10588THREADED_TEST(InterceptorLoadIC) {
ager@chromium.orge2902be2009-06-08 12:21:35 +000010589 CheckInterceptorLoadIC(InterceptorLoadICGetter,
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010590 "var result = 0;"
10591 "for (var i = 0; i < 1000; i++) {"
10592 " result = o.x;"
ager@chromium.orge2902be2009-06-08 12:21:35 +000010593 "}",
10594 42);
10595}
10596
10597
10598// Below go several tests which verify that JITing for various
10599// configurations of interceptor and explicit fields works fine
10600// (those cases are special cased to get better performance).
10601
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010602static void InterceptorLoadXICGetter(
10603 Local<String> name,
10604 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.orge2902be2009-06-08 12:21:35 +000010605 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010606 info.GetReturnValue().Set(
10607 v8_str("x")->Equals(name) ?
10608 v8::Handle<v8::Value>(v8::Integer::New(42)) :
10609 v8::Handle<v8::Value>());
ager@chromium.orge2902be2009-06-08 12:21:35 +000010610}
10611
10612
10613THREADED_TEST(InterceptorLoadICWithFieldOnHolder) {
10614 CheckInterceptorLoadIC(InterceptorLoadXICGetter,
10615 "var result = 0;"
10616 "o.y = 239;"
10617 "for (var i = 0; i < 1000; i++) {"
10618 " result = o.y;"
10619 "}",
10620 239);
10621}
10622
10623
10624THREADED_TEST(InterceptorLoadICWithSubstitutedProto) {
10625 CheckInterceptorLoadIC(InterceptorLoadXICGetter,
10626 "var result = 0;"
10627 "o.__proto__ = { 'y': 239 };"
10628 "for (var i = 0; i < 1000; i++) {"
10629 " result = o.y + o.x;"
10630 "}",
10631 239 + 42);
10632}
10633
10634
10635THREADED_TEST(InterceptorLoadICWithPropertyOnProto) {
10636 CheckInterceptorLoadIC(InterceptorLoadXICGetter,
10637 "var result = 0;"
10638 "o.__proto__.y = 239;"
10639 "for (var i = 0; i < 1000; i++) {"
10640 " result = o.y + o.x;"
10641 "}",
10642 239 + 42);
10643}
10644
10645
10646THREADED_TEST(InterceptorLoadICUndefined) {
10647 CheckInterceptorLoadIC(InterceptorLoadXICGetter,
10648 "var result = 0;"
10649 "for (var i = 0; i < 1000; i++) {"
10650 " result = (o.y == undefined) ? 239 : 42;"
10651 "}",
10652 239);
10653}
10654
10655
10656THREADED_TEST(InterceptorLoadICWithOverride) {
10657 CheckInterceptorLoadIC(InterceptorLoadXICGetter,
10658 "fst = new Object(); fst.__proto__ = o;"
10659 "snd = new Object(); snd.__proto__ = fst;"
10660 "var result1 = 0;"
10661 "for (var i = 0; i < 1000; i++) {"
10662 " result1 = snd.x;"
10663 "}"
10664 "fst.x = 239;"
10665 "var result = 0;"
10666 "for (var i = 0; i < 1000; i++) {"
10667 " result = snd.x;"
10668 "}"
10669 "result + result1",
10670 239 + 42);
10671}
10672
10673
kasperl@chromium.orge959c182009-07-27 08:59:04 +000010674// Test the case when we stored field into
10675// a stub, but interceptor produced value on its own.
10676THREADED_TEST(InterceptorLoadICFieldNotNeeded) {
10677 CheckInterceptorLoadIC(InterceptorLoadXICGetter,
10678 "proto = new Object();"
10679 "o.__proto__ = proto;"
10680 "proto.x = 239;"
10681 "for (var i = 0; i < 1000; i++) {"
10682 " o.x;"
10683 // Now it should be ICed and keep a reference to x defined on proto
10684 "}"
10685 "var result = 0;"
10686 "for (var i = 0; i < 1000; i++) {"
10687 " result += o.x;"
10688 "}"
10689 "result;",
10690 42 * 1000);
10691}
10692
10693
10694// Test the case when we stored field into
10695// a stub, but it got invalidated later on.
10696THREADED_TEST(InterceptorLoadICInvalidatedField) {
10697 CheckInterceptorLoadIC(InterceptorLoadXICGetter,
10698 "proto1 = new Object();"
10699 "proto2 = new Object();"
10700 "o.__proto__ = proto1;"
10701 "proto1.__proto__ = proto2;"
10702 "proto2.y = 239;"
10703 "for (var i = 0; i < 1000; i++) {"
10704 " o.y;"
10705 // Now it should be ICed and keep a reference to y defined on proto2
10706 "}"
10707 "proto1.y = 42;"
10708 "var result = 0;"
10709 "for (var i = 0; i < 1000; i++) {"
10710 " result += o.y;"
10711 "}"
10712 "result;",
10713 42 * 1000);
10714}
10715
10716
ager@chromium.orgb26c50a2010-03-26 09:27:16 +000010717static int interceptor_load_not_handled_calls = 0;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010718static void InterceptorLoadNotHandled(
10719 Local<String> name,
10720 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.orgb26c50a2010-03-26 09:27:16 +000010721 ++interceptor_load_not_handled_calls;
ager@chromium.orgb26c50a2010-03-26 09:27:16 +000010722}
10723
10724
10725// Test how post-interceptor lookups are done in the non-cacheable
10726// case: the interceptor should not be invoked during this lookup.
10727THREADED_TEST(InterceptorLoadICPostInterceptor) {
10728 interceptor_load_not_handled_calls = 0;
10729 CheckInterceptorLoadIC(InterceptorLoadNotHandled,
10730 "receiver = new Object();"
10731 "receiver.__proto__ = o;"
10732 "proto = new Object();"
10733 "/* Make proto a slow-case object. */"
10734 "for (var i = 0; i < 1000; i++) {"
10735 " proto[\"xxxxxxxx\" + i] = [];"
10736 "}"
10737 "proto.x = 17;"
10738 "o.__proto__ = proto;"
10739 "var result = 0;"
10740 "for (var i = 0; i < 1000; i++) {"
10741 " result += receiver.x;"
10742 "}"
10743 "result;",
10744 17 * 1000);
10745 CHECK_EQ(1000, interceptor_load_not_handled_calls);
10746}
10747
10748
kasperl@chromium.orge959c182009-07-27 08:59:04 +000010749// Test the case when we stored field into
10750// a stub, but it got invalidated later on due to override on
10751// global object which is between interceptor and fields' holders.
10752THREADED_TEST(InterceptorLoadICInvalidatedFieldViaGlobal) {
10753 CheckInterceptorLoadIC(InterceptorLoadXICGetter,
10754 "o.__proto__ = this;" // set a global to be a proto of o.
10755 "this.__proto__.y = 239;"
10756 "for (var i = 0; i < 10; i++) {"
10757 " if (o.y != 239) throw 'oops: ' + o.y;"
10758 // Now it should be ICed and keep a reference to y defined on field_holder.
10759 "}"
10760 "this.y = 42;" // Assign on a global.
10761 "var result = 0;"
10762 "for (var i = 0; i < 10; i++) {"
10763 " result += o.y;"
10764 "}"
10765 "result;",
10766 42 * 10);
10767}
10768
10769
kasperl@chromium.orge959c182009-07-27 08:59:04 +000010770static void SetOnThis(Local<String> name,
10771 Local<Value> value,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010772 const v8::PropertyCallbackInfo<void>& info) {
kasperl@chromium.orge959c182009-07-27 08:59:04 +000010773 info.This()->ForceSet(name, value);
10774}
10775
10776
10777THREADED_TEST(InterceptorLoadICWithCallbackOnHolder) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000010778 v8::HandleScope scope(CcTest::isolate());
kasperl@chromium.orge959c182009-07-27 08:59:04 +000010779 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
10780 templ->SetNamedPropertyHandler(InterceptorLoadXICGetter);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010781 templ->SetAccessor(v8_str("y"), Return239Callback);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000010782 LocalContext context;
10783 context->Global()->Set(v8_str("o"), templ->NewInstance());
ricow@chromium.org30ce4112010-05-31 10:38:25 +000010784
10785 // Check the case when receiver and interceptor's holder
10786 // are the same objects.
kasperl@chromium.orge959c182009-07-27 08:59:04 +000010787 v8::Handle<Value> value = CompileRun(
10788 "var result = 0;"
10789 "for (var i = 0; i < 7; i++) {"
10790 " result = o.y;"
10791 "}");
10792 CHECK_EQ(239, value->Int32Value());
ricow@chromium.org30ce4112010-05-31 10:38:25 +000010793
10794 // Check the case when interceptor's holder is in proto chain
10795 // of receiver.
10796 value = CompileRun(
10797 "r = { __proto__: o };"
10798 "var result = 0;"
10799 "for (var i = 0; i < 7; i++) {"
10800 " result = r.y;"
10801 "}");
10802 CHECK_EQ(239, value->Int32Value());
kasperl@chromium.orge959c182009-07-27 08:59:04 +000010803}
10804
10805
10806THREADED_TEST(InterceptorLoadICWithCallbackOnProto) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000010807 v8::HandleScope scope(CcTest::isolate());
kasperl@chromium.orge959c182009-07-27 08:59:04 +000010808 v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
10809 templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
10810 v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010811 templ_p->SetAccessor(v8_str("y"), Return239Callback);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000010812
10813 LocalContext context;
10814 context->Global()->Set(v8_str("o"), templ_o->NewInstance());
10815 context->Global()->Set(v8_str("p"), templ_p->NewInstance());
10816
ricow@chromium.org30ce4112010-05-31 10:38:25 +000010817 // Check the case when receiver and interceptor's holder
10818 // are the same objects.
kasperl@chromium.orge959c182009-07-27 08:59:04 +000010819 v8::Handle<Value> value = CompileRun(
10820 "o.__proto__ = p;"
10821 "var result = 0;"
10822 "for (var i = 0; i < 7; i++) {"
10823 " result = o.x + o.y;"
10824 "}");
10825 CHECK_EQ(239 + 42, value->Int32Value());
ricow@chromium.org30ce4112010-05-31 10:38:25 +000010826
10827 // Check the case when interceptor's holder is in proto chain
10828 // of receiver.
10829 value = CompileRun(
10830 "r = { __proto__: o };"
10831 "var result = 0;"
10832 "for (var i = 0; i < 7; i++) {"
10833 " result = r.x + r.y;"
10834 "}");
10835 CHECK_EQ(239 + 42, value->Int32Value());
kasperl@chromium.orge959c182009-07-27 08:59:04 +000010836}
10837
10838
10839THREADED_TEST(InterceptorLoadICForCallbackWithOverride) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000010840 v8::HandleScope scope(CcTest::isolate());
kasperl@chromium.orge959c182009-07-27 08:59:04 +000010841 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
10842 templ->SetNamedPropertyHandler(InterceptorLoadXICGetter);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010843 templ->SetAccessor(v8_str("y"), Return239Callback);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000010844
10845 LocalContext context;
10846 context->Global()->Set(v8_str("o"), templ->NewInstance());
10847
10848 v8::Handle<Value> value = CompileRun(
10849 "fst = new Object(); fst.__proto__ = o;"
10850 "snd = new Object(); snd.__proto__ = fst;"
10851 "var result1 = 0;"
10852 "for (var i = 0; i < 7; i++) {"
10853 " result1 = snd.x;"
10854 "}"
10855 "fst.x = 239;"
10856 "var result = 0;"
10857 "for (var i = 0; i < 7; i++) {"
10858 " result = snd.x;"
10859 "}"
10860 "result + result1");
10861 CHECK_EQ(239 + 42, value->Int32Value());
10862}
10863
10864
10865// Test the case when we stored callback into
10866// a stub, but interceptor produced value on its own.
10867THREADED_TEST(InterceptorLoadICCallbackNotNeeded) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000010868 v8::HandleScope scope(CcTest::isolate());
kasperl@chromium.orge959c182009-07-27 08:59:04 +000010869 v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
10870 templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
10871 v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010872 templ_p->SetAccessor(v8_str("y"), Return239Callback);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000010873
10874 LocalContext context;
10875 context->Global()->Set(v8_str("o"), templ_o->NewInstance());
10876 context->Global()->Set(v8_str("p"), templ_p->NewInstance());
10877
10878 v8::Handle<Value> value = CompileRun(
10879 "o.__proto__ = p;"
10880 "for (var i = 0; i < 7; i++) {"
10881 " o.x;"
10882 // Now it should be ICed and keep a reference to x defined on p
10883 "}"
10884 "var result = 0;"
10885 "for (var i = 0; i < 7; i++) {"
10886 " result += o.x;"
10887 "}"
10888 "result");
10889 CHECK_EQ(42 * 7, value->Int32Value());
10890}
10891
10892
10893// Test the case when we stored callback into
10894// a stub, but it got invalidated later on.
10895THREADED_TEST(InterceptorLoadICInvalidatedCallback) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000010896 v8::HandleScope scope(CcTest::isolate());
kasperl@chromium.orge959c182009-07-27 08:59:04 +000010897 v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
10898 templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
10899 v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010900 templ_p->SetAccessor(v8_str("y"), Return239Callback, SetOnThis);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000010901
10902 LocalContext context;
10903 context->Global()->Set(v8_str("o"), templ_o->NewInstance());
10904 context->Global()->Set(v8_str("p"), templ_p->NewInstance());
10905
10906 v8::Handle<Value> value = CompileRun(
10907 "inbetween = new Object();"
10908 "o.__proto__ = inbetween;"
10909 "inbetween.__proto__ = p;"
10910 "for (var i = 0; i < 10; i++) {"
10911 " o.y;"
10912 // Now it should be ICed and keep a reference to y defined on p
10913 "}"
10914 "inbetween.y = 42;"
10915 "var result = 0;"
10916 "for (var i = 0; i < 10; i++) {"
10917 " result += o.y;"
10918 "}"
10919 "result");
10920 CHECK_EQ(42 * 10, value->Int32Value());
10921}
10922
10923
10924// Test the case when we stored callback into
10925// a stub, but it got invalidated later on due to override on
10926// global object which is between interceptor and callbacks' holders.
10927THREADED_TEST(InterceptorLoadICInvalidatedCallbackViaGlobal) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000010928 v8::HandleScope scope(CcTest::isolate());
kasperl@chromium.orge959c182009-07-27 08:59:04 +000010929 v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
10930 templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
10931 v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010932 templ_p->SetAccessor(v8_str("y"), Return239Callback, SetOnThis);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000010933
10934 LocalContext context;
10935 context->Global()->Set(v8_str("o"), templ_o->NewInstance());
10936 context->Global()->Set(v8_str("p"), templ_p->NewInstance());
10937
10938 v8::Handle<Value> value = CompileRun(
10939 "o.__proto__ = this;"
10940 "this.__proto__ = p;"
10941 "for (var i = 0; i < 10; i++) {"
10942 " if (o.y != 239) throw 'oops: ' + o.y;"
10943 // Now it should be ICed and keep a reference to y defined on p
10944 "}"
10945 "this.y = 42;"
10946 "var result = 0;"
10947 "for (var i = 0; i < 10; i++) {"
10948 " result += o.y;"
10949 "}"
10950 "result");
10951 CHECK_EQ(42 * 10, value->Int32Value());
10952}
10953
10954
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010955static void InterceptorLoadICGetter0(
10956 Local<String> name,
10957 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.orge2902be2009-06-08 12:21:35 +000010958 ApiTestFuzzer::Fuzz();
10959 CHECK(v8_str("x")->Equals(name));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010960 info.GetReturnValue().Set(v8::Integer::New(0));
ager@chromium.orge2902be2009-06-08 12:21:35 +000010961}
10962
10963
10964THREADED_TEST(InterceptorReturningZero) {
10965 CheckInterceptorLoadIC(InterceptorLoadICGetter0,
10966 "o.x == undefined ? 1 : 0",
10967 0);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010968}
10969
10970
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010971static void InterceptorStoreICSetter(
10972 Local<String> key,
10973 Local<Value> value,
10974 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010975 CHECK(v8_str("x")->Equals(key));
10976 CHECK_EQ(42, value->Int32Value());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010977 info.GetReturnValue().Set(value);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010978}
10979
10980
10981// This test should hit the store IC for the interceptor case.
10982THREADED_TEST(InterceptorStoreIC) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000010983 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010984 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
10985 templ->SetNamedPropertyHandler(InterceptorLoadICGetter,
vegorov@chromium.org21b5e952010-11-23 10:24:40 +000010986 InterceptorStoreICSetter,
10987 0, 0, 0, v8_str("data"));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010988 LocalContext context;
10989 context->Global()->Set(v8_str("o"), templ->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000010990 CompileRun(
10991 "for (var i = 0; i < 1000; i++) {"
10992 " o.x = 42;"
10993 "}");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010994}
10995
10996
ager@chromium.orgeadaf222009-06-16 09:43:10 +000010997THREADED_TEST(InterceptorStoreICWithNoSetter) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000010998 v8::HandleScope scope(CcTest::isolate());
ager@chromium.orgeadaf222009-06-16 09:43:10 +000010999 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
11000 templ->SetNamedPropertyHandler(InterceptorLoadXICGetter);
11001 LocalContext context;
11002 context->Global()->Set(v8_str("o"), templ->NewInstance());
11003 v8::Handle<Value> value = CompileRun(
11004 "for (var i = 0; i < 1000; i++) {"
11005 " o.y = 239;"
11006 "}"
11007 "42 + o.y");
11008 CHECK_EQ(239 + 42, value->Int32Value());
11009}
11010
11011
11012
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011013
11014v8::Handle<Value> call_ic_function;
11015v8::Handle<Value> call_ic_function2;
11016v8::Handle<Value> call_ic_function3;
11017
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011018static void InterceptorCallICGetter(
11019 Local<String> name,
11020 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011021 ApiTestFuzzer::Fuzz();
11022 CHECK(v8_str("x")->Equals(name));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011023 info.GetReturnValue().Set(call_ic_function);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011024}
11025
11026
11027// This test should hit the call IC for the interceptor case.
11028THREADED_TEST(InterceptorCallIC) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000011029 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011030 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
11031 templ->SetNamedPropertyHandler(InterceptorCallICGetter);
11032 LocalContext context;
11033 context->Global()->Set(v8_str("o"), templ->NewInstance());
11034 call_ic_function =
11035 v8_compile("function f(x) { return x + 1; }; f")->Run();
11036 v8::Handle<Value> value = CompileRun(
11037 "var result = 0;"
11038 "for (var i = 0; i < 1000; i++) {"
11039 " result = o.x(41);"
11040 "}");
11041 CHECK_EQ(42, value->Int32Value());
11042}
11043
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011044
11045// This test checks that if interceptor doesn't provide
11046// a value, we can fetch regular value.
11047THREADED_TEST(InterceptorCallICSeesOthers) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000011048 v8::HandleScope scope(CcTest::isolate());
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011049 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
11050 templ->SetNamedPropertyHandler(NoBlockGetterX);
11051 LocalContext context;
11052 context->Global()->Set(v8_str("o"), templ->NewInstance());
11053 v8::Handle<Value> value = CompileRun(
11054 "o.x = function f(x) { return x + 1; };"
11055 "var result = 0;"
11056 "for (var i = 0; i < 7; i++) {"
11057 " result = o.x(41);"
11058 "}");
11059 CHECK_EQ(42, value->Int32Value());
11060}
11061
11062
11063static v8::Handle<Value> call_ic_function4;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011064static void InterceptorCallICGetter4(
11065 Local<String> name,
11066 const v8::PropertyCallbackInfo<v8::Value>& info) {
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011067 ApiTestFuzzer::Fuzz();
11068 CHECK(v8_str("x")->Equals(name));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011069 info.GetReturnValue().Set(call_ic_function4);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011070}
11071
11072
11073// This test checks that if interceptor provides a function,
11074// even if we cached shadowed variant, interceptor's function
11075// is invoked
11076THREADED_TEST(InterceptorCallICCacheableNotNeeded) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000011077 v8::HandleScope scope(CcTest::isolate());
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011078 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
11079 templ->SetNamedPropertyHandler(InterceptorCallICGetter4);
11080 LocalContext context;
11081 context->Global()->Set(v8_str("o"), templ->NewInstance());
11082 call_ic_function4 =
11083 v8_compile("function f(x) { return x - 1; }; f")->Run();
11084 v8::Handle<Value> value = CompileRun(
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +000011085 "Object.getPrototypeOf(o).x = function(x) { return x + 1; };"
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011086 "var result = 0;"
11087 "for (var i = 0; i < 1000; i++) {"
11088 " result = o.x(42);"
11089 "}");
11090 CHECK_EQ(41, value->Int32Value());
11091}
11092
11093
11094// Test the case when we stored cacheable lookup into
11095// a stub, but it got invalidated later on
11096THREADED_TEST(InterceptorCallICInvalidatedCacheable) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000011097 v8::HandleScope scope(CcTest::isolate());
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011098 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
11099 templ->SetNamedPropertyHandler(NoBlockGetterX);
11100 LocalContext context;
11101 context->Global()->Set(v8_str("o"), templ->NewInstance());
11102 v8::Handle<Value> value = CompileRun(
11103 "proto1 = new Object();"
11104 "proto2 = new Object();"
11105 "o.__proto__ = proto1;"
11106 "proto1.__proto__ = proto2;"
11107 "proto2.y = function(x) { return x + 1; };"
11108 // Invoke it many times to compile a stub
11109 "for (var i = 0; i < 7; i++) {"
11110 " o.y(42);"
11111 "}"
11112 "proto1.y = function(x) { return x - 1; };"
11113 "var result = 0;"
11114 "for (var i = 0; i < 7; i++) {"
11115 " result += o.y(42);"
11116 "}");
11117 CHECK_EQ(41 * 7, value->Int32Value());
11118}
11119
11120
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011121// This test checks that if interceptor doesn't provide a function,
11122// cached constant function is used
11123THREADED_TEST(InterceptorCallICConstantFunctionUsed) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000011124 v8::HandleScope scope(CcTest::isolate());
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011125 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
11126 templ->SetNamedPropertyHandler(NoBlockGetterX);
11127 LocalContext context;
11128 context->Global()->Set(v8_str("o"), templ->NewInstance());
11129 v8::Handle<Value> value = CompileRun(
11130 "function inc(x) { return x + 1; };"
11131 "inc(1);"
11132 "o.x = inc;"
11133 "var result = 0;"
11134 "for (var i = 0; i < 1000; i++) {"
11135 " result = o.x(42);"
11136 "}");
11137 CHECK_EQ(43, value->Int32Value());
11138}
11139
11140
ulan@chromium.org2efb9002012-01-19 15:36:35 +000011141static v8::Handle<Value> call_ic_function5;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011142static void InterceptorCallICGetter5(
11143 Local<String> name,
11144 const v8::PropertyCallbackInfo<v8::Value>& info) {
ulan@chromium.org2efb9002012-01-19 15:36:35 +000011145 ApiTestFuzzer::Fuzz();
11146 if (v8_str("x")->Equals(name))
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011147 info.GetReturnValue().Set(call_ic_function5);
ulan@chromium.org2efb9002012-01-19 15:36:35 +000011148}
11149
11150
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011151// This test checks that if interceptor provides a function,
11152// even if we cached constant function, interceptor's function
11153// is invoked
11154THREADED_TEST(InterceptorCallICConstantFunctionNotNeeded) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000011155 v8::HandleScope scope(CcTest::isolate());
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011156 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
11157 templ->SetNamedPropertyHandler(InterceptorCallICGetter5);
11158 LocalContext context;
11159 context->Global()->Set(v8_str("o"), templ->NewInstance());
11160 call_ic_function5 =
11161 v8_compile("function f(x) { return x - 1; }; f")->Run();
11162 v8::Handle<Value> value = CompileRun(
11163 "function inc(x) { return x + 1; };"
11164 "inc(1);"
11165 "o.x = inc;"
11166 "var result = 0;"
11167 "for (var i = 0; i < 1000; i++) {"
11168 " result = o.x(42);"
11169 "}");
11170 CHECK_EQ(41, value->Int32Value());
11171}
11172
11173
ulan@chromium.org2efb9002012-01-19 15:36:35 +000011174static v8::Handle<Value> call_ic_function6;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011175static void InterceptorCallICGetter6(
11176 Local<String> name,
11177 const v8::PropertyCallbackInfo<v8::Value>& info) {
ulan@chromium.org2efb9002012-01-19 15:36:35 +000011178 ApiTestFuzzer::Fuzz();
11179 if (v8_str("x")->Equals(name))
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011180 info.GetReturnValue().Set(call_ic_function6);
ulan@chromium.org2efb9002012-01-19 15:36:35 +000011181}
11182
11183
11184// Same test as above, except the code is wrapped in a function
11185// to test the optimized compiler.
11186THREADED_TEST(InterceptorCallICConstantFunctionNotNeededWrapped) {
11187 i::FLAG_allow_natives_syntax = true;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000011188 v8::HandleScope scope(CcTest::isolate());
ulan@chromium.org2efb9002012-01-19 15:36:35 +000011189 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
11190 templ->SetNamedPropertyHandler(InterceptorCallICGetter6);
11191 LocalContext context;
11192 context->Global()->Set(v8_str("o"), templ->NewInstance());
11193 call_ic_function6 =
11194 v8_compile("function f(x) { return x - 1; }; f")->Run();
11195 v8::Handle<Value> value = CompileRun(
11196 "function inc(x) { return x + 1; };"
11197 "inc(1);"
11198 "o.x = inc;"
11199 "function test() {"
11200 " var result = 0;"
11201 " for (var i = 0; i < 1000; i++) {"
11202 " result = o.x(42);"
11203 " }"
11204 " return result;"
11205 "};"
11206 "test();"
11207 "test();"
11208 "test();"
11209 "%OptimizeFunctionOnNextCall(test);"
11210 "test()");
11211 CHECK_EQ(41, value->Int32Value());
11212}
11213
11214
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011215// Test the case when we stored constant function into
11216// a stub, but it got invalidated later on
11217THREADED_TEST(InterceptorCallICInvalidatedConstantFunction) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000011218 v8::HandleScope scope(CcTest::isolate());
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011219 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
11220 templ->SetNamedPropertyHandler(NoBlockGetterX);
11221 LocalContext context;
11222 context->Global()->Set(v8_str("o"), templ->NewInstance());
11223 v8::Handle<Value> value = CompileRun(
11224 "function inc(x) { return x + 1; };"
11225 "inc(1);"
11226 "proto1 = new Object();"
11227 "proto2 = new Object();"
11228 "o.__proto__ = proto1;"
11229 "proto1.__proto__ = proto2;"
11230 "proto2.y = inc;"
11231 // Invoke it many times to compile a stub
11232 "for (var i = 0; i < 7; i++) {"
11233 " o.y(42);"
11234 "}"
11235 "proto1.y = function(x) { return x - 1; };"
11236 "var result = 0;"
11237 "for (var i = 0; i < 7; i++) {"
11238 " result += o.y(42);"
11239 "}");
11240 CHECK_EQ(41 * 7, value->Int32Value());
11241}
11242
11243
11244// Test the case when we stored constant function into
11245// a stub, but it got invalidated later on due to override on
11246// global object which is between interceptor and constant function' holders.
11247THREADED_TEST(InterceptorCallICInvalidatedConstantFunctionViaGlobal) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000011248 v8::HandleScope scope(CcTest::isolate());
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011249 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
11250 templ->SetNamedPropertyHandler(NoBlockGetterX);
11251 LocalContext context;
11252 context->Global()->Set(v8_str("o"), templ->NewInstance());
11253 v8::Handle<Value> value = CompileRun(
11254 "function inc(x) { return x + 1; };"
11255 "inc(1);"
11256 "o.__proto__ = this;"
11257 "this.__proto__.y = inc;"
11258 // Invoke it many times to compile a stub
11259 "for (var i = 0; i < 7; i++) {"
11260 " if (o.y(42) != 43) throw 'oops: ' + o.y(42);"
11261 "}"
11262 "this.y = function(x) { return x - 1; };"
11263 "var result = 0;"
11264 "for (var i = 0; i < 7; i++) {"
11265 " result += o.y(42);"
11266 "}");
11267 CHECK_EQ(41 * 7, value->Int32Value());
11268}
11269
11270
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000011271// Test the case when actual function to call sits on global object.
11272THREADED_TEST(InterceptorCallICCachedFromGlobal) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000011273 v8::HandleScope scope(CcTest::isolate());
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000011274 v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
11275 templ_o->SetNamedPropertyHandler(NoBlockGetterX);
11276
11277 LocalContext context;
11278 context->Global()->Set(v8_str("o"), templ_o->NewInstance());
11279
11280 v8::Handle<Value> value = CompileRun(
11281 "try {"
11282 " o.__proto__ = this;"
11283 " for (var i = 0; i < 10; i++) {"
11284 " var v = o.parseFloat('239');"
11285 " if (v != 239) throw v;"
11286 // Now it should be ICed and keep a reference to parseFloat.
11287 " }"
11288 " var result = 0;"
11289 " for (var i = 0; i < 10; i++) {"
11290 " result += o.parseFloat('239');"
11291 " }"
11292 " result"
11293 "} catch(e) {"
11294 " e"
11295 "};");
11296 CHECK_EQ(239 * 10, value->Int32Value());
11297}
11298
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011299static void InterceptorCallICFastApi(
11300 Local<String> name,
11301 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.org5c838252010-02-19 08:53:10 +000011302 ApiTestFuzzer::Fuzz();
dslomov@chromium.orgb752d402013-06-18 11:54:54 +000011303 CheckReturnValue(info, FUNCTION_ADDR(InterceptorCallICFastApi));
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000011304 int* call_count =
11305 reinterpret_cast<int*>(v8::External::Cast(*info.Data())->Value());
ager@chromium.org5c838252010-02-19 08:53:10 +000011306 ++(*call_count);
11307 if ((*call_count) % 20 == 0) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000011308 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org5c838252010-02-19 08:53:10 +000011309 }
ager@chromium.org5c838252010-02-19 08:53:10 +000011310}
11311
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011312static void FastApiCallback_TrivialSignature(
11313 const v8::FunctionCallbackInfo<v8::Value>& args) {
ager@chromium.org5c838252010-02-19 08:53:10 +000011314 ApiTestFuzzer::Fuzz();
dslomov@chromium.orgb752d402013-06-18 11:54:54 +000011315 CheckReturnValue(args, FUNCTION_ADDR(FastApiCallback_TrivialSignature));
machenbach@chromium.org528ce022013-09-23 14:09:36 +000011316 v8::Isolate* isolate = CcTest::isolate();
jkummerow@chromium.org28faa982012-04-13 09:58:30 +000011317 CHECK_EQ(isolate, args.GetIsolate());
ager@chromium.org5c838252010-02-19 08:53:10 +000011318 CHECK_EQ(args.This(), args.Holder());
11319 CHECK(args.Data()->Equals(v8_str("method_data")));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011320 args.GetReturnValue().Set(args[0]->Int32Value() + 1);
ager@chromium.org5c838252010-02-19 08:53:10 +000011321}
11322
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011323static void FastApiCallback_SimpleSignature(
11324 const v8::FunctionCallbackInfo<v8::Value>& args) {
ager@chromium.org5c838252010-02-19 08:53:10 +000011325 ApiTestFuzzer::Fuzz();
dslomov@chromium.orgb752d402013-06-18 11:54:54 +000011326 CheckReturnValue(args, FUNCTION_ADDR(FastApiCallback_SimpleSignature));
machenbach@chromium.org528ce022013-09-23 14:09:36 +000011327 v8::Isolate* isolate = CcTest::isolate();
jkummerow@chromium.org28faa982012-04-13 09:58:30 +000011328 CHECK_EQ(isolate, args.GetIsolate());
ager@chromium.org5c838252010-02-19 08:53:10 +000011329 CHECK_EQ(args.This()->GetPrototype(), args.Holder());
11330 CHECK(args.Data()->Equals(v8_str("method_data")));
11331 // Note, we're using HasRealNamedProperty instead of Has to avoid
11332 // invoking the interceptor again.
11333 CHECK(args.Holder()->HasRealNamedProperty(v8_str("foo")));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011334 args.GetReturnValue().Set(args[0]->Int32Value() + 1);
ager@chromium.org5c838252010-02-19 08:53:10 +000011335}
11336
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000011337
ager@chromium.org5c838252010-02-19 08:53:10 +000011338// Helper to maximize the odds of object moving.
11339static void GenerateSomeGarbage() {
11340 CompileRun(
11341 "var garbage;"
11342 "for (var i = 0; i < 1000; i++) {"
11343 " garbage = [1/i, \"garbage\" + i, garbage, {foo: garbage}];"
11344 "}"
11345 "garbage = undefined;");
11346}
11347
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000011348
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011349void DirectApiCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +000011350 static int count = 0;
11351 if (count++ % 3 == 0) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000011352 CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
yangguo@chromium.orgd2899aa2012-06-21 11:16:20 +000011353 // This should move the stub
ricow@chromium.org83aa5492011-02-07 12:42:56 +000011354 GenerateSomeGarbage(); // This should ensure the old stub memory is flushed
11355 }
ricow@chromium.org83aa5492011-02-07 12:42:56 +000011356}
11357
11358
11359THREADED_TEST(CallICFastApi_DirectCall_GCMoveStub) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +000011360 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000011361 v8::HandleScope scope(context->GetIsolate());
ricow@chromium.org83aa5492011-02-07 12:42:56 +000011362 v8::Handle<v8::ObjectTemplate> nativeobject_templ = v8::ObjectTemplate::New();
11363 nativeobject_templ->Set("callback",
11364 v8::FunctionTemplate::New(DirectApiCallback));
11365 v8::Local<v8::Object> nativeobject_obj = nativeobject_templ->NewInstance();
11366 context->Global()->Set(v8_str("nativeobject"), nativeobject_obj);
11367 // call the api function multiple times to ensure direct call stub creation.
11368 CompileRun(
11369 "function f() {"
11370 " for (var i = 1; i <= 30; i++) {"
11371 " nativeobject.callback();"
11372 " }"
11373 "}"
11374 "f();");
11375}
11376
11377
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011378void ThrowingDirectApiCallback(
11379 const v8::FunctionCallbackInfo<v8::Value>& args) {
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000011380 args.GetIsolate()->ThrowException(v8_str("g"));
ricow@chromium.org83aa5492011-02-07 12:42:56 +000011381}
11382
11383
11384THREADED_TEST(CallICFastApi_DirectCall_Throw) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +000011385 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000011386 v8::HandleScope scope(context->GetIsolate());
ricow@chromium.org83aa5492011-02-07 12:42:56 +000011387 v8::Handle<v8::ObjectTemplate> nativeobject_templ = v8::ObjectTemplate::New();
11388 nativeobject_templ->Set("callback",
11389 v8::FunctionTemplate::New(ThrowingDirectApiCallback));
11390 v8::Local<v8::Object> nativeobject_obj = nativeobject_templ->NewInstance();
11391 context->Global()->Set(v8_str("nativeobject"), nativeobject_obj);
11392 // call the api function multiple times to ensure direct call stub creation.
11393 v8::Handle<Value> result = CompileRun(
11394 "var result = '';"
11395 "function f() {"
11396 " for (var i = 1; i <= 5; i++) {"
11397 " try { nativeobject.callback(); } catch (e) { result += e; }"
11398 " }"
11399 "}"
11400 "f(); result;");
11401 CHECK_EQ(v8_str("ggggg"), result);
11402}
11403
11404
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +000011405static Handle<Value> DoDirectGetter() {
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000011406 if (++p_getter_count % 3 == 0) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000011407 CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000011408 GenerateSomeGarbage();
11409 }
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +000011410 return v8_str("Direct Getter Result");
11411}
11412
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +000011413static void DirectGetterCallback(
11414 Local<String> name,
11415 const v8::PropertyCallbackInfo<v8::Value>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +000011416 CheckReturnValue(info, FUNCTION_ADDR(DirectGetterCallback));
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +000011417 info.GetReturnValue().Set(DoDirectGetter());
11418}
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000011419
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +000011420
11421template<typename Accessor>
11422static void LoadICFastApi_DirectCall_GCMoveStub(Accessor accessor) {
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000011423 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000011424 v8::HandleScope scope(context->GetIsolate());
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000011425 v8::Handle<v8::ObjectTemplate> obj = v8::ObjectTemplate::New();
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +000011426 obj->SetAccessor(v8_str("p1"), accessor);
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000011427 context->Global()->Set(v8_str("o1"), obj->NewInstance());
11428 p_getter_count = 0;
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +000011429 v8::Handle<v8::Value> result = CompileRun(
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000011430 "function f() {"
11431 " for (var i = 0; i < 30; i++) o1.p1;"
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +000011432 " return o1.p1"
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000011433 "}"
11434 "f();");
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +000011435 CHECK_EQ(v8_str("Direct Getter Result"), result);
11436 CHECK_EQ(31, p_getter_count);
11437}
11438
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000011439
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011440THREADED_PROFILED_TEST(LoadICFastApi_DirectCall_GCMoveStub) {
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +000011441 LoadICFastApi_DirectCall_GCMoveStub(DirectGetterCallback);
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000011442}
11443
11444
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011445void ThrowingDirectGetterCallback(
11446 Local<String> name,
11447 const v8::PropertyCallbackInfo<v8::Value>& info) {
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000011448 info.GetIsolate()->ThrowException(v8_str("g"));
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000011449}
11450
11451
11452THREADED_TEST(LoadICFastApi_DirectCall_Throw) {
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000011453 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000011454 v8::HandleScope scope(context->GetIsolate());
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000011455 v8::Handle<v8::ObjectTemplate> obj = v8::ObjectTemplate::New();
11456 obj->SetAccessor(v8_str("p1"), ThrowingDirectGetterCallback);
11457 context->Global()->Set(v8_str("o1"), obj->NewInstance());
11458 v8::Handle<Value> result = CompileRun(
11459 "var result = '';"
11460 "for (var i = 0; i < 5; i++) {"
11461 " try { o1.p1; } catch (e) { result += e; }"
11462 "}"
11463 "result;");
11464 CHECK_EQ(v8_str("ggggg"), result);
11465}
11466
11467
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011468THREADED_PROFILED_TEST(InterceptorCallICFastApi_TrivialSignature) {
ager@chromium.org5c838252010-02-19 08:53:10 +000011469 int interceptor_call_count = 0;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000011470 v8::HandleScope scope(CcTest::isolate());
ager@chromium.org5c838252010-02-19 08:53:10 +000011471 v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
11472 v8::Handle<v8::FunctionTemplate> method_templ =
11473 v8::FunctionTemplate::New(FastApiCallback_TrivialSignature,
11474 v8_str("method_data"),
11475 v8::Handle<v8::Signature>());
11476 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
11477 proto_templ->Set(v8_str("method"), method_templ);
11478 v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
11479 templ->SetNamedPropertyHandler(InterceptorCallICFastApi,
11480 NULL, NULL, NULL, NULL,
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000011481 v8::External::New(&interceptor_call_count));
ager@chromium.org5c838252010-02-19 08:53:10 +000011482 LocalContext context;
11483 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
11484 GenerateSomeGarbage();
11485 context->Global()->Set(v8_str("o"), fun->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000011486 CompileRun(
ager@chromium.org5c838252010-02-19 08:53:10 +000011487 "var result = 0;"
11488 "for (var i = 0; i < 100; i++) {"
11489 " result = o.method(41);"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000011490 "}");
ager@chromium.org5c838252010-02-19 08:53:10 +000011491 CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
11492 CHECK_EQ(100, interceptor_call_count);
11493}
11494
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000011495
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011496THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature) {
ager@chromium.org5c838252010-02-19 08:53:10 +000011497 int interceptor_call_count = 0;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000011498 v8::HandleScope scope(CcTest::isolate());
ager@chromium.org5c838252010-02-19 08:53:10 +000011499 v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
11500 v8::Handle<v8::FunctionTemplate> method_templ =
11501 v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
11502 v8_str("method_data"),
11503 v8::Signature::New(fun_templ));
11504 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
11505 proto_templ->Set(v8_str("method"), method_templ);
mmassi@chromium.org49a44672012-12-04 13:52:03 +000011506 fun_templ->SetHiddenPrototype(true);
ager@chromium.org5c838252010-02-19 08:53:10 +000011507 v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
11508 templ->SetNamedPropertyHandler(InterceptorCallICFastApi,
11509 NULL, NULL, NULL, NULL,
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000011510 v8::External::New(&interceptor_call_count));
ager@chromium.org5c838252010-02-19 08:53:10 +000011511 LocalContext context;
11512 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
11513 GenerateSomeGarbage();
11514 context->Global()->Set(v8_str("o"), fun->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000011515 CompileRun(
ager@chromium.org5c838252010-02-19 08:53:10 +000011516 "o.foo = 17;"
11517 "var receiver = {};"
11518 "receiver.__proto__ = o;"
11519 "var result = 0;"
11520 "for (var i = 0; i < 100; i++) {"
11521 " result = receiver.method(41);"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000011522 "}");
ager@chromium.org5c838252010-02-19 08:53:10 +000011523 CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
11524 CHECK_EQ(100, interceptor_call_count);
11525}
11526
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000011527
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011528THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss1) {
ager@chromium.org5c838252010-02-19 08:53:10 +000011529 int interceptor_call_count = 0;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000011530 v8::HandleScope scope(CcTest::isolate());
ager@chromium.org5c838252010-02-19 08:53:10 +000011531 v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
11532 v8::Handle<v8::FunctionTemplate> method_templ =
11533 v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
11534 v8_str("method_data"),
11535 v8::Signature::New(fun_templ));
11536 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
11537 proto_templ->Set(v8_str("method"), method_templ);
mmassi@chromium.org49a44672012-12-04 13:52:03 +000011538 fun_templ->SetHiddenPrototype(true);
ager@chromium.org5c838252010-02-19 08:53:10 +000011539 v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
11540 templ->SetNamedPropertyHandler(InterceptorCallICFastApi,
11541 NULL, NULL, NULL, NULL,
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000011542 v8::External::New(&interceptor_call_count));
ager@chromium.org5c838252010-02-19 08:53:10 +000011543 LocalContext context;
11544 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
11545 GenerateSomeGarbage();
11546 context->Global()->Set(v8_str("o"), fun->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000011547 CompileRun(
ager@chromium.org5c838252010-02-19 08:53:10 +000011548 "o.foo = 17;"
11549 "var receiver = {};"
11550 "receiver.__proto__ = o;"
11551 "var result = 0;"
11552 "var saved_result = 0;"
11553 "for (var i = 0; i < 100; i++) {"
11554 " result = receiver.method(41);"
11555 " if (i == 50) {"
11556 " saved_result = result;"
11557 " receiver = {method: function(x) { return x - 1 }};"
11558 " }"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000011559 "}");
ager@chromium.org5c838252010-02-19 08:53:10 +000011560 CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
11561 CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
11562 CHECK_GE(interceptor_call_count, 50);
11563}
11564
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000011565
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011566THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss2) {
ager@chromium.org5c838252010-02-19 08:53:10 +000011567 int interceptor_call_count = 0;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000011568 v8::HandleScope scope(CcTest::isolate());
ager@chromium.org5c838252010-02-19 08:53:10 +000011569 v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
11570 v8::Handle<v8::FunctionTemplate> method_templ =
11571 v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
11572 v8_str("method_data"),
11573 v8::Signature::New(fun_templ));
11574 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
11575 proto_templ->Set(v8_str("method"), method_templ);
mmassi@chromium.org49a44672012-12-04 13:52:03 +000011576 fun_templ->SetHiddenPrototype(true);
ager@chromium.org5c838252010-02-19 08:53:10 +000011577 v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
11578 templ->SetNamedPropertyHandler(InterceptorCallICFastApi,
11579 NULL, NULL, NULL, NULL,
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000011580 v8::External::New(&interceptor_call_count));
ager@chromium.org5c838252010-02-19 08:53:10 +000011581 LocalContext context;
11582 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
11583 GenerateSomeGarbage();
11584 context->Global()->Set(v8_str("o"), fun->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000011585 CompileRun(
ager@chromium.org5c838252010-02-19 08:53:10 +000011586 "o.foo = 17;"
11587 "var receiver = {};"
11588 "receiver.__proto__ = o;"
11589 "var result = 0;"
11590 "var saved_result = 0;"
11591 "for (var i = 0; i < 100; i++) {"
11592 " result = receiver.method(41);"
11593 " if (i == 50) {"
11594 " saved_result = result;"
11595 " o.method = function(x) { return x - 1 };"
11596 " }"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000011597 "}");
ager@chromium.org5c838252010-02-19 08:53:10 +000011598 CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
11599 CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
11600 CHECK_GE(interceptor_call_count, 50);
11601}
11602
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000011603
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011604THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss3) {
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000011605 int interceptor_call_count = 0;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000011606 v8::HandleScope scope(CcTest::isolate());
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000011607 v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
11608 v8::Handle<v8::FunctionTemplate> method_templ =
11609 v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
11610 v8_str("method_data"),
11611 v8::Signature::New(fun_templ));
11612 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
11613 proto_templ->Set(v8_str("method"), method_templ);
mmassi@chromium.org49a44672012-12-04 13:52:03 +000011614 fun_templ->SetHiddenPrototype(true);
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000011615 v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
11616 templ->SetNamedPropertyHandler(InterceptorCallICFastApi,
11617 NULL, NULL, NULL, NULL,
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000011618 v8::External::New(&interceptor_call_count));
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000011619 LocalContext context;
11620 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
11621 GenerateSomeGarbage();
11622 context->Global()->Set(v8_str("o"), fun->NewInstance());
11623 v8::TryCatch try_catch;
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000011624 CompileRun(
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000011625 "o.foo = 17;"
11626 "var receiver = {};"
11627 "receiver.__proto__ = o;"
11628 "var result = 0;"
11629 "var saved_result = 0;"
11630 "for (var i = 0; i < 100; i++) {"
11631 " result = receiver.method(41);"
11632 " if (i == 50) {"
11633 " saved_result = result;"
11634 " receiver = 333;"
11635 " }"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000011636 "}");
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000011637 CHECK(try_catch.HasCaught());
11638 CHECK_EQ(v8_str("TypeError: Object 333 has no method 'method'"),
11639 try_catch.Exception()->ToString());
11640 CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
11641 CHECK_GE(interceptor_call_count, 50);
11642}
11643
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000011644
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011645THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_TypeError) {
ager@chromium.org5c838252010-02-19 08:53:10 +000011646 int interceptor_call_count = 0;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000011647 v8::HandleScope scope(CcTest::isolate());
ager@chromium.org5c838252010-02-19 08:53:10 +000011648 v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
11649 v8::Handle<v8::FunctionTemplate> method_templ =
11650 v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
11651 v8_str("method_data"),
11652 v8::Signature::New(fun_templ));
11653 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
11654 proto_templ->Set(v8_str("method"), method_templ);
mmassi@chromium.org49a44672012-12-04 13:52:03 +000011655 fun_templ->SetHiddenPrototype(true);
ager@chromium.org5c838252010-02-19 08:53:10 +000011656 v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
11657 templ->SetNamedPropertyHandler(InterceptorCallICFastApi,
11658 NULL, NULL, NULL, NULL,
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000011659 v8::External::New(&interceptor_call_count));
ager@chromium.org5c838252010-02-19 08:53:10 +000011660 LocalContext context;
11661 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
11662 GenerateSomeGarbage();
11663 context->Global()->Set(v8_str("o"), fun->NewInstance());
11664 v8::TryCatch try_catch;
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000011665 CompileRun(
ager@chromium.org5c838252010-02-19 08:53:10 +000011666 "o.foo = 17;"
11667 "var receiver = {};"
11668 "receiver.__proto__ = o;"
11669 "var result = 0;"
11670 "var saved_result = 0;"
11671 "for (var i = 0; i < 100; i++) {"
11672 " result = receiver.method(41);"
11673 " if (i == 50) {"
11674 " saved_result = result;"
11675 " receiver = {method: receiver.method};"
11676 " }"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000011677 "}");
ager@chromium.org5c838252010-02-19 08:53:10 +000011678 CHECK(try_catch.HasCaught());
11679 CHECK_EQ(v8_str("TypeError: Illegal invocation"),
11680 try_catch.Exception()->ToString());
11681 CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
11682 CHECK_GE(interceptor_call_count, 50);
11683}
11684
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000011685
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011686THREADED_PROFILED_TEST(CallICFastApi_TrivialSignature) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000011687 v8::HandleScope scope(CcTest::isolate());
ager@chromium.org5c838252010-02-19 08:53:10 +000011688 v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
11689 v8::Handle<v8::FunctionTemplate> method_templ =
11690 v8::FunctionTemplate::New(FastApiCallback_TrivialSignature,
11691 v8_str("method_data"),
11692 v8::Handle<v8::Signature>());
11693 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
11694 proto_templ->Set(v8_str("method"), method_templ);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000011695 v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000011696 USE(templ);
ager@chromium.org5c838252010-02-19 08:53:10 +000011697 LocalContext context;
11698 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
11699 GenerateSomeGarbage();
11700 context->Global()->Set(v8_str("o"), fun->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000011701 CompileRun(
ager@chromium.org5c838252010-02-19 08:53:10 +000011702 "var result = 0;"
11703 "for (var i = 0; i < 100; i++) {"
11704 " result = o.method(41);"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000011705 "}");
ager@chromium.org5c838252010-02-19 08:53:10 +000011706
11707 CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
11708}
11709
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000011710
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011711THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000011712 v8::HandleScope scope(CcTest::isolate());
ager@chromium.org5c838252010-02-19 08:53:10 +000011713 v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
11714 v8::Handle<v8::FunctionTemplate> method_templ =
11715 v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
11716 v8_str("method_data"),
11717 v8::Signature::New(fun_templ));
11718 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
11719 proto_templ->Set(v8_str("method"), method_templ);
mmassi@chromium.org49a44672012-12-04 13:52:03 +000011720 fun_templ->SetHiddenPrototype(true);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000011721 v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000011722 CHECK(!templ.IsEmpty());
ager@chromium.org5c838252010-02-19 08:53:10 +000011723 LocalContext context;
11724 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
11725 GenerateSomeGarbage();
11726 context->Global()->Set(v8_str("o"), fun->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000011727 CompileRun(
ager@chromium.org5c838252010-02-19 08:53:10 +000011728 "o.foo = 17;"
11729 "var receiver = {};"
11730 "receiver.__proto__ = o;"
11731 "var result = 0;"
11732 "for (var i = 0; i < 100; i++) {"
11733 " result = receiver.method(41);"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000011734 "}");
ager@chromium.org5c838252010-02-19 08:53:10 +000011735
11736 CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
11737}
11738
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000011739
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011740THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_Miss1) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000011741 v8::HandleScope scope(CcTest::isolate());
ager@chromium.org5c838252010-02-19 08:53:10 +000011742 v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
11743 v8::Handle<v8::FunctionTemplate> method_templ =
11744 v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
11745 v8_str("method_data"),
11746 v8::Signature::New(fun_templ));
11747 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
11748 proto_templ->Set(v8_str("method"), method_templ);
mmassi@chromium.org49a44672012-12-04 13:52:03 +000011749 fun_templ->SetHiddenPrototype(true);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000011750 v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000011751 CHECK(!templ.IsEmpty());
ager@chromium.org5c838252010-02-19 08:53:10 +000011752 LocalContext context;
11753 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
11754 GenerateSomeGarbage();
11755 context->Global()->Set(v8_str("o"), fun->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000011756 CompileRun(
ager@chromium.org5c838252010-02-19 08:53:10 +000011757 "o.foo = 17;"
11758 "var receiver = {};"
11759 "receiver.__proto__ = o;"
11760 "var result = 0;"
11761 "var saved_result = 0;"
11762 "for (var i = 0; i < 100; i++) {"
11763 " result = receiver.method(41);"
11764 " if (i == 50) {"
11765 " saved_result = result;"
11766 " receiver = {method: function(x) { return x - 1 }};"
11767 " }"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000011768 "}");
ager@chromium.org5c838252010-02-19 08:53:10 +000011769 CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
11770 CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
11771}
11772
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000011773
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011774THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_Miss2) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000011775 v8::HandleScope scope(CcTest::isolate());
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000011776 v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
11777 v8::Handle<v8::FunctionTemplate> method_templ =
11778 v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
11779 v8_str("method_data"),
11780 v8::Signature::New(fun_templ));
11781 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
11782 proto_templ->Set(v8_str("method"), method_templ);
mmassi@chromium.org49a44672012-12-04 13:52:03 +000011783 fun_templ->SetHiddenPrototype(true);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000011784 v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000011785 CHECK(!templ.IsEmpty());
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000011786 LocalContext context;
11787 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
11788 GenerateSomeGarbage();
11789 context->Global()->Set(v8_str("o"), fun->NewInstance());
11790 v8::TryCatch try_catch;
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000011791 CompileRun(
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000011792 "o.foo = 17;"
11793 "var receiver = {};"
11794 "receiver.__proto__ = o;"
11795 "var result = 0;"
11796 "var saved_result = 0;"
11797 "for (var i = 0; i < 100; i++) {"
11798 " result = receiver.method(41);"
11799 " if (i == 50) {"
11800 " saved_result = result;"
11801 " receiver = 333;"
11802 " }"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000011803 "}");
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000011804 CHECK(try_catch.HasCaught());
11805 CHECK_EQ(v8_str("TypeError: Object 333 has no method 'method'"),
11806 try_catch.Exception()->ToString());
11807 CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
11808}
11809
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000011810
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011811THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_TypeError) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000011812 v8::HandleScope scope(CcTest::isolate());
mmassi@chromium.org49a44672012-12-04 13:52:03 +000011813 v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
11814 v8::Handle<v8::FunctionTemplate> method_templ =
11815 v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
11816 v8_str("method_data"),
11817 v8::Signature::New(fun_templ));
11818 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
11819 proto_templ->Set(v8_str("method"), method_templ);
11820 fun_templ->SetHiddenPrototype(true);
11821 v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
11822 CHECK(!templ.IsEmpty());
11823 LocalContext context;
11824 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
11825 GenerateSomeGarbage();
11826 context->Global()->Set(v8_str("o"), fun->NewInstance());
11827 v8::TryCatch try_catch;
11828 CompileRun(
11829 "o.foo = 17;"
11830 "var receiver = {};"
11831 "receiver.__proto__ = o;"
11832 "var result = 0;"
11833 "var saved_result = 0;"
11834 "for (var i = 0; i < 100; i++) {"
11835 " result = receiver.method(41);"
11836 " if (i == 50) {"
11837 " saved_result = result;"
11838 " receiver = Object.create(receiver);"
11839 " }"
11840 "}");
11841 CHECK(try_catch.HasCaught());
11842 CHECK_EQ(v8_str("TypeError: Illegal invocation"),
11843 try_catch.Exception()->ToString());
11844 CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
11845}
11846
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000011847
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000011848v8::Handle<Value> keyed_call_ic_function;
11849
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011850static void InterceptorKeyedCallICGetter(
11851 Local<String> name,
11852 const v8::PropertyCallbackInfo<v8::Value>& info) {
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000011853 ApiTestFuzzer::Fuzz();
11854 if (v8_str("x")->Equals(name)) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011855 info.GetReturnValue().Set(keyed_call_ic_function);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000011856 }
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000011857}
11858
11859
11860// Test the case when we stored cacheable lookup into
11861// a stub, but the function name changed (to another cacheable function).
11862THREADED_TEST(InterceptorKeyedCallICKeyChange1) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000011863 v8::HandleScope scope(CcTest::isolate());
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000011864 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
11865 templ->SetNamedPropertyHandler(NoBlockGetterX);
11866 LocalContext context;
11867 context->Global()->Set(v8_str("o"), templ->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000011868 CompileRun(
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000011869 "proto = new Object();"
11870 "proto.y = function(x) { return x + 1; };"
11871 "proto.z = function(x) { return x - 1; };"
11872 "o.__proto__ = proto;"
11873 "var result = 0;"
11874 "var method = 'y';"
11875 "for (var i = 0; i < 10; i++) {"
11876 " if (i == 5) { method = 'z'; };"
11877 " result += o[method](41);"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000011878 "}");
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000011879 CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
11880}
11881
11882
11883// Test the case when we stored cacheable lookup into
11884// a stub, but the function name changed (and the new function is present
11885// both before and after the interceptor in the prototype chain).
11886THREADED_TEST(InterceptorKeyedCallICKeyChange2) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000011887 v8::HandleScope scope(CcTest::isolate());
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000011888 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
11889 templ->SetNamedPropertyHandler(InterceptorKeyedCallICGetter);
11890 LocalContext context;
11891 context->Global()->Set(v8_str("proto1"), templ->NewInstance());
11892 keyed_call_ic_function =
11893 v8_compile("function f(x) { return x - 1; }; f")->Run();
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000011894 CompileRun(
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000011895 "o = new Object();"
11896 "proto2 = new Object();"
11897 "o.y = function(x) { return x + 1; };"
11898 "proto2.y = function(x) { return x + 2; };"
11899 "o.__proto__ = proto1;"
11900 "proto1.__proto__ = proto2;"
11901 "var result = 0;"
11902 "var method = 'x';"
11903 "for (var i = 0; i < 10; i++) {"
11904 " if (i == 5) { method = 'y'; };"
11905 " result += o[method](41);"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000011906 "}");
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000011907 CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
11908}
11909
11910
11911// Same as InterceptorKeyedCallICKeyChange1 only the cacheable function sit
11912// on the global object.
11913THREADED_TEST(InterceptorKeyedCallICKeyChangeOnGlobal) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000011914 v8::HandleScope scope(CcTest::isolate());
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000011915 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
11916 templ->SetNamedPropertyHandler(NoBlockGetterX);
11917 LocalContext context;
11918 context->Global()->Set(v8_str("o"), templ->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000011919 CompileRun(
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000011920 "function inc(x) { return x + 1; };"
11921 "inc(1);"
11922 "function dec(x) { return x - 1; };"
11923 "dec(1);"
11924 "o.__proto__ = this;"
11925 "this.__proto__.x = inc;"
11926 "this.__proto__.y = dec;"
11927 "var result = 0;"
11928 "var method = 'x';"
11929 "for (var i = 0; i < 10; i++) {"
11930 " if (i == 5) { method = 'y'; };"
11931 " result += o[method](41);"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000011932 "}");
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000011933 CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
11934}
11935
11936
11937// Test the case when actual function to call sits on global object.
11938THREADED_TEST(InterceptorKeyedCallICFromGlobal) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000011939 v8::HandleScope scope(CcTest::isolate());
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000011940 v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
11941 templ_o->SetNamedPropertyHandler(NoBlockGetterX);
11942 LocalContext context;
11943 context->Global()->Set(v8_str("o"), templ_o->NewInstance());
11944
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000011945 CompileRun(
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000011946 "function len(x) { return x.length; };"
11947 "o.__proto__ = this;"
11948 "var m = 'parseFloat';"
11949 "var result = 0;"
11950 "for (var i = 0; i < 10; i++) {"
11951 " if (i == 5) {"
11952 " m = 'len';"
11953 " saved_result = result;"
11954 " };"
11955 " result = o[m]('239');"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000011956 "}");
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000011957 CHECK_EQ(3, context->Global()->Get(v8_str("result"))->Int32Value());
11958 CHECK_EQ(239, context->Global()->Get(v8_str("saved_result"))->Int32Value());
11959}
11960
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000011961
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000011962// Test the map transition before the interceptor.
11963THREADED_TEST(InterceptorKeyedCallICMapChangeBefore) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000011964 v8::HandleScope scope(CcTest::isolate());
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000011965 v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
11966 templ_o->SetNamedPropertyHandler(NoBlockGetterX);
11967 LocalContext context;
11968 context->Global()->Set(v8_str("proto"), templ_o->NewInstance());
11969
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000011970 CompileRun(
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000011971 "var o = new Object();"
11972 "o.__proto__ = proto;"
11973 "o.method = function(x) { return x + 1; };"
11974 "var m = 'method';"
11975 "var result = 0;"
11976 "for (var i = 0; i < 10; i++) {"
11977 " if (i == 5) { o.method = function(x) { return x - 1; }; };"
11978 " result += o[m](41);"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000011979 "}");
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000011980 CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
11981}
11982
11983
11984// Test the map transition after the interceptor.
11985THREADED_TEST(InterceptorKeyedCallICMapChangeAfter) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000011986 v8::HandleScope scope(CcTest::isolate());
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000011987 v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
11988 templ_o->SetNamedPropertyHandler(NoBlockGetterX);
11989 LocalContext context;
11990 context->Global()->Set(v8_str("o"), templ_o->NewInstance());
11991
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000011992 CompileRun(
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000011993 "var proto = new Object();"
11994 "o.__proto__ = proto;"
11995 "proto.method = function(x) { return x + 1; };"
11996 "var m = 'method';"
11997 "var result = 0;"
11998 "for (var i = 0; i < 10; i++) {"
11999 " if (i == 5) { proto.method = function(x) { return x - 1; }; };"
12000 " result += o[m](41);"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012001 "}");
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012002 CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
12003}
12004
12005
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012006static int interceptor_call_count = 0;
12007
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012008static void InterceptorICRefErrorGetter(
12009 Local<String> name,
12010 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012011 ApiTestFuzzer::Fuzz();
12012 if (v8_str("x")->Equals(name) && interceptor_call_count++ < 20) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012013 info.GetReturnValue().Set(call_ic_function2);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012014 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012015}
12016
12017
12018// This test should hit load and call ICs for the interceptor case.
12019// Once in a while, the interceptor will reply that a property was not
12020// found in which case we should get a reference error.
12021THREADED_TEST(InterceptorICReferenceErrors) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000012022 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012023 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
12024 templ->SetNamedPropertyHandler(InterceptorICRefErrorGetter);
12025 LocalContext context(0, templ, v8::Handle<Value>());
12026 call_ic_function2 = v8_compile("function h(x) { return x; }; h")->Run();
12027 v8::Handle<Value> value = CompileRun(
12028 "function f() {"
12029 " for (var i = 0; i < 1000; i++) {"
12030 " try { x; } catch(e) { return true; }"
12031 " }"
12032 " return false;"
12033 "};"
12034 "f();");
12035 CHECK_EQ(true, value->BooleanValue());
12036 interceptor_call_count = 0;
12037 value = CompileRun(
12038 "function g() {"
12039 " for (var i = 0; i < 1000; i++) {"
12040 " try { x(42); } catch(e) { return true; }"
12041 " }"
12042 " return false;"
12043 "};"
12044 "g();");
12045 CHECK_EQ(true, value->BooleanValue());
12046}
12047
12048
12049static int interceptor_ic_exception_get_count = 0;
12050
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012051static void InterceptorICExceptionGetter(
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012052 Local<String> name,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012053 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012054 ApiTestFuzzer::Fuzz();
12055 if (v8_str("x")->Equals(name) && ++interceptor_ic_exception_get_count < 20) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012056 info.GetReturnValue().Set(call_ic_function3);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012057 }
12058 if (interceptor_ic_exception_get_count == 20) {
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000012059 info.GetIsolate()->ThrowException(v8_num(42));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012060 return;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012061 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012062}
12063
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012064
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012065// Test interceptor load/call IC where the interceptor throws an
12066// exception once in a while.
12067THREADED_TEST(InterceptorICGetterExceptions) {
12068 interceptor_ic_exception_get_count = 0;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000012069 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012070 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
12071 templ->SetNamedPropertyHandler(InterceptorICExceptionGetter);
12072 LocalContext context(0, templ, v8::Handle<Value>());
12073 call_ic_function3 = v8_compile("function h(x) { return x; }; h")->Run();
12074 v8::Handle<Value> value = CompileRun(
12075 "function f() {"
12076 " for (var i = 0; i < 100; i++) {"
12077 " try { x; } catch(e) { return true; }"
12078 " }"
12079 " return false;"
12080 "};"
12081 "f();");
12082 CHECK_EQ(true, value->BooleanValue());
12083 interceptor_ic_exception_get_count = 0;
12084 value = CompileRun(
12085 "function f() {"
12086 " for (var i = 0; i < 100; i++) {"
12087 " try { x(42); } catch(e) { return true; }"
12088 " }"
12089 " return false;"
12090 "};"
12091 "f();");
12092 CHECK_EQ(true, value->BooleanValue());
12093}
12094
12095
12096static int interceptor_ic_exception_set_count = 0;
12097
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012098static void InterceptorICExceptionSetter(
12099 Local<String> key,
12100 Local<Value> value,
12101 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012102 ApiTestFuzzer::Fuzz();
12103 if (++interceptor_ic_exception_set_count > 20) {
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000012104 info.GetIsolate()->ThrowException(v8_num(42));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012105 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012106}
12107
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012108
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012109// Test interceptor store IC where the interceptor throws an exception
12110// once in a while.
12111THREADED_TEST(InterceptorICSetterExceptions) {
12112 interceptor_ic_exception_set_count = 0;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000012113 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012114 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
12115 templ->SetNamedPropertyHandler(0, InterceptorICExceptionSetter);
12116 LocalContext context(0, templ, v8::Handle<Value>());
12117 v8::Handle<Value> value = CompileRun(
12118 "function f() {"
12119 " for (var i = 0; i < 100; i++) {"
12120 " try { x = 42; } catch(e) { return true; }"
12121 " }"
12122 " return false;"
12123 "};"
12124 "f();");
12125 CHECK_EQ(true, value->BooleanValue());
12126}
12127
12128
12129// Test that we ignore null interceptors.
12130THREADED_TEST(NullNamedInterceptor) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000012131 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012132 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012133 templ->SetNamedPropertyHandler(
12134 static_cast<v8::NamedPropertyGetterCallback>(0));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012135 LocalContext context;
12136 templ->Set("x", v8_num(42));
12137 v8::Handle<v8::Object> obj = templ->NewInstance();
12138 context->Global()->Set(v8_str("obj"), obj);
12139 v8::Handle<Value> value = CompileRun("obj.x");
12140 CHECK(value->IsInt32());
12141 CHECK_EQ(42, value->Int32Value());
12142}
12143
12144
12145// Test that we ignore null interceptors.
12146THREADED_TEST(NullIndexedInterceptor) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000012147 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012148 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012149 templ->SetIndexedPropertyHandler(
12150 static_cast<v8::IndexedPropertyGetterCallback>(0));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012151 LocalContext context;
12152 templ->Set("42", v8_num(42));
12153 v8::Handle<v8::Object> obj = templ->NewInstance();
12154 context->Global()->Set(v8_str("obj"), obj);
12155 v8::Handle<Value> value = CompileRun("obj[42]");
12156 CHECK(value->IsInt32());
12157 CHECK_EQ(42, value->Int32Value());
12158}
12159
12160
ricow@chromium.org30ce4112010-05-31 10:38:25 +000012161THREADED_TEST(NamedPropertyHandlerGetterAttributes) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000012162 v8::HandleScope scope(CcTest::isolate());
ricow@chromium.org30ce4112010-05-31 10:38:25 +000012163 v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
12164 templ->InstanceTemplate()->SetNamedPropertyHandler(InterceptorLoadXICGetter);
12165 LocalContext env;
12166 env->Global()->Set(v8_str("obj"),
12167 templ->GetFunction()->NewInstance());
12168 ExpectTrue("obj.x === 42");
12169 ExpectTrue("!obj.propertyIsEnumerable('x')");
12170}
12171
12172
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012173static void ThrowingGetter(Local<String> name,
12174 const v8::PropertyCallbackInfo<v8::Value>& info) {
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012175 ApiTestFuzzer::Fuzz();
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000012176 info.GetIsolate()->ThrowException(Handle<Value>());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012177 info.GetReturnValue().SetUndefined();
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012178}
12179
12180
12181THREADED_TEST(VariousGetPropertiesAndThrowingCallbacks) {
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012182 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000012183 HandleScope scope(context->GetIsolate());
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012184
12185 Local<FunctionTemplate> templ = FunctionTemplate::New();
12186 Local<ObjectTemplate> instance_templ = templ->InstanceTemplate();
12187 instance_templ->SetAccessor(v8_str("f"), ThrowingGetter);
12188
12189 Local<Object> instance = templ->GetFunction()->NewInstance();
12190
12191 Local<Object> another = Object::New();
12192 another->SetPrototype(instance);
12193
12194 Local<Object> with_js_getter = CompileRun(
12195 "o = {};\n"
12196 "o.__defineGetter__('f', function() { throw undefined; });\n"
12197 "o\n").As<Object>();
12198 CHECK(!with_js_getter.IsEmpty());
12199
12200 TryCatch try_catch;
12201
12202 Local<Value> result = instance->GetRealNamedProperty(v8_str("f"));
12203 CHECK(try_catch.HasCaught());
12204 try_catch.Reset();
12205 CHECK(result.IsEmpty());
12206
12207 result = another->GetRealNamedProperty(v8_str("f"));
12208 CHECK(try_catch.HasCaught());
12209 try_catch.Reset();
12210 CHECK(result.IsEmpty());
12211
12212 result = another->GetRealNamedPropertyInPrototypeChain(v8_str("f"));
12213 CHECK(try_catch.HasCaught());
12214 try_catch.Reset();
12215 CHECK(result.IsEmpty());
12216
12217 result = another->Get(v8_str("f"));
12218 CHECK(try_catch.HasCaught());
12219 try_catch.Reset();
12220 CHECK(result.IsEmpty());
12221
12222 result = with_js_getter->GetRealNamedProperty(v8_str("f"));
12223 CHECK(try_catch.HasCaught());
12224 try_catch.Reset();
12225 CHECK(result.IsEmpty());
12226
12227 result = with_js_getter->Get(v8_str("f"));
12228 CHECK(try_catch.HasCaught());
12229 try_catch.Reset();
12230 CHECK(result.IsEmpty());
12231}
12232
12233
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012234static void ThrowingCallbackWithTryCatch(
12235 const v8::FunctionCallbackInfo<v8::Value>& args) {
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012236 TryCatch try_catch;
12237 // Verboseness is important: it triggers message delivery which can call into
12238 // external code.
12239 try_catch.SetVerbose(true);
12240 CompileRun("throw 'from JS';");
12241 CHECK(try_catch.HasCaught());
machenbach@chromium.org528ce022013-09-23 14:09:36 +000012242 CHECK(!CcTest::i_isolate()->has_pending_exception());
12243 CHECK(!CcTest::i_isolate()->has_scheduled_exception());
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012244}
12245
12246
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +000012247static int call_depth;
12248
12249
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012250static void WithTryCatch(Handle<Message> message, Handle<Value> data) {
12251 TryCatch try_catch;
12252}
12253
12254
12255static void ThrowFromJS(Handle<Message> message, Handle<Value> data) {
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +000012256 if (--call_depth) CompileRun("throw 'ThrowInJS';");
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012257}
12258
12259
12260static void ThrowViaApi(Handle<Message> message, Handle<Value> data) {
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000012261 if (--call_depth) CcTest::isolate()->ThrowException(v8_str("ThrowViaApi"));
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012262}
12263
12264
12265static void WebKitLike(Handle<Message> message, Handle<Value> data) {
12266 Handle<String> errorMessageString = message->Get();
12267 CHECK(!errorMessageString.IsEmpty());
12268 message->GetStackTrace();
12269 message->GetScriptResourceName();
12270}
12271
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012272
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012273THREADED_TEST(ExceptionsDoNotPropagatePastTryCatch) {
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012274 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000012275 HandleScope scope(context->GetIsolate());
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012276
12277 Local<Function> func =
12278 FunctionTemplate::New(ThrowingCallbackWithTryCatch)->GetFunction();
12279 context->Global()->Set(v8_str("func"), func);
12280
12281 MessageCallback callbacks[] =
12282 { NULL, WebKitLike, ThrowViaApi, ThrowFromJS, WithTryCatch };
12283 for (unsigned i = 0; i < sizeof(callbacks)/sizeof(callbacks[0]); i++) {
12284 MessageCallback callback = callbacks[i];
12285 if (callback != NULL) {
12286 V8::AddMessageListener(callback);
12287 }
ricow@chromium.orgdcebac02011-04-20 09:44:50 +000012288 // Some small number to control number of times message handler should
12289 // throw an exception.
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +000012290 call_depth = 5;
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012291 ExpectFalse(
12292 "var thrown = false;\n"
12293 "try { func(); } catch(e) { thrown = true; }\n"
12294 "thrown\n");
12295 if (callback != NULL) {
12296 V8::RemoveMessageListeners(callback);
12297 }
12298 }
12299}
12300
12301
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012302static void ParentGetter(Local<String> name,
12303 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012304 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012305 info.GetReturnValue().Set(v8_num(1));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012306}
12307
12308
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012309static void ChildGetter(Local<String> name,
12310 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012311 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012312 info.GetReturnValue().Set(v8_num(42));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012313}
12314
12315
12316THREADED_TEST(Overriding) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +000012317 i::FLAG_es5_readonly = true;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012318 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000012319 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012320
12321 // Parent template.
12322 Local<v8::FunctionTemplate> parent_templ = v8::FunctionTemplate::New();
12323 Local<ObjectTemplate> parent_instance_templ =
12324 parent_templ->InstanceTemplate();
12325 parent_instance_templ->SetAccessor(v8_str("f"), ParentGetter);
12326
12327 // Template that inherits from the parent template.
12328 Local<v8::FunctionTemplate> child_templ = v8::FunctionTemplate::New();
12329 Local<ObjectTemplate> child_instance_templ =
12330 child_templ->InstanceTemplate();
12331 child_templ->Inherit(parent_templ);
12332 // Override 'f'. The child version of 'f' should get called for child
12333 // instances.
12334 child_instance_templ->SetAccessor(v8_str("f"), ChildGetter);
12335 // Add 'g' twice. The 'g' added last should get called for instances.
12336 child_instance_templ->SetAccessor(v8_str("g"), ParentGetter);
12337 child_instance_templ->SetAccessor(v8_str("g"), ChildGetter);
12338
12339 // Add 'h' as an accessor to the proto template with ReadOnly attributes
12340 // so 'h' can be shadowed on the instance object.
12341 Local<ObjectTemplate> child_proto_templ = child_templ->PrototypeTemplate();
12342 child_proto_templ->SetAccessor(v8_str("h"), ParentGetter, 0,
12343 v8::Handle<Value>(), v8::DEFAULT, v8::ReadOnly);
12344
12345 // Add 'i' as an accessor to the instance template with ReadOnly attributes
12346 // but the attribute does not have effect because it is duplicated with
12347 // NULL setter.
12348 child_instance_templ->SetAccessor(v8_str("i"), ChildGetter, 0,
12349 v8::Handle<Value>(), v8::DEFAULT, v8::ReadOnly);
12350
12351
12352
12353 // Instantiate the child template.
12354 Local<v8::Object> instance = child_templ->GetFunction()->NewInstance();
12355
12356 // Check that the child function overrides the parent one.
12357 context->Global()->Set(v8_str("o"), instance);
12358 Local<Value> value = v8_compile("o.f")->Run();
12359 // Check that the 'g' that was added last is hit.
12360 CHECK_EQ(42, value->Int32Value());
12361 value = v8_compile("o.g")->Run();
12362 CHECK_EQ(42, value->Int32Value());
12363
mmassi@chromium.org7028c052012-06-13 11:51:58 +000012364 // Check that 'h' cannot be shadowed.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012365 value = v8_compile("o.h = 3; o.h")->Run();
mmassi@chromium.org7028c052012-06-13 11:51:58 +000012366 CHECK_EQ(1, value->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012367
mmassi@chromium.org7028c052012-06-13 11:51:58 +000012368 // Check that 'i' cannot be shadowed or changed.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012369 value = v8_compile("o.i = 3; o.i")->Run();
12370 CHECK_EQ(42, value->Int32Value());
12371}
12372
12373
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012374static void IsConstructHandler(
12375 const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012376 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012377 args.GetReturnValue().Set(args.IsConstructCall());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012378}
12379
12380
12381THREADED_TEST(IsConstructCall) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000012382 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012383
12384 // Function template with call handler.
12385 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
12386 templ->SetCallHandler(IsConstructHandler);
12387
12388 LocalContext context;
12389
12390 context->Global()->Set(v8_str("f"), templ->GetFunction());
12391 Local<Value> value = v8_compile("f()")->Run();
12392 CHECK(!value->BooleanValue());
12393 value = v8_compile("new f()")->Run();
12394 CHECK(value->BooleanValue());
12395}
12396
12397
12398THREADED_TEST(ObjectProtoToString) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000012399 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012400 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
12401 templ->SetClassName(v8_str("MyClass"));
12402
12403 LocalContext context;
12404
12405 Local<String> customized_tostring = v8_str("customized toString");
12406
12407 // Replace Object.prototype.toString
12408 v8_compile("Object.prototype.toString = function() {"
12409 " return 'customized toString';"
12410 "}")->Run();
12411
12412 // Normal ToString call should call replaced Object.prototype.toString
12413 Local<v8::Object> instance = templ->GetFunction()->NewInstance();
12414 Local<String> value = instance->ToString();
12415 CHECK(value->IsString() && value->Equals(customized_tostring));
12416
12417 // ObjectProtoToString should not call replace toString function.
12418 value = instance->ObjectProtoToString();
12419 CHECK(value->IsString() && value->Equals(v8_str("[object MyClass]")));
12420
12421 // Check global
12422 value = context->Global()->ObjectProtoToString();
12423 CHECK(value->IsString() && value->Equals(v8_str("[object global]")));
12424
12425 // Check ordinary object
12426 Local<Value> object = v8_compile("new Object()")->Run();
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000012427 value = object.As<v8::Object>()->ObjectProtoToString();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012428 CHECK(value->IsString() && value->Equals(v8_str("[object Object]")));
12429}
12430
12431
ager@chromium.orgbeb25712010-11-29 08:02:25 +000012432THREADED_TEST(ObjectGetConstructorName) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +000012433 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000012434 v8::HandleScope scope(context->GetIsolate());
ager@chromium.orgbeb25712010-11-29 08:02:25 +000012435 v8_compile("function Parent() {};"
12436 "function Child() {};"
12437 "Child.prototype = new Parent();"
12438 "var outer = { inner: function() { } };"
12439 "var p = new Parent();"
12440 "var c = new Child();"
12441 "var x = new outer.inner();")->Run();
12442
12443 Local<v8::Value> p = context->Global()->Get(v8_str("p"));
12444 CHECK(p->IsObject() && p->ToObject()->GetConstructorName()->Equals(
12445 v8_str("Parent")));
12446
12447 Local<v8::Value> c = context->Global()->Get(v8_str("c"));
12448 CHECK(c->IsObject() && c->ToObject()->GetConstructorName()->Equals(
12449 v8_str("Child")));
12450
12451 Local<v8::Value> x = context->Global()->Get(v8_str("x"));
12452 CHECK(x->IsObject() && x->ToObject()->GetConstructorName()->Equals(
12453 v8_str("outer.inner")));
12454}
12455
12456
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012457bool ApiTestFuzzer::fuzzing_ = false;
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000012458i::Semaphore ApiTestFuzzer::all_tests_done_(0);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012459int ApiTestFuzzer::active_tests_;
12460int ApiTestFuzzer::tests_being_run_;
12461int ApiTestFuzzer::current_;
12462
12463
12464// We are in a callback and want to switch to another thread (if we
12465// are currently running the thread fuzzing test).
12466void ApiTestFuzzer::Fuzz() {
12467 if (!fuzzing_) return;
12468 ApiTestFuzzer* test = RegisterThreadedTest::nth(current_)->fuzzer_;
12469 test->ContextSwitch();
12470}
12471
12472
12473// Let the next thread go. Since it is also waiting on the V8 lock it may
12474// not start immediately.
12475bool ApiTestFuzzer::NextThread() {
12476 int test_position = GetNextTestNumber();
ager@chromium.orgc4c92722009-11-18 14:12:51 +000012477 const char* test_name = RegisterThreadedTest::nth(current_)->name();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012478 if (test_position == current_) {
ager@chromium.orgc4c92722009-11-18 14:12:51 +000012479 if (kLogThreading)
12480 printf("Stay with %s\n", test_name);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012481 return false;
12482 }
ager@chromium.orgc4c92722009-11-18 14:12:51 +000012483 if (kLogThreading) {
12484 printf("Switch from %s to %s\n",
12485 test_name,
12486 RegisterThreadedTest::nth(test_position)->name());
12487 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012488 current_ = test_position;
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000012489 RegisterThreadedTest::nth(current_)->fuzzer_->gate_.Signal();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012490 return true;
12491}
12492
12493
12494void ApiTestFuzzer::Run() {
12495 // When it is our turn...
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000012496 gate_.Wait();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012497 {
12498 // ... get the V8 lock and start running the test.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000012499 v8::Locker locker(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012500 CallTest();
12501 }
12502 // This test finished.
12503 active_ = false;
12504 active_tests_--;
12505 // If it was the last then signal that fact.
12506 if (active_tests_ == 0) {
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000012507 all_tests_done_.Signal();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012508 } else {
12509 // Otherwise select a new test and start that.
12510 NextThread();
12511 }
12512}
12513
12514
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012515static unsigned linear_congruential_generator;
12516
12517
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000012518void ApiTestFuzzer::SetUp(PartOfTest part) {
kasperl@chromium.orgb9123622008-09-17 14:05:56 +000012519 linear_congruential_generator = i::FLAG_testing_prng_seed;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012520 fuzzing_ = true;
lrn@chromium.org1c092762011-05-09 09:42:16 +000012521 int count = RegisterThreadedTest::count();
12522 int start = count * part / (LAST_PART + 1);
12523 int end = (count * (part + 1) / (LAST_PART + 1)) - 1;
12524 active_tests_ = tests_being_run_ = end - start + 1;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012525 for (int i = 0; i < tests_being_run_; i++) {
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000012526 RegisterThreadedTest::nth(i)->fuzzer_ = new ApiTestFuzzer(i + start);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012527 }
12528 for (int i = 0; i < active_tests_; i++) {
12529 RegisterThreadedTest::nth(i)->fuzzer_->Start();
12530 }
12531}
12532
12533
12534static void CallTestNumber(int test_number) {
12535 (RegisterThreadedTest::nth(test_number)->callback())();
12536}
12537
12538
12539void ApiTestFuzzer::RunAllTests() {
12540 // Set off the first test.
12541 current_ = -1;
12542 NextThread();
12543 // Wait till they are all done.
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000012544 all_tests_done_.Wait();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012545}
12546
12547
12548int ApiTestFuzzer::GetNextTestNumber() {
12549 int next_test;
12550 do {
12551 next_test = (linear_congruential_generator >> 16) % tests_being_run_;
12552 linear_congruential_generator *= 1664525u;
12553 linear_congruential_generator += 1013904223u;
12554 } while (!RegisterThreadedTest::nth(next_test)->fuzzer_->active_);
12555 return next_test;
12556}
12557
12558
12559void ApiTestFuzzer::ContextSwitch() {
12560 // If the new thread is the same as the current thread there is nothing to do.
12561 if (NextThread()) {
12562 // Now it can start.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000012563 v8::Unlocker unlocker(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012564 // Wait till someone starts us again.
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000012565 gate_.Wait();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012566 // And we're off.
12567 }
12568}
12569
12570
12571void ApiTestFuzzer::TearDown() {
12572 fuzzing_ = false;
ager@chromium.org41826e72009-03-30 13:30:57 +000012573 for (int i = 0; i < RegisterThreadedTest::count(); i++) {
12574 ApiTestFuzzer *fuzzer = RegisterThreadedTest::nth(i)->fuzzer_;
12575 if (fuzzer != NULL) fuzzer->Join();
12576 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012577}
12578
12579
12580// Lets not be needlessly self-referential.
mmassi@chromium.org2f0efde2013-02-06 14:12:58 +000012581TEST(Threading1) {
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000012582 ApiTestFuzzer::SetUp(ApiTestFuzzer::FIRST_PART);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012583 ApiTestFuzzer::RunAllTests();
12584 ApiTestFuzzer::TearDown();
12585}
12586
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012587
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012588TEST(Threading2) {
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000012589 ApiTestFuzzer::SetUp(ApiTestFuzzer::SECOND_PART);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012590 ApiTestFuzzer::RunAllTests();
12591 ApiTestFuzzer::TearDown();
12592}
12593
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012594
lrn@chromium.org1c092762011-05-09 09:42:16 +000012595TEST(Threading3) {
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000012596 ApiTestFuzzer::SetUp(ApiTestFuzzer::THIRD_PART);
lrn@chromium.org1c092762011-05-09 09:42:16 +000012597 ApiTestFuzzer::RunAllTests();
12598 ApiTestFuzzer::TearDown();
12599}
12600
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012601
lrn@chromium.org1c092762011-05-09 09:42:16 +000012602TEST(Threading4) {
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000012603 ApiTestFuzzer::SetUp(ApiTestFuzzer::FOURTH_PART);
lrn@chromium.org1c092762011-05-09 09:42:16 +000012604 ApiTestFuzzer::RunAllTests();
12605 ApiTestFuzzer::TearDown();
12606}
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012607
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012608
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012609void ApiTestFuzzer::CallTest() {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000012610 v8::Isolate::Scope scope(CcTest::isolate());
ager@chromium.orgc4c92722009-11-18 14:12:51 +000012611 if (kLogThreading)
12612 printf("Start test %d\n", test_number_);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012613 CallTestNumber(test_number_);
ager@chromium.orgc4c92722009-11-18 14:12:51 +000012614 if (kLogThreading)
12615 printf("End test %d\n", test_number_);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012616}
12617
12618
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012619static void ThrowInJS(const v8::FunctionCallbackInfo<v8::Value>& args) {
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000012620 v8::Isolate* isolate = args.GetIsolate();
12621 CHECK(v8::Locker::IsLocked(isolate));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012622 ApiTestFuzzer::Fuzz();
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000012623 v8::Unlocker unlocker(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012624 const char* code = "throw 7;";
12625 {
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000012626 v8::Locker nested_locker(isolate);
12627 v8::HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012628 v8::Handle<Value> exception;
12629 { v8::TryCatch try_catch;
12630 v8::Handle<Value> value = CompileRun(code);
12631 CHECK(value.IsEmpty());
12632 CHECK(try_catch.HasCaught());
12633 // Make sure to wrap the exception in a new handle because
12634 // the handle returned from the TryCatch is destroyed
12635 // when the TryCatch is destroyed.
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000012636 exception = Local<Value>::New(isolate, try_catch.Exception());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012637 }
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000012638 args.GetIsolate()->ThrowException(exception);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012639 }
12640}
12641
12642
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012643static void ThrowInJSNoCatch(const v8::FunctionCallbackInfo<v8::Value>& args) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000012644 CHECK(v8::Locker::IsLocked(CcTest::isolate()));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012645 ApiTestFuzzer::Fuzz();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000012646 v8::Unlocker unlocker(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012647 const char* code = "throw 7;";
12648 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000012649 v8::Locker nested_locker(CcTest::isolate());
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000012650 v8::HandleScope scope(args.GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012651 v8::Handle<Value> value = CompileRun(code);
12652 CHECK(value.IsEmpty());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012653 args.GetReturnValue().Set(v8_str("foo"));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012654 }
12655}
12656
12657
12658// These are locking tests that don't need to be run again
12659// as part of the locking aggregation tests.
12660TEST(NestedLockers) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000012661 v8::Locker locker(CcTest::isolate());
12662 CHECK(v8::Locker::IsLocked(CcTest::isolate()));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012663 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000012664 v8::HandleScope scope(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012665 Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(ThrowInJS);
12666 Local<Function> fun = fun_templ->GetFunction();
12667 env->Global()->Set(v8_str("throw_in_js"), fun);
12668 Local<Script> script = v8_compile("(function () {"
12669 " try {"
12670 " throw_in_js();"
12671 " return 42;"
12672 " } catch (e) {"
12673 " return e * 13;"
12674 " }"
12675 "})();");
12676 CHECK_EQ(91, script->Run()->Int32Value());
12677}
12678
12679
12680// These are locking tests that don't need to be run again
12681// as part of the locking aggregation tests.
12682TEST(NestedLockersNoTryCatch) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000012683 v8::Locker locker(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012684 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000012685 v8::HandleScope scope(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012686 Local<v8::FunctionTemplate> fun_templ =
12687 v8::FunctionTemplate::New(ThrowInJSNoCatch);
12688 Local<Function> fun = fun_templ->GetFunction();
12689 env->Global()->Set(v8_str("throw_in_js"), fun);
12690 Local<Script> script = v8_compile("(function () {"
12691 " try {"
12692 " throw_in_js();"
12693 " return 42;"
12694 " } catch (e) {"
12695 " return e * 13;"
12696 " }"
12697 "})();");
12698 CHECK_EQ(91, script->Run()->Int32Value());
12699}
12700
12701
12702THREADED_TEST(RecursiveLocking) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000012703 v8::Locker locker(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012704 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000012705 v8::Locker locker2(CcTest::isolate());
12706 CHECK(v8::Locker::IsLocked(CcTest::isolate()));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012707 }
12708}
12709
12710
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012711static void UnlockForAMoment(const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012712 ApiTestFuzzer::Fuzz();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000012713 v8::Unlocker unlocker(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012714}
12715
12716
12717THREADED_TEST(LockUnlockLock) {
12718 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000012719 v8::Locker locker(CcTest::isolate());
12720 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012721 LocalContext env;
12722 Local<v8::FunctionTemplate> fun_templ =
12723 v8::FunctionTemplate::New(UnlockForAMoment);
12724 Local<Function> fun = fun_templ->GetFunction();
12725 env->Global()->Set(v8_str("unlock_for_a_moment"), fun);
12726 Local<Script> script = v8_compile("(function () {"
12727 " unlock_for_a_moment();"
12728 " return 42;"
12729 "})();");
12730 CHECK_EQ(42, script->Run()->Int32Value());
12731 }
12732 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000012733 v8::Locker locker(CcTest::isolate());
12734 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012735 LocalContext env;
12736 Local<v8::FunctionTemplate> fun_templ =
12737 v8::FunctionTemplate::New(UnlockForAMoment);
12738 Local<Function> fun = fun_templ->GetFunction();
12739 env->Global()->Set(v8_str("unlock_for_a_moment"), fun);
12740 Local<Script> script = v8_compile("(function () {"
12741 " unlock_for_a_moment();"
12742 " return 42;"
12743 "})();");
12744 CHECK_EQ(42, script->Run()->Int32Value());
12745 }
12746}
12747
12748
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000012749static int GetGlobalObjectsCount() {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000012750 CcTest::heap()->EnsureHeapIsIterable();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012751 int count = 0;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000012752 i::HeapIterator it(CcTest::heap());
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000012753 for (i::HeapObject* object = it.next(); object != NULL; object = it.next())
12754 if (object->IsJSGlobalObject()) count++;
12755 return count;
12756}
12757
12758
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000012759static void CheckSurvivingGlobalObjectsCount(int expected) {
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +000012760 // We need to collect all garbage twice to be sure that everything
12761 // has been collected. This is because inline caches are cleared in
12762 // the first garbage collection but some of the maps have already
12763 // been marked at that point. Therefore some of the maps are not
12764 // collected until the second garbage collection.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000012765 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
12766 CcTest::heap()->CollectAllGarbage(i::Heap::kMakeHeapIterableMask);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000012767 int count = GetGlobalObjectsCount();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012768#ifdef DEBUG
machenbach@chromium.org528ce022013-09-23 14:09:36 +000012769 if (count != expected) CcTest::heap()->TracePathToGlobal();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012770#endif
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000012771 CHECK_EQ(expected, count);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012772}
12773
12774
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012775TEST(DontLeakGlobalObjects) {
12776 // Regression test for issues 1139850 and 1174891.
12777
kasperl@chromium.orgb9123622008-09-17 14:05:56 +000012778 v8::V8::Initialize();
ager@chromium.org9258b6b2008-09-11 09:11:10 +000012779
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012780 for (int i = 0; i < 5; i++) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000012781 { v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012782 LocalContext context;
12783 }
svenpanne@chromium.orgc859c4f2012-10-15 11:51:39 +000012784 v8::V8::ContextDisposedNotification();
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000012785 CheckSurvivingGlobalObjectsCount(0);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012786
machenbach@chromium.org528ce022013-09-23 14:09:36 +000012787 { v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012788 LocalContext context;
12789 v8_compile("Date")->Run();
12790 }
svenpanne@chromium.orgc859c4f2012-10-15 11:51:39 +000012791 v8::V8::ContextDisposedNotification();
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000012792 CheckSurvivingGlobalObjectsCount(0);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012793
machenbach@chromium.org528ce022013-09-23 14:09:36 +000012794 { v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012795 LocalContext context;
12796 v8_compile("/aaa/")->Run();
12797 }
svenpanne@chromium.orgc859c4f2012-10-15 11:51:39 +000012798 v8::V8::ContextDisposedNotification();
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000012799 CheckSurvivingGlobalObjectsCount(0);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012800
machenbach@chromium.org528ce022013-09-23 14:09:36 +000012801 { v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012802 const char* extension_list[] = { "v8/gc" };
12803 v8::ExtensionConfiguration extensions(1, extension_list);
12804 LocalContext context(&extensions);
12805 v8_compile("gc();")->Run();
12806 }
svenpanne@chromium.orgc859c4f2012-10-15 11:51:39 +000012807 v8::V8::ContextDisposedNotification();
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000012808 CheckSurvivingGlobalObjectsCount(0);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012809 }
12810}
12811
dslomov@chromium.org639bac02013-09-09 11:58:54 +000012812
12813TEST(CopyablePersistent) {
12814 LocalContext context;
12815 v8::Isolate* isolate = context->GetIsolate();
12816 i::GlobalHandles* globals =
12817 reinterpret_cast<i::Isolate*>(isolate)->global_handles();
12818 int initial_handles = globals->global_handles_count();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000012819 typedef v8::Persistent<v8::Object, v8::CopyablePersistentTraits<v8::Object> >
12820 CopyableObject;
dslomov@chromium.org639bac02013-09-09 11:58:54 +000012821 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000012822 CopyableObject handle1;
dslomov@chromium.org639bac02013-09-09 11:58:54 +000012823 {
12824 v8::HandleScope scope(isolate);
12825 handle1.Reset(isolate, v8::Object::New());
12826 }
12827 CHECK_EQ(initial_handles + 1, globals->global_handles_count());
machenbach@chromium.org528ce022013-09-23 14:09:36 +000012828 CopyableObject handle2;
dslomov@chromium.org639bac02013-09-09 11:58:54 +000012829 handle2 = handle1;
12830 CHECK(handle1 == handle2);
12831 CHECK_EQ(initial_handles + 2, globals->global_handles_count());
machenbach@chromium.org528ce022013-09-23 14:09:36 +000012832 CopyableObject handle3(handle2);
dslomov@chromium.org639bac02013-09-09 11:58:54 +000012833 CHECK(handle1 == handle3);
12834 CHECK_EQ(initial_handles + 3, globals->global_handles_count());
12835 }
12836 // Verify autodispose
hpayer@chromium.orgc5d49712013-09-11 08:25:48 +000012837 CHECK_EQ(initial_handles, globals->global_handles_count());
dslomov@chromium.org639bac02013-09-09 11:58:54 +000012838}
12839
12840
12841static void WeakApiCallback(
12842 const v8::WeakCallbackData<v8::Object, Persistent<v8::Object> >& data) {
12843 Local<Value> value = data.GetValue()->Get(v8_str("key"));
12844 CHECK_EQ(231, static_cast<int32_t>(Local<v8::Integer>::Cast(value)->Value()));
12845 data.GetParameter()->Reset();
12846 delete data.GetParameter();
12847}
12848
12849
12850TEST(WeakCallbackApi) {
12851 LocalContext context;
12852 v8::Isolate* isolate = context->GetIsolate();
12853 i::GlobalHandles* globals =
12854 reinterpret_cast<i::Isolate*>(isolate)->global_handles();
12855 int initial_handles = globals->global_handles_count();
12856 {
12857 v8::HandleScope scope(isolate);
12858 v8::Local<v8::Object> obj = v8::Object::New();
12859 obj->Set(v8_str("key"), v8::Integer::New(231, isolate));
12860 v8::Persistent<v8::Object>* handle =
12861 new v8::Persistent<v8::Object>(isolate, obj);
12862 handle->SetWeak<v8::Object, v8::Persistent<v8::Object> >(handle,
12863 WeakApiCallback);
12864 }
12865 reinterpret_cast<i::Isolate*>(isolate)->heap()->
12866 CollectAllGarbage(i::Heap::kNoGCFlags);
12867 // Verify disposed.
12868 CHECK_EQ(initial_handles, globals->global_handles_count());
12869}
12870
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012871
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000012872v8::Persistent<v8::Object> some_object;
12873v8::Persistent<v8::Object> bad_handle;
12874
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000012875void NewPersistentHandleCallback(v8::Isolate* isolate,
ulan@chromium.org57ff8812013-05-10 08:16:55 +000012876 v8::Persistent<v8::Value>* handle,
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000012877 void*) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000012878 v8::HandleScope scope(isolate);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000012879 bad_handle.Reset(isolate, some_object);
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000012880 handle->Dispose();
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000012881}
12882
12883
12884THREADED_TEST(NewPersistentHandleFromWeakCallback) {
12885 LocalContext context;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000012886 v8::Isolate* isolate = context->GetIsolate();
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000012887
12888 v8::Persistent<v8::Object> handle1, handle2;
12889 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000012890 v8::HandleScope scope(isolate);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000012891 some_object.Reset(isolate, v8::Object::New());
12892 handle1.Reset(isolate, v8::Object::New());
12893 handle2.Reset(isolate, v8::Object::New());
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000012894 }
12895 // Note: order is implementation dependent alas: currently
12896 // global handle nodes are processed by PostGarbageCollectionProcessing
12897 // in reverse allocation order, so if second allocated handle is deleted,
12898 // weak callback of the first handle would be able to 'reallocate' it.
danno@chromium.orgf95d4b92013-06-13 14:40:17 +000012899 handle1.MakeWeak<v8::Value, void>(NULL, NewPersistentHandleCallback);
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000012900 handle2.Dispose();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000012901 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000012902}
12903
12904
12905v8::Persistent<v8::Object> to_be_disposed;
12906
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000012907void DisposeAndForceGcCallback(v8::Isolate* isolate,
ulan@chromium.org57ff8812013-05-10 08:16:55 +000012908 v8::Persistent<v8::Value>* handle,
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000012909 void*) {
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000012910 to_be_disposed.Dispose();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000012911 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000012912 handle->Dispose();
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000012913}
12914
12915
12916THREADED_TEST(DoNotUseDeletedNodesInSecondLevelGc) {
12917 LocalContext context;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000012918 v8::Isolate* isolate = context->GetIsolate();
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000012919
12920 v8::Persistent<v8::Object> handle1, handle2;
12921 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000012922 v8::HandleScope scope(isolate);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000012923 handle1.Reset(isolate, v8::Object::New());
12924 handle2.Reset(isolate, v8::Object::New());
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000012925 }
danno@chromium.orgf95d4b92013-06-13 14:40:17 +000012926 handle1.MakeWeak<v8::Value, void>(NULL, DisposeAndForceGcCallback);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000012927 to_be_disposed.Reset(isolate, handle2);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000012928 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000012929}
12930
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000012931void DisposingCallback(v8::Isolate* isolate,
ulan@chromium.org57ff8812013-05-10 08:16:55 +000012932 v8::Persistent<v8::Value>* handle,
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000012933 void*) {
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000012934 handle->Dispose();
ager@chromium.orgc4c92722009-11-18 14:12:51 +000012935}
12936
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000012937void HandleCreatingCallback(v8::Isolate* isolate,
ulan@chromium.org57ff8812013-05-10 08:16:55 +000012938 v8::Persistent<v8::Value>* handle,
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000012939 void*) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000012940 v8::HandleScope scope(isolate);
danno@chromium.orgf95d4b92013-06-13 14:40:17 +000012941 v8::Persistent<v8::Object>(isolate, v8::Object::New());
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000012942 handle->Dispose();
ager@chromium.orgc4c92722009-11-18 14:12:51 +000012943}
12944
12945
12946THREADED_TEST(NoGlobalHandlesOrphaningDueToWeakCallback) {
12947 LocalContext context;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000012948 v8::Isolate* isolate = context->GetIsolate();
ager@chromium.orgc4c92722009-11-18 14:12:51 +000012949
12950 v8::Persistent<v8::Object> handle1, handle2, handle3;
12951 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000012952 v8::HandleScope scope(isolate);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000012953 handle3.Reset(isolate, v8::Object::New());
12954 handle2.Reset(isolate, v8::Object::New());
12955 handle1.Reset(isolate, v8::Object::New());
ager@chromium.orgc4c92722009-11-18 14:12:51 +000012956 }
danno@chromium.orgf95d4b92013-06-13 14:40:17 +000012957 handle2.MakeWeak<v8::Value, void>(NULL, DisposingCallback);
12958 handle3.MakeWeak<v8::Value, void>(NULL, HandleCreatingCallback);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000012959 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.orgc4c92722009-11-18 14:12:51 +000012960}
12961
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000012962
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012963THREADED_TEST(CheckForCrossContextObjectLiterals) {
kasperl@chromium.orgb9123622008-09-17 14:05:56 +000012964 v8::V8::Initialize();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012965
12966 const int nof = 2;
12967 const char* sources[nof] = {
12968 "try { [ 2, 3, 4 ].forEach(5); } catch(e) { e.toString(); }",
12969 "Object()"
12970 };
12971
12972 for (int i = 0; i < nof; i++) {
12973 const char* source = sources[i];
machenbach@chromium.org528ce022013-09-23 14:09:36 +000012974 { v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012975 LocalContext context;
12976 CompileRun(source);
12977 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +000012978 { v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012979 LocalContext context;
12980 CompileRun(source);
12981 }
12982 }
12983}
12984
12985
ulan@chromium.org57ff8812013-05-10 08:16:55 +000012986static v8::Handle<Value> NestedScope(v8::Local<Context> env) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000012987 v8::HandleScope inner(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012988 env->Enter();
12989 v8::Handle<Value> three = v8_num(3);
12990 v8::Handle<Value> value = inner.Close(three);
12991 env->Exit();
12992 return value;
12993}
12994
12995
12996THREADED_TEST(NestedHandleScopeAndContexts) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000012997 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000012998 v8::HandleScope outer(isolate);
12999 v8::Local<Context> env = Context::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013000 env->Enter();
13001 v8::Handle<Value> value = NestedScope(env);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000013002 v8::Handle<String> str(value->ToString());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000013003 CHECK(!str.IsEmpty());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013004 env->Exit();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013005}
13006
13007
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013008static bool MatchPointers(void* key1, void* key2) {
13009 return key1 == key2;
13010}
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013011
13012
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013013struct SymbolInfo {
13014 size_t id;
13015 size_t size;
13016 std::string name;
13017};
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013018
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013019
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013020class SetFunctionEntryHookTest {
13021 public:
13022 SetFunctionEntryHookTest() {
13023 CHECK(instance_ == NULL);
13024 instance_ = this;
13025 }
13026 ~SetFunctionEntryHookTest() {
13027 CHECK(instance_ == this);
13028 instance_ = NULL;
13029 }
13030 void Reset() {
13031 symbols_.clear();
13032 symbol_locations_.clear();
13033 invocations_.clear();
13034 }
13035 void RunTest();
13036 void OnJitEvent(const v8::JitCodeEvent* event);
13037 static void JitEvent(const v8::JitCodeEvent* event) {
13038 CHECK(instance_ != NULL);
13039 instance_->OnJitEvent(event);
13040 }
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013041
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013042 void OnEntryHook(uintptr_t function,
13043 uintptr_t return_addr_location);
13044 static void EntryHook(uintptr_t function,
13045 uintptr_t return_addr_location) {
13046 CHECK(instance_ != NULL);
13047 instance_->OnEntryHook(function, return_addr_location);
13048 }
ulan@chromium.orgdfe53072013-06-06 14:14:51 +000013049
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013050 static void RuntimeCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
13051 CHECK(instance_ != NULL);
13052 args.GetReturnValue().Set(v8_num(42));
13053 }
13054 void RunLoopInNewEnv(v8::Isolate* isolate);
13055
13056 // Records addr as location of symbol.
13057 void InsertSymbolAt(i::Address addr, SymbolInfo* symbol);
13058
13059 // Finds the symbol containing addr
13060 SymbolInfo* FindSymbolForAddr(i::Address addr);
13061 // Returns the number of invocations where the caller name contains
13062 // \p caller_name and the function name contains \p function_name.
13063 int CountInvocations(const char* caller_name,
13064 const char* function_name);
13065
13066 i::Handle<i::JSFunction> foo_func_;
13067 i::Handle<i::JSFunction> bar_func_;
13068
13069 typedef std::map<size_t, SymbolInfo> SymbolMap;
13070 typedef std::map<i::Address, SymbolInfo*> SymbolLocationMap;
13071 typedef std::map<std::pair<SymbolInfo*, SymbolInfo*>, int> InvocationMap;
13072 SymbolMap symbols_;
13073 SymbolLocationMap symbol_locations_;
13074 InvocationMap invocations_;
13075
13076 static SetFunctionEntryHookTest* instance_;
13077};
13078SetFunctionEntryHookTest* SetFunctionEntryHookTest::instance_ = NULL;
13079
13080
13081// Returns true if addr is in the range [start, start+len).
13082static bool Overlaps(i::Address start, size_t len, i::Address addr) {
13083 if (start <= addr && start + len > addr)
13084 return true;
13085
13086 return false;
13087}
13088
13089void SetFunctionEntryHookTest::InsertSymbolAt(i::Address addr,
13090 SymbolInfo* symbol) {
13091 // Insert the symbol at the new location.
13092 SymbolLocationMap::iterator it =
13093 symbol_locations_.insert(std::make_pair(addr, symbol)).first;
13094 // Now erase symbols to the left and right that overlap this one.
13095 while (it != symbol_locations_.begin()) {
13096 SymbolLocationMap::iterator left = it;
13097 --left;
13098 if (!Overlaps(left->first, left->second->size, addr))
13099 break;
13100 symbol_locations_.erase(left);
13101 }
13102
13103 // Now erase symbols to the left and right that overlap this one.
13104 while (true) {
13105 SymbolLocationMap::iterator right = it;
13106 ++right;
13107 if (right == symbol_locations_.end())
13108 break;
13109 if (!Overlaps(addr, symbol->size, right->first))
13110 break;
13111 symbol_locations_.erase(right);
ulan@chromium.orgdfe53072013-06-06 14:14:51 +000013112 }
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013113}
13114
13115
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013116void SetFunctionEntryHookTest::OnJitEvent(const v8::JitCodeEvent* event) {
13117 switch (event->type) {
13118 case v8::JitCodeEvent::CODE_ADDED: {
13119 CHECK(event->code_start != NULL);
13120 CHECK_NE(0, static_cast<int>(event->code_len));
13121 CHECK(event->name.str != NULL);
13122 size_t symbol_id = symbols_.size();
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013123
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013124 // Record the new symbol.
13125 SymbolInfo& info = symbols_[symbol_id];
13126 info.id = symbol_id;
13127 info.size = event->code_len;
13128 info.name.assign(event->name.str, event->name.str + event->name.len);
13129
13130 // And record it's location.
13131 InsertSymbolAt(reinterpret_cast<i::Address>(event->code_start), &info);
13132 }
13133 break;
13134
13135 case v8::JitCodeEvent::CODE_MOVED: {
13136 // We would like to never see code move that we haven't seen before,
13137 // but the code creation event does not happen until the line endings
13138 // have been calculated (this is so that we can report the line in the
13139 // script at which the function source is found, see
13140 // Compiler::RecordFunctionCompilation) and the line endings
13141 // calculations can cause a GC, which can move the newly created code
13142 // before its existence can be logged.
13143 SymbolLocationMap::iterator it(
13144 symbol_locations_.find(
13145 reinterpret_cast<i::Address>(event->code_start)));
13146 if (it != symbol_locations_.end()) {
13147 // Found a symbol at this location, move it.
13148 SymbolInfo* info = it->second;
13149 symbol_locations_.erase(it);
13150 InsertSymbolAt(reinterpret_cast<i::Address>(event->new_code_start),
13151 info);
13152 }
13153 }
13154 default:
13155 break;
13156 }
13157}
13158
13159void SetFunctionEntryHookTest::OnEntryHook(
13160 uintptr_t function, uintptr_t return_addr_location) {
13161 // Get the function's code object.
13162 i::Code* function_code = i::Code::GetCodeFromTargetAddress(
13163 reinterpret_cast<i::Address>(function));
13164 CHECK(function_code != NULL);
13165
13166 // Then try and look up the caller's code object.
13167 i::Address caller = *reinterpret_cast<i::Address*>(return_addr_location);
13168
13169 // Count the invocation.
13170 SymbolInfo* caller_symbol = FindSymbolForAddr(caller);
13171 SymbolInfo* function_symbol =
13172 FindSymbolForAddr(reinterpret_cast<i::Address>(function));
13173 ++invocations_[std::make_pair(caller_symbol, function_symbol)];
13174
13175 if (!bar_func_.is_null() && function_code == bar_func_->code()) {
13176 // Check that we have a symbol for the "bar" function at the right location.
13177 SymbolLocationMap::iterator it(
13178 symbol_locations_.find(function_code->instruction_start()));
13179 CHECK(it != symbol_locations_.end());
13180 }
13181
13182 if (!foo_func_.is_null() && function_code == foo_func_->code()) {
13183 // Check that we have a symbol for "foo" at the right location.
13184 SymbolLocationMap::iterator it(
13185 symbol_locations_.find(function_code->instruction_start()));
13186 CHECK(it != symbol_locations_.end());
13187 }
13188}
13189
13190
13191SymbolInfo* SetFunctionEntryHookTest::FindSymbolForAddr(i::Address addr) {
13192 SymbolLocationMap::iterator it(symbol_locations_.lower_bound(addr));
13193 // Do we have a direct hit on a symbol?
13194 if (it != symbol_locations_.end()) {
13195 if (it->first == addr)
13196 return it->second;
13197 }
13198
13199 // If not a direct hit, it'll have to be the previous symbol.
13200 if (it == symbol_locations_.begin())
13201 return NULL;
13202
13203 --it;
13204 size_t offs = addr - it->first;
13205 if (offs < it->second->size)
13206 return it->second;
13207
13208 return NULL;
13209}
13210
13211
13212int SetFunctionEntryHookTest::CountInvocations(
13213 const char* caller_name, const char* function_name) {
13214 InvocationMap::iterator it(invocations_.begin());
13215 int invocations = 0;
13216 for (; it != invocations_.end(); ++it) {
13217 SymbolInfo* caller = it->first.first;
13218 SymbolInfo* function = it->first.second;
13219
13220 // Filter out non-matching functions.
13221 if (function_name != NULL) {
13222 if (function->name.find(function_name) == std::string::npos)
13223 continue;
13224 }
13225
13226 // Filter out non-matching callers.
13227 if (caller_name != NULL) {
13228 if (caller == NULL)
13229 continue;
13230 if (caller->name.find(caller_name) == std::string::npos)
13231 continue;
13232 }
13233
13234 // It matches add the invocation count to the tally.
13235 invocations += it->second;
13236 }
13237
13238 return invocations;
13239}
13240
13241
13242void SetFunctionEntryHookTest::RunLoopInNewEnv(v8::Isolate* isolate) {
ulan@chromium.org57ff8812013-05-10 08:16:55 +000013243 v8::HandleScope outer(isolate);
13244 v8::Local<Context> env = Context::New(isolate);
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013245 env->Enter();
13246
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013247 Local<ObjectTemplate> t = ObjectTemplate::New();
13248 t->Set(v8_str("asdf"), v8::FunctionTemplate::New(RuntimeCallback));
13249 env->Global()->Set(v8_str("obj"), t->NewInstance());
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013250
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013251 const char* script =
13252 "function bar() {\n"
13253 " var sum = 0;\n"
13254 " for (i = 0; i < 100; ++i)\n"
13255 " sum = foo(i);\n"
13256 " return sum;\n"
13257 "}\n"
13258 "function foo(i) { return i * i; }\n"
13259 "// Invoke on the runtime function.\n"
13260 "obj.asdf()";
13261 CompileRun(script);
13262 bar_func_ = i::Handle<i::JSFunction>::cast(
13263 v8::Utils::OpenHandle(*env->Global()->Get(v8_str("bar"))));
13264 ASSERT(!bar_func_.is_null());
13265
13266 foo_func_ =
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013267 i::Handle<i::JSFunction>::cast(
13268 v8::Utils::OpenHandle(*env->Global()->Get(v8_str("foo"))));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013269 ASSERT(!foo_func_.is_null());
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013270
13271 v8::Handle<v8::Value> value = CompileRun("bar();");
13272 CHECK(value->IsNumber());
13273 CHECK_EQ(9801.0, v8::Number::Cast(*value)->Value());
13274
13275 // Test the optimized codegen path.
13276 value = CompileRun("%OptimizeFunctionOnNextCall(foo);"
13277 "bar();");
13278 CHECK(value->IsNumber());
13279 CHECK_EQ(9801.0, v8::Number::Cast(*value)->Value());
13280
13281 env->Exit();
13282}
13283
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000013284
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013285void SetFunctionEntryHookTest::RunTest() {
13286 // Work in a new isolate throughout.
13287 v8::Isolate* isolate = v8::Isolate::New();
13288
13289 // Test setting the entry hook on the new isolate.
13290 CHECK(v8::V8::SetFunctionEntryHook(isolate, EntryHook));
13291
13292 // Replacing the hook, once set should fail.
13293 CHECK_EQ(false, v8::V8::SetFunctionEntryHook(isolate, EntryHook));
13294
13295 {
13296 v8::Isolate::Scope scope(isolate);
13297
13298 v8::V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault, JitEvent);
13299
13300 RunLoopInNewEnv(isolate);
13301
13302 // Check the exepected invocation counts.
13303 CHECK_EQ(2, CountInvocations(NULL, "bar"));
13304 CHECK_EQ(200, CountInvocations("bar", "foo"));
13305 CHECK_EQ(200, CountInvocations(NULL, "foo"));
13306
13307 // Verify that we have an entry hook on some specific stubs.
13308 CHECK_NE(0, CountInvocations(NULL, "CEntryStub"));
13309 CHECK_NE(0, CountInvocations(NULL, "JSEntryStub"));
13310 CHECK_NE(0, CountInvocations(NULL, "JSEntryTrampoline"));
13311 }
13312 isolate->Dispose();
13313
13314 Reset();
13315
13316 // Make sure a second isolate is unaffected by the previous entry hook.
13317 isolate = v8::Isolate::New();
13318 {
13319 v8::Isolate::Scope scope(isolate);
13320
13321 // Reset the entry count to zero and set the entry hook.
13322 RunLoopInNewEnv(isolate);
13323
13324 // We should record no invocations in this isolate.
13325 CHECK_EQ(0, static_cast<int>(invocations_.size()));
13326 }
13327 // Since the isolate has been used, we shouldn't be able to set an entry
13328 // hook anymore.
13329 CHECK_EQ(false, v8::V8::SetFunctionEntryHook(isolate, EntryHook));
13330
13331 isolate->Dispose();
13332}
13333
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013334
13335TEST(SetFunctionEntryHook) {
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000013336 // FunctionEntryHook does not work well with experimental natives.
13337 // Experimental natives are compiled during snapshot deserialization.
13338 // This test breaks because InstallGetter (function from snapshot that
13339 // only gets called from experimental natives) is compiled with entry hooks.
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013340 i::FLAG_allow_natives_syntax = true;
yangguo@chromium.orgfb377212012-11-16 14:43:43 +000013341 i::FLAG_use_inlining = false;
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013342
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013343 SetFunctionEntryHookTest test;
13344 test.RunTest();
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013345}
13346
13347
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000013348static i::HashMap* code_map = NULL;
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +000013349static i::HashMap* jitcode_line_info = NULL;
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000013350static int saw_bar = 0;
13351static int move_events = 0;
13352
13353
13354static bool FunctionNameIs(const char* expected,
13355 const v8::JitCodeEvent* event) {
13356 // Log lines for functions are of the general form:
13357 // "LazyCompile:<type><function_name>", where the type is one of
13358 // "*", "~" or "".
13359 static const char kPreamble[] = "LazyCompile:";
13360 static size_t kPreambleLen = sizeof(kPreamble) - 1;
13361
13362 if (event->name.len < sizeof(kPreamble) - 1 ||
13363 strncmp(kPreamble, event->name.str, kPreambleLen) != 0) {
13364 return false;
13365 }
13366
13367 const char* tail = event->name.str + kPreambleLen;
13368 size_t tail_len = event->name.len - kPreambleLen;
13369 size_t expected_len = strlen(expected);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000013370 if (tail_len > 1 && (*tail == '*' || *tail == '~')) {
13371 --tail_len;
13372 ++tail;
13373 }
13374
13375 // Check for tails like 'bar :1'.
13376 if (tail_len > expected_len + 2 &&
13377 tail[expected_len] == ' ' &&
13378 tail[expected_len + 1] == ':' &&
13379 tail[expected_len + 2] &&
13380 !strncmp(tail, expected, expected_len)) {
13381 return true;
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000013382 }
13383
13384 if (tail_len != expected_len)
13385 return false;
13386
13387 return strncmp(tail, expected, expected_len) == 0;
13388}
13389
13390
13391static void event_handler(const v8::JitCodeEvent* event) {
13392 CHECK(event != NULL);
13393 CHECK(code_map != NULL);
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +000013394 CHECK(jitcode_line_info != NULL);
13395
13396 class DummyJitCodeLineInfo {
13397 };
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000013398
13399 switch (event->type) {
13400 case v8::JitCodeEvent::CODE_ADDED: {
13401 CHECK(event->code_start != NULL);
13402 CHECK_NE(0, static_cast<int>(event->code_len));
13403 CHECK(event->name.str != NULL);
13404 i::HashMap::Entry* entry =
13405 code_map->Lookup(event->code_start,
13406 i::ComputePointerHash(event->code_start),
13407 true);
13408 entry->value = reinterpret_cast<void*>(event->code_len);
13409
13410 if (FunctionNameIs("bar", event)) {
13411 ++saw_bar;
13412 }
13413 }
13414 break;
13415
13416 case v8::JitCodeEvent::CODE_MOVED: {
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000013417 uint32_t hash = i::ComputePointerHash(event->code_start);
jkummerow@chromium.org78502a92012-09-06 13:50:42 +000013418 // We would like to never see code move that we haven't seen before,
13419 // but the code creation event does not happen until the line endings
13420 // have been calculated (this is so that we can report the line in the
13421 // script at which the function source is found, see
13422 // Compiler::RecordFunctionCompilation) and the line endings
13423 // calculations can cause a GC, which can move the newly created code
13424 // before its existence can be logged.
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000013425 i::HashMap::Entry* entry =
13426 code_map->Lookup(event->code_start, hash, false);
jkummerow@chromium.org78502a92012-09-06 13:50:42 +000013427 if (entry != NULL) {
13428 ++move_events;
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000013429
jkummerow@chromium.org78502a92012-09-06 13:50:42 +000013430 CHECK_EQ(reinterpret_cast<void*>(event->code_len), entry->value);
13431 code_map->Remove(event->code_start, hash);
13432
13433 entry = code_map->Lookup(event->new_code_start,
13434 i::ComputePointerHash(event->new_code_start),
13435 true);
13436 CHECK(entry != NULL);
13437 entry->value = reinterpret_cast<void*>(event->code_len);
13438 }
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000013439 }
13440 break;
13441
13442 case v8::JitCodeEvent::CODE_REMOVED:
13443 // Object/code removal events are currently not dispatched from the GC.
13444 CHECK(false);
13445 break;
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +000013446
13447 // For CODE_START_LINE_INFO_RECORDING event, we will create one
13448 // DummyJitCodeLineInfo data structure pointed by event->user_dat. We
13449 // record it in jitcode_line_info.
13450 case v8::JitCodeEvent::CODE_START_LINE_INFO_RECORDING: {
13451 DummyJitCodeLineInfo* line_info = new DummyJitCodeLineInfo();
13452 v8::JitCodeEvent* temp_event = const_cast<v8::JitCodeEvent*>(event);
13453 temp_event->user_data = line_info;
13454 i::HashMap::Entry* entry =
13455 jitcode_line_info->Lookup(line_info,
13456 i::ComputePointerHash(line_info),
13457 true);
13458 entry->value = reinterpret_cast<void*>(line_info);
13459 }
13460 break;
13461 // For these two events, we will check whether the event->user_data
13462 // data structure is created before during CODE_START_LINE_INFO_RECORDING
13463 // event. And delete it in CODE_END_LINE_INFO_RECORDING event handling.
13464 case v8::JitCodeEvent::CODE_END_LINE_INFO_RECORDING: {
13465 CHECK(event->user_data != NULL);
13466 uint32_t hash = i::ComputePointerHash(event->user_data);
13467 i::HashMap::Entry* entry =
13468 jitcode_line_info->Lookup(event->user_data, hash, false);
13469 CHECK(entry != NULL);
13470 delete reinterpret_cast<DummyJitCodeLineInfo*>(event->user_data);
13471 }
13472 break;
13473
13474 case v8::JitCodeEvent::CODE_ADD_LINE_POS_INFO: {
13475 CHECK(event->user_data != NULL);
13476 uint32_t hash = i::ComputePointerHash(event->user_data);
13477 i::HashMap::Entry* entry =
13478 jitcode_line_info->Lookup(event->user_data, hash, false);
13479 CHECK(entry != NULL);
13480 }
13481 break;
13482
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000013483 default:
13484 // Impossible event.
13485 CHECK(false);
13486 break;
13487 }
13488}
13489
13490
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013491UNINITIALIZED_TEST(SetJitCodeEventHandler) {
ulan@chromium.org6ba1fd02013-02-14 14:56:11 +000013492 i::FLAG_stress_compaction = true;
danno@chromium.orgf005df62013-04-30 16:36:45 +000013493 i::FLAG_incremental_marking = false;
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000013494 const char* script =
13495 "function bar() {"
13496 " var sum = 0;"
13497 " for (i = 0; i < 100; ++i)"
13498 " sum = foo(i);"
13499 " return sum;"
13500 "}"
13501 "function foo(i) { return i * i; };"
13502 "bar();";
13503
13504 // Run this test in a new isolate to make sure we don't
13505 // have remnants of state from other code.
13506 v8::Isolate* isolate = v8::Isolate::New();
13507 isolate->Enter();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013508 i::Heap* heap = reinterpret_cast<i::Isolate*>(isolate)->heap();
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000013509
13510 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013511 v8::HandleScope scope(isolate);
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000013512 i::HashMap code(MatchPointers);
13513 code_map = &code;
13514
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +000013515 i::HashMap lineinfo(MatchPointers);
13516 jitcode_line_info = &lineinfo;
13517
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000013518 saw_bar = 0;
13519 move_events = 0;
13520
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000013521 V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault, event_handler);
13522
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000013523 // Generate new code objects sparsely distributed across several
13524 // different fragmented code-space pages.
13525 const int kIterations = 10;
13526 for (int i = 0; i < kIterations; ++i) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013527 LocalContext env(isolate);
ulan@chromium.org6ba1fd02013-02-14 14:56:11 +000013528 i::AlwaysAllocateScope always_allocate;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013529 SimulateFullSpace(heap->code_space());
ulan@chromium.org6ba1fd02013-02-14 14:56:11 +000013530 CompileRun(script);
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000013531
ulan@chromium.org6ba1fd02013-02-14 14:56:11 +000013532 // Keep a strong reference to the code object in the handle scope.
13533 i::Handle<i::Code> bar_code(i::Handle<i::JSFunction>::cast(
13534 v8::Utils::OpenHandle(*env->Global()->Get(v8_str("bar"))))->code());
13535 i::Handle<i::Code> foo_code(i::Handle<i::JSFunction>::cast(
13536 v8::Utils::OpenHandle(*env->Global()->Get(v8_str("foo"))))->code());
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000013537
13538 // Clear the compilation cache to get more wastage.
hpayer@chromium.orgc5d49712013-09-11 08:25:48 +000013539 reinterpret_cast<i::Isolate*>(isolate)->compilation_cache()->Clear();
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000013540 }
13541
13542 // Force code movement.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013543 heap->CollectAllAvailableGarbage("TestSetJitCodeEventHandler");
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000013544
ulan@chromium.org6ba1fd02013-02-14 14:56:11 +000013545 V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault, NULL);
13546
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000013547 CHECK_LE(kIterations, saw_bar);
ulan@chromium.org6ba1fd02013-02-14 14:56:11 +000013548 CHECK_LT(0, move_events);
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000013549
13550 code_map = NULL;
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +000013551 jitcode_line_info = NULL;
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000013552 }
13553
13554 isolate->Exit();
13555 isolate->Dispose();
13556
13557 // Do this in a new isolate.
13558 isolate = v8::Isolate::New();
13559 isolate->Enter();
13560
13561 // Verify that we get callbacks for existing code objects when we
13562 // request enumeration of existing code.
13563 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013564 v8::HandleScope scope(isolate);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013565 LocalContext env(isolate);
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000013566 CompileRun(script);
13567
13568 // Now get code through initial iteration.
13569 i::HashMap code(MatchPointers);
13570 code_map = &code;
13571
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +000013572 i::HashMap lineinfo(MatchPointers);
13573 jitcode_line_info = &lineinfo;
13574
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000013575 V8::SetJitCodeEventHandler(v8::kJitCodeEventEnumExisting, event_handler);
13576 V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault, NULL);
13577
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +000013578 jitcode_line_info = NULL;
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000013579 // We expect that we got some events. Note that if we could get code removal
13580 // notifications, we could compare two collections, one created by listening
13581 // from the time of creation of an isolate, and the other by subscribing
13582 // with EnumExisting.
ulan@chromium.org6ba1fd02013-02-14 14:56:11 +000013583 CHECK_LT(0, code.occupancy());
13584
13585 code_map = NULL;
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000013586 }
13587
13588 isolate->Exit();
13589 isolate->Dispose();
13590}
13591
13592
jkummerow@chromium.org28faa982012-04-13 09:58:30 +000013593static int64_t cast(intptr_t x) { return static_cast<int64_t>(x); }
13594
13595
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013596THREADED_TEST(ExternalAllocatedMemory) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013597 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000013598 v8::HandleScope outer(isolate);
13599 v8::Local<Context> env(Context::New(isolate));
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000013600 CHECK(!env.IsEmpty());
jkummerow@chromium.org28faa982012-04-13 09:58:30 +000013601 const intptr_t kSize = 1024*1024;
danno@chromium.orgf005df62013-04-30 16:36:45 +000013602 int64_t baseline = cast(isolate->AdjustAmountOfExternalAllocatedMemory(0));
13603 CHECK_EQ(baseline + cast(kSize),
13604 cast(isolate->AdjustAmountOfExternalAllocatedMemory(kSize)));
13605 CHECK_EQ(baseline,
13606 cast(isolate->AdjustAmountOfExternalAllocatedMemory(-kSize)));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013607}
13608
13609
ager@chromium.org9258b6b2008-09-11 09:11:10 +000013610// Regression test for issue 54, object templates with internal fields
13611// but no accessors or interceptors did not get their internal field
13612// count set on instances.
13613THREADED_TEST(Regress54) {
ager@chromium.org9258b6b2008-09-11 09:11:10 +000013614 LocalContext context;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000013615 v8::Isolate* isolate = context->GetIsolate();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013616 v8::HandleScope outer(isolate);
ager@chromium.org9258b6b2008-09-11 09:11:10 +000013617 static v8::Persistent<v8::ObjectTemplate> templ;
13618 if (templ.IsEmpty()) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013619 v8::HandleScope inner(isolate);
ager@chromium.org9258b6b2008-09-11 09:11:10 +000013620 v8::Handle<v8::ObjectTemplate> local = v8::ObjectTemplate::New();
13621 local->SetInternalFieldCount(1);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000013622 templ.Reset(isolate, inner.Close(local));
ager@chromium.org9258b6b2008-09-11 09:11:10 +000013623 }
rossberg@chromium.org79e79022013-06-03 15:43:46 +000013624 v8::Handle<v8::Object> result =
13625 v8::Local<v8::ObjectTemplate>::New(isolate, templ)->NewInstance();
ager@chromium.org9258b6b2008-09-11 09:11:10 +000013626 CHECK_EQ(1, result->InternalFieldCount());
13627}
13628
13629
13630// If part of the threaded tests, this test makes ThreadingTest fail
13631// on mac.
13632TEST(CatchStackOverflow) {
ager@chromium.org9258b6b2008-09-11 09:11:10 +000013633 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013634 v8::HandleScope scope(context->GetIsolate());
ager@chromium.org9258b6b2008-09-11 09:11:10 +000013635 v8::TryCatch try_catch;
13636 v8::Handle<v8::Script> script = v8::Script::Compile(v8::String::New(
13637 "function f() {"
13638 " return f();"
13639 "}"
13640 ""
13641 "f();"));
13642 v8::Handle<v8::Value> result = script->Run();
13643 CHECK(result.IsEmpty());
13644}
13645
13646
kasperl@chromium.org7be3c992009-03-12 07:19:55 +000013647static void CheckTryCatchSourceInfo(v8::Handle<v8::Script> script,
13648 const char* resource_name,
13649 int line_offset) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013650 v8::HandleScope scope(CcTest::isolate());
kasperl@chromium.org7be3c992009-03-12 07:19:55 +000013651 v8::TryCatch try_catch;
13652 v8::Handle<v8::Value> result = script->Run();
13653 CHECK(result.IsEmpty());
13654 CHECK(try_catch.HasCaught());
13655 v8::Handle<v8::Message> message = try_catch.Message();
13656 CHECK(!message.IsEmpty());
13657 CHECK_EQ(10 + line_offset, message->GetLineNumber());
13658 CHECK_EQ(91, message->GetStartPosition());
13659 CHECK_EQ(92, message->GetEndPosition());
13660 CHECK_EQ(2, message->GetStartColumn());
13661 CHECK_EQ(3, message->GetEndColumn());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000013662 v8::String::Utf8Value line(message->GetSourceLine());
kasperl@chromium.org7be3c992009-03-12 07:19:55 +000013663 CHECK_EQ(" throw 'nirk';", *line);
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000013664 v8::String::Utf8Value name(message->GetScriptResourceName());
kasperl@chromium.org7be3c992009-03-12 07:19:55 +000013665 CHECK_EQ(resource_name, *name);
13666}
13667
13668
ager@chromium.org9258b6b2008-09-11 09:11:10 +000013669THREADED_TEST(TryCatchSourceInfo) {
ager@chromium.org9258b6b2008-09-11 09:11:10 +000013670 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013671 v8::HandleScope scope(context->GetIsolate());
ager@chromium.org9258b6b2008-09-11 09:11:10 +000013672 v8::Handle<v8::String> source = v8::String::New(
13673 "function Foo() {\n"
13674 " return Bar();\n"
13675 "}\n"
13676 "\n"
13677 "function Bar() {\n"
13678 " return Baz();\n"
13679 "}\n"
13680 "\n"
13681 "function Baz() {\n"
13682 " throw 'nirk';\n"
13683 "}\n"
13684 "\n"
13685 "Foo();\n");
kasperl@chromium.org7be3c992009-03-12 07:19:55 +000013686
13687 const char* resource_name;
13688 v8::Handle<v8::Script> script;
13689 resource_name = "test.js";
13690 script = v8::Script::Compile(source, v8::String::New(resource_name));
13691 CheckTryCatchSourceInfo(script, resource_name, 0);
13692
13693 resource_name = "test1.js";
13694 v8::ScriptOrigin origin1(v8::String::New(resource_name));
13695 script = v8::Script::Compile(source, &origin1);
13696 CheckTryCatchSourceInfo(script, resource_name, 0);
13697
13698 resource_name = "test2.js";
13699 v8::ScriptOrigin origin2(v8::String::New(resource_name), v8::Integer::New(7));
13700 script = v8::Script::Compile(source, &origin2);
13701 CheckTryCatchSourceInfo(script, resource_name, 7);
ager@chromium.org9258b6b2008-09-11 09:11:10 +000013702}
kasperl@chromium.orgb9123622008-09-17 14:05:56 +000013703
13704
13705THREADED_TEST(CompilationCache) {
kasperl@chromium.orgb9123622008-09-17 14:05:56 +000013706 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013707 v8::HandleScope scope(context->GetIsolate());
kasperl@chromium.orgb9123622008-09-17 14:05:56 +000013708 v8::Handle<v8::String> source0 = v8::String::New("1234");
13709 v8::Handle<v8::String> source1 = v8::String::New("1234");
13710 v8::Handle<v8::Script> script0 =
13711 v8::Script::Compile(source0, v8::String::New("test.js"));
13712 v8::Handle<v8::Script> script1 =
13713 v8::Script::Compile(source1, v8::String::New("test.js"));
13714 v8::Handle<v8::Script> script2 =
13715 v8::Script::Compile(source0); // different origin
13716 CHECK_EQ(1234, script0->Run()->Int32Value());
13717 CHECK_EQ(1234, script1->Run()->Int32Value());
13718 CHECK_EQ(1234, script2->Run()->Int32Value());
13719}
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000013720
13721
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013722static void FunctionNameCallback(
13723 const v8::FunctionCallbackInfo<v8::Value>& args) {
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000013724 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013725 args.GetReturnValue().Set(v8_num(42));
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000013726}
13727
13728
13729THREADED_TEST(CallbackFunctionName) {
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000013730 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013731 v8::HandleScope scope(context->GetIsolate());
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000013732 Local<ObjectTemplate> t = ObjectTemplate::New();
13733 t->Set(v8_str("asdf"), v8::FunctionTemplate::New(FunctionNameCallback));
13734 context->Global()->Set(v8_str("obj"), t->NewInstance());
13735 v8::Handle<v8::Value> value = CompileRun("obj.asdf.name");
13736 CHECK(value->IsString());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000013737 v8::String::Utf8Value name(value);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000013738 CHECK_EQ("asdf", *name);
13739}
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000013740
13741
13742THREADED_TEST(DateAccess) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000013743 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013744 v8::HandleScope scope(context->GetIsolate());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000013745 v8::Handle<v8::Value> date = v8::Date::New(1224744689038.0);
13746 CHECK(date->IsDate());
danno@chromium.orgd3c42102013-08-01 16:58:23 +000013747 CHECK_EQ(1224744689038.0, date.As<v8::Date>()->ValueOf());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000013748}
13749
13750
13751void CheckProperties(v8::Handle<v8::Value> val, int elmc, const char* elmv[]) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000013752 v8::Handle<v8::Object> obj = val.As<v8::Object>();
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000013753 v8::Handle<v8::Array> props = obj->GetPropertyNames();
13754 CHECK_EQ(elmc, props->Length());
13755 for (int i = 0; i < elmc; i++) {
13756 v8::String::Utf8Value elm(props->Get(v8::Integer::New(i)));
13757 CHECK_EQ(elmv[i], *elm);
13758 }
13759}
13760
13761
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000013762void CheckOwnProperties(v8::Handle<v8::Value> val,
13763 int elmc,
13764 const char* elmv[]) {
13765 v8::Handle<v8::Object> obj = val.As<v8::Object>();
13766 v8::Handle<v8::Array> props = obj->GetOwnPropertyNames();
13767 CHECK_EQ(elmc, props->Length());
13768 for (int i = 0; i < elmc; i++) {
13769 v8::String::Utf8Value elm(props->Get(v8::Integer::New(i)));
13770 CHECK_EQ(elmv[i], *elm);
13771 }
13772}
13773
13774
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000013775THREADED_TEST(PropertyEnumeration) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000013776 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013777 v8::HandleScope scope(context->GetIsolate());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000013778 v8::Handle<v8::Value> obj = v8::Script::Compile(v8::String::New(
13779 "var result = [];"
13780 "result[0] = {};"
13781 "result[1] = {a: 1, b: 2};"
13782 "result[2] = [1, 2, 3];"
13783 "var proto = {x: 1, y: 2, z: 3};"
13784 "var x = { __proto__: proto, w: 0, z: 1 };"
13785 "result[3] = x;"
13786 "result;"))->Run();
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000013787 v8::Handle<v8::Array> elms = obj.As<v8::Array>();
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000013788 CHECK_EQ(4, elms->Length());
13789 int elmc0 = 0;
13790 const char** elmv0 = NULL;
13791 CheckProperties(elms->Get(v8::Integer::New(0)), elmc0, elmv0);
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000013792 CheckOwnProperties(elms->Get(v8::Integer::New(0)), elmc0, elmv0);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000013793 int elmc1 = 2;
13794 const char* elmv1[] = {"a", "b"};
13795 CheckProperties(elms->Get(v8::Integer::New(1)), elmc1, elmv1);
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000013796 CheckOwnProperties(elms->Get(v8::Integer::New(1)), elmc1, elmv1);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000013797 int elmc2 = 3;
13798 const char* elmv2[] = {"0", "1", "2"};
13799 CheckProperties(elms->Get(v8::Integer::New(2)), elmc2, elmv2);
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000013800 CheckOwnProperties(elms->Get(v8::Integer::New(2)), elmc2, elmv2);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000013801 int elmc3 = 4;
13802 const char* elmv3[] = {"w", "z", "x", "y"};
13803 CheckProperties(elms->Get(v8::Integer::New(3)), elmc3, elmv3);
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000013804 int elmc4 = 2;
13805 const char* elmv4[] = {"w", "z"};
13806 CheckOwnProperties(elms->Get(v8::Integer::New(3)), elmc4, elmv4);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000013807}
ager@chromium.org870a0b62008-11-04 11:43:05 +000013808
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000013809
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000013810THREADED_TEST(PropertyEnumeration2) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000013811 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013812 v8::HandleScope scope(context->GetIsolate());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000013813 v8::Handle<v8::Value> obj = v8::Script::Compile(v8::String::New(
13814 "var result = [];"
13815 "result[0] = {};"
13816 "result[1] = {a: 1, b: 2};"
13817 "result[2] = [1, 2, 3];"
13818 "var proto = {x: 1, y: 2, z: 3};"
13819 "var x = { __proto__: proto, w: 0, z: 1 };"
13820 "result[3] = x;"
13821 "result;"))->Run();
13822 v8::Handle<v8::Array> elms = obj.As<v8::Array>();
13823 CHECK_EQ(4, elms->Length());
13824 int elmc0 = 0;
13825 const char** elmv0 = NULL;
13826 CheckProperties(elms->Get(v8::Integer::New(0)), elmc0, elmv0);
13827
13828 v8::Handle<v8::Value> val = elms->Get(v8::Integer::New(0));
13829 v8::Handle<v8::Array> props = val.As<v8::Object>()->GetPropertyNames();
13830 CHECK_EQ(0, props->Length());
13831 for (uint32_t i = 0; i < props->Length(); i++) {
13832 printf("p[%d]\n", i);
13833 }
13834}
ager@chromium.org870a0b62008-11-04 11:43:05 +000013835
ager@chromium.org870a0b62008-11-04 11:43:05 +000013836static bool NamedSetAccessBlocker(Local<v8::Object> obj,
13837 Local<Value> name,
13838 v8::AccessType type,
13839 Local<Value> data) {
13840 return type != v8::ACCESS_SET;
13841}
13842
13843
13844static bool IndexedSetAccessBlocker(Local<v8::Object> obj,
13845 uint32_t key,
13846 v8::AccessType type,
13847 Local<Value> data) {
13848 return type != v8::ACCESS_SET;
13849}
13850
13851
13852THREADED_TEST(DisableAccessChecksWhileConfiguring) {
ager@chromium.org870a0b62008-11-04 11:43:05 +000013853 LocalContext context;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000013854 v8::Isolate* isolate = context->GetIsolate();
13855 v8::HandleScope scope(isolate);
ager@chromium.org870a0b62008-11-04 11:43:05 +000013856 Local<ObjectTemplate> templ = ObjectTemplate::New();
13857 templ->SetAccessCheckCallbacks(NamedSetAccessBlocker,
13858 IndexedSetAccessBlocker);
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000013859 templ->Set(v8_str("x"), v8::True(isolate));
ager@chromium.org870a0b62008-11-04 11:43:05 +000013860 Local<v8::Object> instance = templ->NewInstance();
13861 context->Global()->Set(v8_str("obj"), instance);
13862 Local<Value> value = CompileRun("obj.x");
13863 CHECK(value->BooleanValue());
13864}
ager@chromium.orga74f0da2008-12-03 16:05:52 +000013865
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000013866
ager@chromium.org32912102009-01-16 10:38:43 +000013867static bool NamedGetAccessBlocker(Local<v8::Object> obj,
13868 Local<Value> name,
13869 v8::AccessType type,
13870 Local<Value> data) {
13871 return false;
13872}
13873
13874
13875static bool IndexedGetAccessBlocker(Local<v8::Object> obj,
13876 uint32_t key,
13877 v8::AccessType type,
13878 Local<Value> data) {
13879 return false;
13880}
13881
13882
13883
13884THREADED_TEST(AccessChecksReenabledCorrectly) {
ager@chromium.org32912102009-01-16 10:38:43 +000013885 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013886 v8::HandleScope scope(context->GetIsolate());
ager@chromium.org32912102009-01-16 10:38:43 +000013887 Local<ObjectTemplate> templ = ObjectTemplate::New();
13888 templ->SetAccessCheckCallbacks(NamedGetAccessBlocker,
13889 IndexedGetAccessBlocker);
13890 templ->Set(v8_str("a"), v8_str("a"));
13891 // Add more than 8 (see kMaxFastProperties) properties
13892 // so that the constructor will force copying map.
13893 // Cannot sprintf, gcc complains unsafety.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000013894 char buf[4];
ager@chromium.org32912102009-01-16 10:38:43 +000013895 for (char i = '0'; i <= '9' ; i++) {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000013896 buf[0] = i;
ager@chromium.org32912102009-01-16 10:38:43 +000013897 for (char j = '0'; j <= '9'; j++) {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000013898 buf[1] = j;
ager@chromium.org32912102009-01-16 10:38:43 +000013899 for (char k = '0'; k <= '9'; k++) {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000013900 buf[2] = k;
13901 buf[3] = 0;
ager@chromium.org32912102009-01-16 10:38:43 +000013902 templ->Set(v8_str(buf), v8::Number::New(k));
13903 }
13904 }
13905 }
13906
13907 Local<v8::Object> instance_1 = templ->NewInstance();
13908 context->Global()->Set(v8_str("obj_1"), instance_1);
13909
13910 Local<Value> value_1 = CompileRun("obj_1.a");
13911 CHECK(value_1->IsUndefined());
13912
13913 Local<v8::Object> instance_2 = templ->NewInstance();
13914 context->Global()->Set(v8_str("obj_2"), instance_2);
13915
13916 Local<Value> value_2 = CompileRun("obj_2.a");
13917 CHECK(value_2->IsUndefined());
13918}
ager@chromium.orga74f0da2008-12-03 16:05:52 +000013919
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000013920
ager@chromium.org8bb60582008-12-11 12:02:20 +000013921// This tests that access check information remains on the global
13922// object template when creating contexts.
13923THREADED_TEST(AccessControlRepeatedContextCreation) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013924 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000013925 v8::HandleScope handle_scope(isolate);
ager@chromium.org8bb60582008-12-11 12:02:20 +000013926 v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
13927 global_template->SetAccessCheckCallbacks(NamedSetAccessBlocker,
13928 IndexedSetAccessBlocker);
13929 i::Handle<i::ObjectTemplateInfo> internal_template =
13930 v8::Utils::OpenHandle(*global_template);
13931 CHECK(!internal_template->constructor()->IsUndefined());
13932 i::Handle<i::FunctionTemplateInfo> constructor(
13933 i::FunctionTemplateInfo::cast(internal_template->constructor()));
13934 CHECK(!constructor->access_check_info()->IsUndefined());
ulan@chromium.org57ff8812013-05-10 08:16:55 +000013935 v8::Local<Context> context0(Context::New(isolate, NULL, global_template));
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000013936 CHECK(!context0.IsEmpty());
ager@chromium.org8bb60582008-12-11 12:02:20 +000013937 CHECK(!constructor->access_check_info()->IsUndefined());
13938}
13939
13940
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000013941THREADED_TEST(TurnOnAccessCheck) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013942 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000013943 v8::HandleScope handle_scope(isolate);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000013944
13945 // Create an environment with access check to the global object disabled by
13946 // default.
13947 v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
13948 global_template->SetAccessCheckCallbacks(NamedGetAccessBlocker,
13949 IndexedGetAccessBlocker,
13950 v8::Handle<v8::Value>(),
13951 false);
ulan@chromium.org57ff8812013-05-10 08:16:55 +000013952 v8::Local<Context> context = Context::New(isolate, NULL, global_template);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000013953 Context::Scope context_scope(context);
13954
13955 // Set up a property and a number of functions.
13956 context->Global()->Set(v8_str("a"), v8_num(1));
13957 CompileRun("function f1() {return a;}"
13958 "function f2() {return a;}"
13959 "function g1() {return h();}"
13960 "function g2() {return h();}"
13961 "function h() {return 1;}");
13962 Local<Function> f1 =
13963 Local<Function>::Cast(context->Global()->Get(v8_str("f1")));
13964 Local<Function> f2 =
13965 Local<Function>::Cast(context->Global()->Get(v8_str("f2")));
13966 Local<Function> g1 =
13967 Local<Function>::Cast(context->Global()->Get(v8_str("g1")));
13968 Local<Function> g2 =
13969 Local<Function>::Cast(context->Global()->Get(v8_str("g2")));
13970 Local<Function> h =
13971 Local<Function>::Cast(context->Global()->Get(v8_str("h")));
13972
13973 // Get the global object.
13974 v8::Handle<v8::Object> global = context->Global();
13975
13976 // Call f1 one time and f2 a number of times. This will ensure that f1 still
13977 // uses the runtime system to retreive property a whereas f2 uses global load
13978 // inline cache.
13979 CHECK(f1->Call(global, 0, NULL)->Equals(v8_num(1)));
13980 for (int i = 0; i < 4; i++) {
13981 CHECK(f2->Call(global, 0, NULL)->Equals(v8_num(1)));
13982 }
13983
13984 // Same for g1 and g2.
13985 CHECK(g1->Call(global, 0, NULL)->Equals(v8_num(1)));
13986 for (int i = 0; i < 4; i++) {
13987 CHECK(g2->Call(global, 0, NULL)->Equals(v8_num(1)));
13988 }
13989
13990 // Detach the global and turn on access check.
13991 context->DetachGlobal();
13992 context->Global()->TurnOnAccessCheck();
13993
13994 // Failing access check to property get results in undefined.
13995 CHECK(f1->Call(global, 0, NULL)->IsUndefined());
13996 CHECK(f2->Call(global, 0, NULL)->IsUndefined());
13997
13998 // Failing access check to function call results in exception.
13999 CHECK(g1->Call(global, 0, NULL).IsEmpty());
14000 CHECK(g2->Call(global, 0, NULL).IsEmpty());
14001
14002 // No failing access check when just returning a constant.
14003 CHECK(h->Call(global, 0, NULL)->Equals(v8_num(1)));
14004}
14005
14006
jkummerow@chromium.orgf7a58842012-02-21 10:08:21 +000014007static const char* kPropertyA = "a";
14008static const char* kPropertyH = "h";
kasperl@chromium.orga5551262010-12-07 12:49:48 +000014009
14010static bool NamedGetAccessBlockAandH(Local<v8::Object> obj,
14011 Local<Value> name,
14012 v8::AccessType type,
14013 Local<Value> data) {
jkummerow@chromium.orgf7a58842012-02-21 10:08:21 +000014014 if (!name->IsString()) return false;
14015 i::Handle<i::String> name_handle =
14016 v8::Utils::OpenHandle(String::Cast(*name));
jkummerow@chromium.org59297c72013-01-09 16:32:23 +000014017 return !name_handle->IsUtf8EqualTo(i::CStrVector(kPropertyA))
14018 && !name_handle->IsUtf8EqualTo(i::CStrVector(kPropertyH));
kasperl@chromium.orga5551262010-12-07 12:49:48 +000014019}
14020
14021
jkummerow@chromium.orgf7a58842012-02-21 10:08:21 +000014022THREADED_TEST(TurnOnAccessCheckAndRecompile) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014023 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000014024 v8::HandleScope handle_scope(isolate);
kasperl@chromium.orga5551262010-12-07 12:49:48 +000014025
14026 // Create an environment with access check to the global object disabled by
14027 // default. When the registered access checker will block access to properties
jkummerow@chromium.orgf7a58842012-02-21 10:08:21 +000014028 // a and h.
kasperl@chromium.orga5551262010-12-07 12:49:48 +000014029 v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
14030 global_template->SetAccessCheckCallbacks(NamedGetAccessBlockAandH,
14031 IndexedGetAccessBlocker,
14032 v8::Handle<v8::Value>(),
14033 false);
ulan@chromium.org57ff8812013-05-10 08:16:55 +000014034 v8::Local<Context> context = Context::New(isolate, NULL, global_template);
kasperl@chromium.orga5551262010-12-07 12:49:48 +000014035 Context::Scope context_scope(context);
14036
14037 // Set up a property and a number of functions.
14038 context->Global()->Set(v8_str("a"), v8_num(1));
14039 static const char* source = "function f1() {return a;}"
14040 "function f2() {return a;}"
14041 "function g1() {return h();}"
14042 "function g2() {return h();}"
14043 "function h() {return 1;}";
14044
14045 CompileRun(source);
14046 Local<Function> f1;
14047 Local<Function> f2;
14048 Local<Function> g1;
14049 Local<Function> g2;
14050 Local<Function> h;
14051 f1 = Local<Function>::Cast(context->Global()->Get(v8_str("f1")));
14052 f2 = Local<Function>::Cast(context->Global()->Get(v8_str("f2")));
14053 g1 = Local<Function>::Cast(context->Global()->Get(v8_str("g1")));
14054 g2 = Local<Function>::Cast(context->Global()->Get(v8_str("g2")));
14055 h = Local<Function>::Cast(context->Global()->Get(v8_str("h")));
14056
14057 // Get the global object.
14058 v8::Handle<v8::Object> global = context->Global();
14059
14060 // Call f1 one time and f2 a number of times. This will ensure that f1 still
14061 // uses the runtime system to retreive property a whereas f2 uses global load
14062 // inline cache.
14063 CHECK(f1->Call(global, 0, NULL)->Equals(v8_num(1)));
14064 for (int i = 0; i < 4; i++) {
14065 CHECK(f2->Call(global, 0, NULL)->Equals(v8_num(1)));
14066 }
14067
14068 // Same for g1 and g2.
14069 CHECK(g1->Call(global, 0, NULL)->Equals(v8_num(1)));
14070 for (int i = 0; i < 4; i++) {
14071 CHECK(g2->Call(global, 0, NULL)->Equals(v8_num(1)));
14072 }
14073
14074 // Detach the global and turn on access check now blocking access to property
14075 // a and function h.
14076 context->DetachGlobal();
14077 context->Global()->TurnOnAccessCheck();
14078
14079 // Failing access check to property get results in undefined.
14080 CHECK(f1->Call(global, 0, NULL)->IsUndefined());
14081 CHECK(f2->Call(global, 0, NULL)->IsUndefined());
14082
14083 // Failing access check to function call results in exception.
14084 CHECK(g1->Call(global, 0, NULL).IsEmpty());
14085 CHECK(g2->Call(global, 0, NULL).IsEmpty());
14086
14087 // No failing access check when just returning a constant.
14088 CHECK(h->Call(global, 0, NULL)->Equals(v8_num(1)));
14089
14090 // Now compile the source again. And get the newly compiled functions, except
14091 // for h for which access is blocked.
14092 CompileRun(source);
14093 f1 = Local<Function>::Cast(context->Global()->Get(v8_str("f1")));
14094 f2 = Local<Function>::Cast(context->Global()->Get(v8_str("f2")));
14095 g1 = Local<Function>::Cast(context->Global()->Get(v8_str("g1")));
14096 g2 = Local<Function>::Cast(context->Global()->Get(v8_str("g2")));
14097 CHECK(context->Global()->Get(v8_str("h"))->IsUndefined());
14098
14099 // Failing access check to property get results in undefined.
14100 CHECK(f1->Call(global, 0, NULL)->IsUndefined());
14101 CHECK(f2->Call(global, 0, NULL)->IsUndefined());
14102
14103 // Failing access check to function call results in exception.
14104 CHECK(g1->Call(global, 0, NULL).IsEmpty());
14105 CHECK(g2->Call(global, 0, NULL).IsEmpty());
14106}
14107
14108
ager@chromium.orga74f0da2008-12-03 16:05:52 +000014109// This test verifies that pre-compilation (aka preparsing) can be called
14110// without initializing the whole VM. Thus we cannot run this test in a
14111// multi-threaded setup.
14112TEST(PreCompile) {
14113 // TODO(155): This test would break without the initialization of V8. This is
14114 // a workaround for now to make this test not fail.
14115 v8::V8::Initialize();
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +000014116 v8::Isolate* isolate = CcTest::isolate();
kmillikin@chromium.org9155e252010-05-26 13:27:57 +000014117 const char* script = "function foo(a) { return a+1; }";
14118 v8::ScriptData* sd =
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +000014119 v8::ScriptData::PreCompile(isolate, script, i::StrLength(script));
ager@chromium.orga74f0da2008-12-03 16:05:52 +000014120 CHECK_NE(sd->Length(), 0);
14121 CHECK_NE(sd->Data(), NULL);
fschneider@chromium.org0c20e672010-01-14 15:28:53 +000014122 CHECK(!sd->HasError());
14123 delete sd;
14124}
14125
14126
14127TEST(PreCompileWithError) {
14128 v8::V8::Initialize();
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +000014129 v8::Isolate* isolate = CcTest::isolate();
kmillikin@chromium.org9155e252010-05-26 13:27:57 +000014130 const char* script = "function foo(a) { return 1 * * 2; }";
14131 v8::ScriptData* sd =
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +000014132 v8::ScriptData::PreCompile(isolate, script, i::StrLength(script));
fschneider@chromium.org0c20e672010-01-14 15:28:53 +000014133 CHECK(sd->HasError());
14134 delete sd;
14135}
14136
14137
14138TEST(Regress31661) {
14139 v8::V8::Initialize();
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +000014140 v8::Isolate* isolate = CcTest::isolate();
kmillikin@chromium.org9155e252010-05-26 13:27:57 +000014141 const char* script = " The Definintive Guide";
14142 v8::ScriptData* sd =
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +000014143 v8::ScriptData::PreCompile(isolate, script, i::StrLength(script));
fschneider@chromium.org0c20e672010-01-14 15:28:53 +000014144 CHECK(sd->HasError());
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000014145 delete sd;
ager@chromium.orga74f0da2008-12-03 16:05:52 +000014146}
14147
14148
kmillikin@chromium.org9155e252010-05-26 13:27:57 +000014149// Tests that ScriptData can be serialized and deserialized.
14150TEST(PreCompileSerialization) {
14151 v8::V8::Initialize();
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +000014152 v8::Isolate* isolate = CcTest::isolate();
kmillikin@chromium.org9155e252010-05-26 13:27:57 +000014153 const char* script = "function foo(a) { return a+1; }";
14154 v8::ScriptData* sd =
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +000014155 v8::ScriptData::PreCompile(isolate, script, i::StrLength(script));
kmillikin@chromium.org9155e252010-05-26 13:27:57 +000014156
14157 // Serialize.
14158 int serialized_data_length = sd->Length();
14159 char* serialized_data = i::NewArray<char>(serialized_data_length);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +000014160 i::OS::MemCopy(serialized_data, sd->Data(), serialized_data_length);
kmillikin@chromium.org9155e252010-05-26 13:27:57 +000014161
14162 // Deserialize.
14163 v8::ScriptData* deserialized_sd =
14164 v8::ScriptData::New(serialized_data, serialized_data_length);
14165
14166 // Verify that the original is the same as the deserialized.
14167 CHECK_EQ(sd->Length(), deserialized_sd->Length());
14168 CHECK_EQ(0, memcmp(sd->Data(), deserialized_sd->Data(), sd->Length()));
14169 CHECK_EQ(sd->HasError(), deserialized_sd->HasError());
14170
14171 delete sd;
14172 delete deserialized_sd;
14173}
14174
14175
14176// Attempts to deserialize bad data.
14177TEST(PreCompileDeserializationError) {
14178 v8::V8::Initialize();
14179 const char* data = "DONT CARE";
14180 int invalid_size = 3;
14181 v8::ScriptData* sd = v8::ScriptData::New(data, invalid_size);
14182
14183 CHECK_EQ(0, sd->Length());
14184
14185 delete sd;
14186}
14187
14188
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014189// Attempts to deserialize bad data.
14190TEST(PreCompileInvalidPreparseDataError) {
14191 v8::V8::Initialize();
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +000014192 v8::Isolate* isolate = CcTest::isolate();
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014193 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000014194 v8::HandleScope scope(context->GetIsolate());
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014195
14196 const char* script = "function foo(){ return 5;}\n"
14197 "function bar(){ return 6 + 7;} foo();";
14198 v8::ScriptData* sd =
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +000014199 v8::ScriptData::PreCompile(isolate, script, i::StrLength(script));
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014200 CHECK(!sd->HasError());
14201 // ScriptDataImpl private implementation details
ager@chromium.orgbeb25712010-11-29 08:02:25 +000014202 const int kHeaderSize = i::PreparseDataConstants::kHeaderSize;
ager@chromium.org5b2fbee2010-09-08 06:38:15 +000014203 const int kFunctionEntrySize = i::FunctionEntry::kSize;
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014204 const int kFunctionEntryStartOffset = 0;
14205 const int kFunctionEntryEndOffset = 1;
14206 unsigned* sd_data =
14207 reinterpret_cast<unsigned*>(const_cast<char*>(sd->Data()));
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014208
14209 // Overwrite function bar's end position with 0.
14210 sd_data[kHeaderSize + 1 * kFunctionEntrySize + kFunctionEntryEndOffset] = 0;
14211 v8::TryCatch try_catch;
14212
14213 Local<String> source = String::New(script);
14214 Local<Script> compiled_script = Script::New(source, NULL, sd);
14215 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000014216 String::Utf8Value exception_value(try_catch.Message()->Get());
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014217 CHECK_EQ("Uncaught SyntaxError: Invalid preparser data for function bar",
14218 *exception_value);
14219
14220 try_catch.Reset();
lrn@chromium.orgd4e9e222011-08-03 12:01:58 +000014221
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014222 // Overwrite function bar's start position with 200. The function entry
lrn@chromium.orgd4e9e222011-08-03 12:01:58 +000014223 // will not be found when searching for it by position and we should fall
14224 // back on eager compilation.
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +000014225 sd = v8::ScriptData::PreCompile(isolate, script, i::StrLength(script));
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +000014226 sd_data = reinterpret_cast<unsigned*>(const_cast<char*>(sd->Data()));
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014227 sd_data[kHeaderSize + 1 * kFunctionEntrySize + kFunctionEntryStartOffset] =
14228 200;
14229 compiled_script = Script::New(source, NULL, sd);
lrn@chromium.orgd4e9e222011-08-03 12:01:58 +000014230 CHECK(!try_catch.HasCaught());
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014231
14232 delete sd;
14233}
14234
14235
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +000014236// Verifies that the Handle<String> and const char* versions of the API produce
14237// the same results (at least for one trivial case).
14238TEST(PreCompileAPIVariationsAreSame) {
14239 v8::V8::Initialize();
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +000014240 v8::Isolate* isolate = CcTest::isolate();
14241 v8::HandleScope scope(isolate);
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +000014242
14243 const char* cstring = "function foo(a) { return a+1; }";
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000014244
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +000014245 v8::ScriptData* sd_from_cstring =
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +000014246 v8::ScriptData::PreCompile(isolate, cstring, i::StrLength(cstring));
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +000014247
14248 TestAsciiResource* resource = new TestAsciiResource(cstring);
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000014249 v8::ScriptData* sd_from_external_string = v8::ScriptData::PreCompile(
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +000014250 v8::String::NewExternal(resource));
14251
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000014252 v8::ScriptData* sd_from_string = v8::ScriptData::PreCompile(
14253 v8::String::New(cstring));
14254
14255 CHECK_EQ(sd_from_cstring->Length(), sd_from_external_string->Length());
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +000014256 CHECK_EQ(0, memcmp(sd_from_cstring->Data(),
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000014257 sd_from_external_string->Data(),
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +000014258 sd_from_cstring->Length()));
14259
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000014260 CHECK_EQ(sd_from_cstring->Length(), sd_from_string->Length());
14261 CHECK_EQ(0, memcmp(sd_from_cstring->Data(),
14262 sd_from_string->Data(),
14263 sd_from_cstring->Length()));
14264
14265
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +000014266 delete sd_from_cstring;
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000014267 delete sd_from_external_string;
14268 delete sd_from_string;
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +000014269}
14270
14271
ager@chromium.orga74f0da2008-12-03 16:05:52 +000014272// This tests that we do not allow dictionary load/call inline caches
14273// to use functions that have not yet been compiled. The potential
14274// problem of loading a function that has not yet been compiled can
14275// arise because we share code between contexts via the compilation
14276// cache.
14277THREADED_TEST(DictionaryICLoadedFunction) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014278 v8::HandleScope scope(CcTest::isolate());
ager@chromium.orga74f0da2008-12-03 16:05:52 +000014279 // Test LoadIC.
14280 for (int i = 0; i < 2; i++) {
14281 LocalContext context;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000014282 context->Global()->Set(v8_str("tmp"), v8::True(CcTest::isolate()));
ager@chromium.orga74f0da2008-12-03 16:05:52 +000014283 context->Global()->Delete(v8_str("tmp"));
14284 CompileRun("for (var j = 0; j < 10; j++) new RegExp('');");
14285 }
14286 // Test CallIC.
14287 for (int i = 0; i < 2; i++) {
14288 LocalContext context;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000014289 context->Global()->Set(v8_str("tmp"), v8::True(CcTest::isolate()));
ager@chromium.orga74f0da2008-12-03 16:05:52 +000014290 context->Global()->Delete(v8_str("tmp"));
14291 CompileRun("for (var j = 0; j < 10; j++) RegExp('')");
14292 }
14293}
ager@chromium.orgddb913d2009-01-27 10:01:48 +000014294
14295
14296// Test that cross-context new calls use the context of the callee to
14297// create the new JavaScript object.
14298THREADED_TEST(CrossContextNew) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014299 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000014300 v8::HandleScope scope(isolate);
14301 v8::Local<Context> context0 = Context::New(isolate);
14302 v8::Local<Context> context1 = Context::New(isolate);
ager@chromium.orgddb913d2009-01-27 10:01:48 +000014303
14304 // Allow cross-domain access.
14305 Local<String> token = v8_str("<security token>");
14306 context0->SetSecurityToken(token);
14307 context1->SetSecurityToken(token);
14308
14309 // Set an 'x' property on the Object prototype and define a
14310 // constructor function in context0.
14311 context0->Enter();
14312 CompileRun("Object.prototype.x = 42; function C() {};");
14313 context0->Exit();
14314
14315 // Call the constructor function from context0 and check that the
14316 // result has the 'x' property.
14317 context1->Enter();
14318 context1->Global()->Set(v8_str("other"), context0->Global());
14319 Local<Value> value = CompileRun("var instance = new other.C(); instance.x");
14320 CHECK(value->IsInt32());
14321 CHECK_EQ(42, value->Int32Value());
14322 context1->Exit();
ager@chromium.orgddb913d2009-01-27 10:01:48 +000014323}
ager@chromium.org381abbb2009-02-25 13:23:22 +000014324
14325
ager@chromium.org65dad4b2009-04-23 08:48:43 +000014326class ApplyInterruptTest {
14327 public:
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000014328 ApplyInterruptTest() : block_(0) {}
14329 ~ApplyInterruptTest() {}
ager@chromium.org65dad4b2009-04-23 08:48:43 +000014330 void RunTest() {
ager@chromium.org65dad4b2009-04-23 08:48:43 +000014331 gc_count_ = 0;
14332 gc_during_apply_ = 0;
14333 apply_success_ = false;
14334 gc_success_ = false;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000014335 GCThread gc_thread(this);
ager@chromium.org65dad4b2009-04-23 08:48:43 +000014336 gc_thread.Start();
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +000014337 v8::Isolate* isolate = CcTest::isolate();
14338 v8::Locker::StartPreemption(isolate, 1);
ager@chromium.org65dad4b2009-04-23 08:48:43 +000014339
14340 LongRunningApply();
14341 {
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +000014342 v8::Unlocker unlock(isolate);
ager@chromium.org65dad4b2009-04-23 08:48:43 +000014343 gc_thread.Join();
14344 }
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +000014345 v8::Locker::StopPreemption(isolate);
ager@chromium.org65dad4b2009-04-23 08:48:43 +000014346 CHECK(apply_success_);
14347 CHECK(gc_success_);
14348 }
jkummerow@chromium.orge297f592011-06-08 10:05:15 +000014349
ager@chromium.org65dad4b2009-04-23 08:48:43 +000014350 private:
14351 // Number of garbage collections required.
14352 static const int kRequiredGCs = 2;
14353
14354 class GCThread : public i::Thread {
14355 public:
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000014356 explicit GCThread(ApplyInterruptTest* test)
14357 : Thread("GCThread"), test_(test) {}
ager@chromium.org65dad4b2009-04-23 08:48:43 +000014358 virtual void Run() {
14359 test_->CollectGarbage();
14360 }
14361 private:
14362 ApplyInterruptTest* test_;
14363 };
14364
14365 void CollectGarbage() {
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000014366 block_.Wait();
ager@chromium.org65dad4b2009-04-23 08:48:43 +000014367 while (gc_during_apply_ < kRequiredGCs) {
14368 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014369 v8::Locker lock(CcTest::isolate());
14370 v8::Isolate::Scope isolate_scope(CcTest::isolate());
14371 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org65dad4b2009-04-23 08:48:43 +000014372 gc_count_++;
14373 }
14374 i::OS::Sleep(1);
14375 }
14376 gc_success_ = true;
14377 }
14378
14379 void LongRunningApply() {
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000014380 block_.Signal();
ager@chromium.org65dad4b2009-04-23 08:48:43 +000014381 int rounds = 0;
14382 while (gc_during_apply_ < kRequiredGCs) {
14383 int gc_before = gc_count_;
14384 {
14385 const char* c_source =
14386 "function do_very_little(bar) {"
14387 " this.foo = bar;"
14388 "}"
14389 "for (var i = 0; i < 100000; i++) {"
14390 " do_very_little.apply(this, ['bar']);"
14391 "}";
14392 Local<String> source = String::New(c_source);
14393 Local<Script> script = Script::Compile(source);
14394 Local<Value> result = script->Run();
ager@chromium.org3a37e9b2009-04-27 09:26:21 +000014395 // Check that no exception was thrown.
14396 CHECK(!result.IsEmpty());
ager@chromium.org65dad4b2009-04-23 08:48:43 +000014397 }
14398 int gc_after = gc_count_;
14399 gc_during_apply_ += gc_after - gc_before;
14400 rounds++;
14401 }
14402 apply_success_ = true;
14403 }
14404
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000014405 i::Semaphore block_;
ager@chromium.org65dad4b2009-04-23 08:48:43 +000014406 int gc_count_;
14407 int gc_during_apply_;
14408 bool apply_success_;
14409 bool gc_success_;
14410};
14411
14412
14413// Test that nothing bad happens if we get a preemption just when we were
14414// about to do an apply().
14415TEST(ApplyInterruption) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014416 v8::Locker lock(CcTest::isolate());
ager@chromium.org65dad4b2009-04-23 08:48:43 +000014417 v8::V8::Initialize();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014418 v8::HandleScope scope(CcTest::isolate());
ager@chromium.org65dad4b2009-04-23 08:48:43 +000014419 Local<Context> local_env;
14420 {
14421 LocalContext env;
14422 local_env = env.local();
14423 }
14424
14425 // Local context should still be live.
14426 CHECK(!local_env.IsEmpty());
14427 local_env->Enter();
14428
14429 // Should complete without problems.
14430 ApplyInterruptTest().RunTest();
14431
14432 local_env->Exit();
14433}
14434
14435
ager@chromium.org3b45ab52009-03-19 22:21:34 +000014436// Verify that we can clone an object
14437TEST(ObjectClone) {
ager@chromium.org3b45ab52009-03-19 22:21:34 +000014438 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000014439 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org3b45ab52009-03-19 22:21:34 +000014440
14441 const char* sample =
14442 "var rv = {};" \
14443 "rv.alpha = 'hello';" \
14444 "rv.beta = 123;" \
14445 "rv;";
14446
14447 // Create an object, verify basics.
14448 Local<Value> val = CompileRun(sample);
14449 CHECK(val->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000014450 Local<v8::Object> obj = val.As<v8::Object>();
ager@chromium.org3b45ab52009-03-19 22:21:34 +000014451 obj->Set(v8_str("gamma"), v8_str("cloneme"));
14452
14453 CHECK_EQ(v8_str("hello"), obj->Get(v8_str("alpha")));
14454 CHECK_EQ(v8::Integer::New(123), obj->Get(v8_str("beta")));
14455 CHECK_EQ(v8_str("cloneme"), obj->Get(v8_str("gamma")));
14456
14457 // Clone it.
14458 Local<v8::Object> clone = obj->Clone();
14459 CHECK_EQ(v8_str("hello"), clone->Get(v8_str("alpha")));
14460 CHECK_EQ(v8::Integer::New(123), clone->Get(v8_str("beta")));
14461 CHECK_EQ(v8_str("cloneme"), clone->Get(v8_str("gamma")));
14462
14463 // Set a property on the clone, verify each object.
14464 clone->Set(v8_str("beta"), v8::Integer::New(456));
14465 CHECK_EQ(v8::Integer::New(123), obj->Get(v8_str("beta")));
14466 CHECK_EQ(v8::Integer::New(456), clone->Get(v8_str("beta")));
14467}
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000014468
14469
ager@chromium.org5ec48922009-05-05 07:25:34 +000014470class AsciiVectorResource : public v8::String::ExternalAsciiStringResource {
14471 public:
14472 explicit AsciiVectorResource(i::Vector<const char> vector)
14473 : data_(vector) {}
14474 virtual ~AsciiVectorResource() {}
14475 virtual size_t length() const { return data_.length(); }
14476 virtual const char* data() const { return data_.start(); }
14477 private:
14478 i::Vector<const char> data_;
14479};
14480
14481
14482class UC16VectorResource : public v8::String::ExternalStringResource {
14483 public:
14484 explicit UC16VectorResource(i::Vector<const i::uc16> vector)
14485 : data_(vector) {}
14486 virtual ~UC16VectorResource() {}
14487 virtual size_t length() const { return data_.length(); }
14488 virtual const i::uc16* data() const { return data_.start(); }
14489 private:
14490 i::Vector<const i::uc16> data_;
14491};
14492
14493
14494static void MorphAString(i::String* string,
14495 AsciiVectorResource* ascii_resource,
14496 UC16VectorResource* uc16_resource) {
14497 CHECK(i::StringShape(string).IsExternal());
ulan@chromium.org8e8d8822012-11-23 14:36:46 +000014498 if (string->IsOneByteRepresentation()) {
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +000014499 // Check old map is not internalized or long.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014500 CHECK(string->map() == CcTest::heap()->external_ascii_string_map());
ager@chromium.org5ec48922009-05-05 07:25:34 +000014501 // Morph external string to be TwoByte string.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014502 string->set_map(CcTest::heap()->external_string_map());
ager@chromium.org5ec48922009-05-05 07:25:34 +000014503 i::ExternalTwoByteString* morphed =
14504 i::ExternalTwoByteString::cast(string);
14505 morphed->set_resource(uc16_resource);
14506 } else {
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +000014507 // Check old map is not internalized or long.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014508 CHECK(string->map() == CcTest::heap()->external_string_map());
ager@chromium.org5ec48922009-05-05 07:25:34 +000014509 // Morph external string to be ASCII string.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014510 string->set_map(CcTest::heap()->external_ascii_string_map());
ager@chromium.org5ec48922009-05-05 07:25:34 +000014511 i::ExternalAsciiString* morphed =
14512 i::ExternalAsciiString::cast(string);
14513 morphed->set_resource(ascii_resource);
14514 }
14515}
14516
14517
14518// Test that we can still flatten a string if the components it is built up
14519// from have been turned into 16 bit strings in the mean time.
14520THREADED_TEST(MorphCompositeStringTest) {
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +000014521 char utf_buffer[129];
ager@chromium.org5ec48922009-05-05 07:25:34 +000014522 const char* c_string = "Now is the time for all good men"
14523 " to come to the aid of the party";
14524 uint16_t* two_byte_string = AsciiToTwoByteString(c_string);
14525 {
ager@chromium.org5ec48922009-05-05 07:25:34 +000014526 LocalContext env;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014527 i::Factory* factory = CcTest::i_isolate()->factory();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000014528 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org5ec48922009-05-05 07:25:34 +000014529 AsciiVectorResource ascii_resource(
ager@chromium.orgc4c92722009-11-18 14:12:51 +000014530 i::Vector<const char>(c_string, i::StrLength(c_string)));
ager@chromium.org5ec48922009-05-05 07:25:34 +000014531 UC16VectorResource uc16_resource(
ager@chromium.orgc4c92722009-11-18 14:12:51 +000014532 i::Vector<const uint16_t>(two_byte_string,
14533 i::StrLength(c_string)));
ager@chromium.org5ec48922009-05-05 07:25:34 +000014534
14535 Local<String> lhs(v8::Utils::ToLocal(
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000014536 factory->NewExternalStringFromAscii(&ascii_resource)));
ager@chromium.org5ec48922009-05-05 07:25:34 +000014537 Local<String> rhs(v8::Utils::ToLocal(
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000014538 factory->NewExternalStringFromAscii(&ascii_resource)));
ager@chromium.org5ec48922009-05-05 07:25:34 +000014539
14540 env->Global()->Set(v8_str("lhs"), lhs);
14541 env->Global()->Set(v8_str("rhs"), rhs);
14542
14543 CompileRun(
14544 "var cons = lhs + rhs;"
14545 "var slice = lhs.substring(1, lhs.length - 1);"
14546 "var slice_on_cons = (lhs + rhs).substring(1, lhs.length *2 - 1);");
14547
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000014548 CHECK(lhs->IsOneByte());
14549 CHECK(rhs->IsOneByte());
rossberg@chromium.org2c067b12012-03-19 11:01:52 +000014550
ager@chromium.org5ec48922009-05-05 07:25:34 +000014551 MorphAString(*v8::Utils::OpenHandle(*lhs), &ascii_resource, &uc16_resource);
14552 MorphAString(*v8::Utils::OpenHandle(*rhs), &ascii_resource, &uc16_resource);
14553
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +000014554 // This should UTF-8 without flattening, since everything is ASCII.
14555 Handle<String> cons = v8_compile("cons")->Run().As<String>();
14556 CHECK_EQ(128, cons->Utf8Length());
14557 int nchars = -1;
14558 CHECK_EQ(129, cons->WriteUtf8(utf_buffer, -1, &nchars));
14559 CHECK_EQ(128, nchars);
14560 CHECK_EQ(0, strcmp(
14561 utf_buffer,
14562 "Now is the time for all good men to come to the aid of the party"
14563 "Now is the time for all good men to come to the aid of the party"));
14564
ager@chromium.org5ec48922009-05-05 07:25:34 +000014565 // Now do some stuff to make sure the strings are flattened, etc.
14566 CompileRun(
14567 "/[^a-z]/.test(cons);"
14568 "/[^a-z]/.test(slice);"
14569 "/[^a-z]/.test(slice_on_cons);");
14570 const char* expected_cons =
14571 "Now is the time for all good men to come to the aid of the party"
14572 "Now is the time for all good men to come to the aid of the party";
14573 const char* expected_slice =
14574 "ow is the time for all good men to come to the aid of the part";
14575 const char* expected_slice_on_cons =
14576 "ow is the time for all good men to come to the aid of the party"
14577 "Now is the time for all good men to come to the aid of the part";
14578 CHECK_EQ(String::New(expected_cons),
14579 env->Global()->Get(v8_str("cons")));
14580 CHECK_EQ(String::New(expected_slice),
14581 env->Global()->Get(v8_str("slice")));
14582 CHECK_EQ(String::New(expected_slice_on_cons),
14583 env->Global()->Get(v8_str("slice_on_cons")));
14584 }
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000014585 i::DeleteArray(two_byte_string);
ager@chromium.org5ec48922009-05-05 07:25:34 +000014586}
14587
14588
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000014589TEST(CompileExternalTwoByteSource) {
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000014590 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000014591 v8::HandleScope scope(context->GetIsolate());
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000014592
14593 // This is a very short list of sources, which currently is to check for a
14594 // regression caused by r2703.
14595 const char* ascii_sources[] = {
14596 "0.5",
14597 "-0.5", // This mainly testes PushBack in the Scanner.
14598 "--0.5", // This mainly testes PushBack in the Scanner.
14599 NULL
14600 };
14601
14602 // Compile the sources as external two byte strings.
14603 for (int i = 0; ascii_sources[i] != NULL; i++) {
14604 uint16_t* two_byte_string = AsciiToTwoByteString(ascii_sources[i]);
14605 UC16VectorResource uc16_resource(
ager@chromium.orgc4c92722009-11-18 14:12:51 +000014606 i::Vector<const uint16_t>(two_byte_string,
14607 i::StrLength(ascii_sources[i])));
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000014608 v8::Local<v8::String> source = v8::String::NewExternal(&uc16_resource);
14609 v8::Script::Compile(source);
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000014610 i::DeleteArray(two_byte_string);
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000014611 }
14612}
14613
14614
mstarzinger@chromium.orgb4968be2013-10-16 09:00:56 +000014615#ifndef V8_INTERPRETED_REGEXP
14616
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +000014617struct RegExpInterruptionData {
14618 int loop_count;
14619 UC16VectorResource* string_resource;
14620 v8::Persistent<v8::String> string;
14621} regexp_interruption_data;
14622
14623
14624class RegExpInterruptionThread : public i::Thread {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000014625 public:
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +000014626 explicit RegExpInterruptionThread(v8::Isolate* isolate)
14627 : Thread("TimeoutThread"), isolate_(isolate) {}
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000014628
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +000014629 virtual void Run() {
14630 for (regexp_interruption_data.loop_count = 0;
14631 regexp_interruption_data.loop_count < 7;
14632 regexp_interruption_data.loop_count++) {
14633 i::OS::Sleep(50); // Wait a bit before requesting GC.
14634 reinterpret_cast<i::Isolate*>(isolate_)->stack_guard()->RequestGC();
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000014635 }
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +000014636 i::OS::Sleep(50); // Wait a bit before terminating.
14637 v8::V8::TerminateExecution(isolate_);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000014638 }
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000014639
jkummerow@chromium.orge297f592011-06-08 10:05:15 +000014640 private:
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +000014641 v8::Isolate* isolate_;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000014642};
14643
14644
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +000014645void RunBeforeGC(v8::GCType type, v8::GCCallbackFlags flags) {
14646 if (regexp_interruption_data.loop_count != 2) return;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014647 v8::HandleScope scope(CcTest::isolate());
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +000014648 v8::Local<v8::String> string = v8::Local<v8::String>::New(
14649 CcTest::isolate(), regexp_interruption_data.string);
14650 string->MakeExternal(regexp_interruption_data.string_resource);
14651}
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000014652
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000014653
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +000014654// Test that RegExp execution can be interrupted. Specifically, we test
14655// * interrupting with GC
14656// * turn the subject string from one-byte internal to two-byte external string
14657// * force termination
14658TEST(RegExpInterruption) {
14659 v8::HandleScope scope(CcTest::isolate());
14660 LocalContext env;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000014661
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +000014662 RegExpInterruptionThread timeout_thread(CcTest::isolate());
14663
14664 v8::V8::AddGCPrologueCallback(RunBeforeGC);
14665 static const char* ascii_content = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
14666 i::uc16* uc16_content = AsciiToTwoByteString(ascii_content);
14667 v8::Local<v8::String> string = v8_str(ascii_content);
14668
14669 CcTest::global()->Set(v8_str("a"), string);
14670 regexp_interruption_data.string.Reset(CcTest::isolate(), string);
14671 regexp_interruption_data.string_resource = new UC16VectorResource(
14672 i::Vector<const i::uc16>(uc16_content, i::StrLength(ascii_content)));
14673
14674 v8::TryCatch try_catch;
14675 timeout_thread.Start();
14676
14677 CompileRun("/((a*)*)*b/.exec(a)");
14678 CHECK(try_catch.HasTerminated());
14679
14680 timeout_thread.Join();
14681
14682 delete regexp_interruption_data.string_resource;
14683 regexp_interruption_data.string.Dispose();
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000014684}
14685
mstarzinger@chromium.orgb4968be2013-10-16 09:00:56 +000014686#endif // V8_INTERPRETED_REGEXP
14687
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000014688
mmassi@chromium.org7028c052012-06-13 11:51:58 +000014689// Test that we cannot set a property on the global object if there
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000014690// is a read-only property in the prototype chain.
14691TEST(ReadOnlyPropertyInGlobalProto) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +000014692 i::FLAG_es5_readonly = true;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014693 v8::HandleScope scope(CcTest::isolate());
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000014694 v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
14695 LocalContext context(0, templ);
14696 v8::Handle<v8::Object> global = context->Global();
14697 v8::Handle<v8::Object> global_proto =
14698 v8::Handle<v8::Object>::Cast(global->Get(v8_str("__proto__")));
14699 global_proto->Set(v8_str("x"), v8::Integer::New(0), v8::ReadOnly);
14700 global_proto->Set(v8_str("y"), v8::Integer::New(0), v8::ReadOnly);
14701 // Check without 'eval' or 'with'.
14702 v8::Handle<v8::Value> res =
14703 CompileRun("function f() { x = 42; return x; }; f()");
mmassi@chromium.org7028c052012-06-13 11:51:58 +000014704 CHECK_EQ(v8::Integer::New(0), res);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000014705 // Check with 'eval'.
mmassi@chromium.org7028c052012-06-13 11:51:58 +000014706 res = CompileRun("function f() { eval('1'); y = 43; return y; }; f()");
14707 CHECK_EQ(v8::Integer::New(0), res);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000014708 // Check with 'with'.
mmassi@chromium.org7028c052012-06-13 11:51:58 +000014709 res = CompileRun("function f() { with (this) { y = 44 }; return y; }; f()");
14710 CHECK_EQ(v8::Integer::New(0), res);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000014711}
ager@chromium.org65dad4b2009-04-23 08:48:43 +000014712
14713static int force_set_set_count = 0;
14714static int force_set_get_count = 0;
14715bool pass_on_get = false;
14716
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000014717static void ForceSetGetter(v8::Local<v8::String> name,
14718 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.org65dad4b2009-04-23 08:48:43 +000014719 force_set_get_count++;
14720 if (pass_on_get) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000014721 return;
ager@chromium.org65dad4b2009-04-23 08:48:43 +000014722 }
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000014723 info.GetReturnValue().Set(3);
ager@chromium.org65dad4b2009-04-23 08:48:43 +000014724}
14725
14726static void ForceSetSetter(v8::Local<v8::String> name,
14727 v8::Local<v8::Value> value,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000014728 const v8::PropertyCallbackInfo<void>& info) {
ager@chromium.org65dad4b2009-04-23 08:48:43 +000014729 force_set_set_count++;
14730}
14731
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000014732static void ForceSetInterceptSetter(
ager@chromium.org65dad4b2009-04-23 08:48:43 +000014733 v8::Local<v8::String> name,
14734 v8::Local<v8::Value> value,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000014735 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.org65dad4b2009-04-23 08:48:43 +000014736 force_set_set_count++;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000014737 info.GetReturnValue().SetUndefined();
ager@chromium.org65dad4b2009-04-23 08:48:43 +000014738}
14739
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000014740
ager@chromium.org65dad4b2009-04-23 08:48:43 +000014741TEST(ForceSet) {
14742 force_set_get_count = 0;
14743 force_set_set_count = 0;
14744 pass_on_get = false;
14745
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014746 v8::HandleScope scope(CcTest::isolate());
ager@chromium.org65dad4b2009-04-23 08:48:43 +000014747 v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
14748 v8::Handle<v8::String> access_property = v8::String::New("a");
14749 templ->SetAccessor(access_property, ForceSetGetter, ForceSetSetter);
14750 LocalContext context(NULL, templ);
14751 v8::Handle<v8::Object> global = context->Global();
14752
14753 // Ordinary properties
14754 v8::Handle<v8::String> simple_property = v8::String::New("p");
14755 global->Set(simple_property, v8::Int32::New(4), v8::ReadOnly);
14756 CHECK_EQ(4, global->Get(simple_property)->Int32Value());
14757 // This should fail because the property is read-only
14758 global->Set(simple_property, v8::Int32::New(5));
14759 CHECK_EQ(4, global->Get(simple_property)->Int32Value());
14760 // This should succeed even though the property is read-only
14761 global->ForceSet(simple_property, v8::Int32::New(6));
14762 CHECK_EQ(6, global->Get(simple_property)->Int32Value());
14763
14764 // Accessors
14765 CHECK_EQ(0, force_set_set_count);
14766 CHECK_EQ(0, force_set_get_count);
14767 CHECK_EQ(3, global->Get(access_property)->Int32Value());
14768 // CHECK_EQ the property shouldn't override it, just call the setter
14769 // which in this case does nothing.
14770 global->Set(access_property, v8::Int32::New(7));
14771 CHECK_EQ(3, global->Get(access_property)->Int32Value());
14772 CHECK_EQ(1, force_set_set_count);
14773 CHECK_EQ(2, force_set_get_count);
14774 // Forcing the property to be set should override the accessor without
14775 // calling it
14776 global->ForceSet(access_property, v8::Int32::New(8));
14777 CHECK_EQ(8, global->Get(access_property)->Int32Value());
14778 CHECK_EQ(1, force_set_set_count);
14779 CHECK_EQ(2, force_set_get_count);
14780}
14781
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000014782
ager@chromium.org65dad4b2009-04-23 08:48:43 +000014783TEST(ForceSetWithInterceptor) {
14784 force_set_get_count = 0;
14785 force_set_set_count = 0;
14786 pass_on_get = false;
14787
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014788 v8::HandleScope scope(CcTest::isolate());
ager@chromium.org65dad4b2009-04-23 08:48:43 +000014789 v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
14790 templ->SetNamedPropertyHandler(ForceSetGetter, ForceSetInterceptSetter);
14791 LocalContext context(NULL, templ);
14792 v8::Handle<v8::Object> global = context->Global();
14793
14794 v8::Handle<v8::String> some_property = v8::String::New("a");
14795 CHECK_EQ(0, force_set_set_count);
14796 CHECK_EQ(0, force_set_get_count);
14797 CHECK_EQ(3, global->Get(some_property)->Int32Value());
14798 // Setting the property shouldn't override it, just call the setter
14799 // which in this case does nothing.
14800 global->Set(some_property, v8::Int32::New(7));
14801 CHECK_EQ(3, global->Get(some_property)->Int32Value());
14802 CHECK_EQ(1, force_set_set_count);
14803 CHECK_EQ(2, force_set_get_count);
14804 // Getting the property when the interceptor returns an empty handle
14805 // should yield undefined, since the property isn't present on the
14806 // object itself yet.
14807 pass_on_get = true;
14808 CHECK(global->Get(some_property)->IsUndefined());
14809 CHECK_EQ(1, force_set_set_count);
14810 CHECK_EQ(3, force_set_get_count);
14811 // Forcing the property to be set should cause the value to be
14812 // set locally without calling the interceptor.
14813 global->ForceSet(some_property, v8::Int32::New(8));
14814 CHECK_EQ(8, global->Get(some_property)->Int32Value());
14815 CHECK_EQ(1, force_set_set_count);
14816 CHECK_EQ(4, force_set_get_count);
14817 // Reenabling the interceptor should cause it to take precedence over
14818 // the property
14819 pass_on_get = false;
14820 CHECK_EQ(3, global->Get(some_property)->Int32Value());
14821 CHECK_EQ(1, force_set_set_count);
14822 CHECK_EQ(5, force_set_get_count);
14823 // The interceptor should also work for other properties
14824 CHECK_EQ(3, global->Get(v8::String::New("b"))->Int32Value());
14825 CHECK_EQ(1, force_set_set_count);
14826 CHECK_EQ(6, force_set_get_count);
14827}
ager@chromium.org1bf0cd02009-05-20 11:34:19 +000014828
14829
ager@chromium.orge2902be2009-06-08 12:21:35 +000014830THREADED_TEST(ForceDelete) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014831 v8::HandleScope scope(CcTest::isolate());
ager@chromium.orge2902be2009-06-08 12:21:35 +000014832 v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
14833 LocalContext context(NULL, templ);
14834 v8::Handle<v8::Object> global = context->Global();
14835
14836 // Ordinary properties
14837 v8::Handle<v8::String> simple_property = v8::String::New("p");
14838 global->Set(simple_property, v8::Int32::New(4), v8::DontDelete);
14839 CHECK_EQ(4, global->Get(simple_property)->Int32Value());
14840 // This should fail because the property is dont-delete.
14841 CHECK(!global->Delete(simple_property));
14842 CHECK_EQ(4, global->Get(simple_property)->Int32Value());
14843 // This should succeed even though the property is dont-delete.
14844 CHECK(global->ForceDelete(simple_property));
14845 CHECK(global->Get(simple_property)->IsUndefined());
14846}
14847
14848
14849static int force_delete_interceptor_count = 0;
14850static bool pass_on_delete = false;
14851
14852
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000014853static void ForceDeleteDeleter(
ager@chromium.orge2902be2009-06-08 12:21:35 +000014854 v8::Local<v8::String> name,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000014855 const v8::PropertyCallbackInfo<v8::Boolean>& info) {
ager@chromium.orge2902be2009-06-08 12:21:35 +000014856 force_delete_interceptor_count++;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000014857 if (pass_on_delete) return;
14858 info.GetReturnValue().Set(true);
ager@chromium.orge2902be2009-06-08 12:21:35 +000014859}
14860
14861
14862THREADED_TEST(ForceDeleteWithInterceptor) {
14863 force_delete_interceptor_count = 0;
14864 pass_on_delete = false;
14865
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014866 v8::HandleScope scope(CcTest::isolate());
ager@chromium.orge2902be2009-06-08 12:21:35 +000014867 v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
14868 templ->SetNamedPropertyHandler(0, 0, 0, ForceDeleteDeleter);
14869 LocalContext context(NULL, templ);
14870 v8::Handle<v8::Object> global = context->Global();
14871
14872 v8::Handle<v8::String> some_property = v8::String::New("a");
14873 global->Set(some_property, v8::Integer::New(42), v8::DontDelete);
14874
14875 // Deleting a property should get intercepted and nothing should
14876 // happen.
14877 CHECK_EQ(0, force_delete_interceptor_count);
14878 CHECK(global->Delete(some_property));
14879 CHECK_EQ(1, force_delete_interceptor_count);
14880 CHECK_EQ(42, global->Get(some_property)->Int32Value());
14881 // Deleting the property when the interceptor returns an empty
14882 // handle should not delete the property since it is DontDelete.
14883 pass_on_delete = true;
14884 CHECK(!global->Delete(some_property));
14885 CHECK_EQ(2, force_delete_interceptor_count);
14886 CHECK_EQ(42, global->Get(some_property)->Int32Value());
14887 // Forcing the property to be deleted should delete the value
14888 // without calling the interceptor.
14889 CHECK(global->ForceDelete(some_property));
14890 CHECK(global->Get(some_property)->IsUndefined());
14891 CHECK_EQ(2, force_delete_interceptor_count);
14892}
14893
14894
kasperl@chromium.org68ac0092009-07-09 06:00:35 +000014895// Make sure that forcing a delete invalidates any IC stubs, so we
14896// don't read the hole value.
14897THREADED_TEST(ForceDeleteIC) {
kasperl@chromium.org68ac0092009-07-09 06:00:35 +000014898 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000014899 v8::HandleScope scope(context->GetIsolate());
kasperl@chromium.org68ac0092009-07-09 06:00:35 +000014900 // Create a DontDelete variable on the global object.
14901 CompileRun("this.__proto__ = { foo: 'horse' };"
14902 "var foo = 'fish';"
14903 "function f() { return foo.length; }");
14904 // Initialize the IC for foo in f.
14905 CompileRun("for (var i = 0; i < 4; i++) f();");
14906 // Make sure the value of foo is correct before the deletion.
14907 CHECK_EQ(4, CompileRun("f()")->Int32Value());
14908 // Force the deletion of foo.
14909 CHECK(context->Global()->ForceDelete(v8_str("foo")));
14910 // Make sure the value for foo is read from the prototype, and that
14911 // we don't get in trouble with reading the deleted cell value
14912 // sentinel.
14913 CHECK_EQ(5, CompileRun("f()")->Int32Value());
14914}
14915
14916
mstarzinger@chromium.org88d326b2012-04-23 12:57:22 +000014917TEST(InlinedFunctionAcrossContexts) {
14918 i::FLAG_allow_natives_syntax = true;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014919 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000014920 v8::HandleScope outer_scope(isolate);
14921 v8::Local<v8::Context> ctx1 = v8::Context::New(isolate);
14922 v8::Local<v8::Context> ctx2 = v8::Context::New(isolate);
mstarzinger@chromium.org88d326b2012-04-23 12:57:22 +000014923 ctx1->Enter();
14924
14925 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014926 v8::HandleScope inner_scope(CcTest::isolate());
mstarzinger@chromium.org88d326b2012-04-23 12:57:22 +000014927 CompileRun("var G = 42; function foo() { return G; }");
14928 v8::Local<v8::Value> foo = ctx1->Global()->Get(v8_str("foo"));
14929 ctx2->Enter();
14930 ctx2->Global()->Set(v8_str("o"), foo);
14931 v8::Local<v8::Value> res = CompileRun(
14932 "function f() { return o(); }"
14933 "for (var i = 0; i < 10; ++i) f();"
14934 "%OptimizeFunctionOnNextCall(f);"
14935 "f();");
14936 CHECK_EQ(42, res->Int32Value());
14937 ctx2->Exit();
14938 v8::Handle<v8::String> G_property = v8::String::New("G");
14939 CHECK(ctx1->Global()->ForceDelete(G_property));
14940 ctx2->Enter();
14941 ExpectString(
14942 "(function() {"
14943 " try {"
14944 " return f();"
14945 " } catch(e) {"
14946 " return e.toString();"
14947 " }"
14948 " })()",
14949 "ReferenceError: G is not defined");
14950 ctx2->Exit();
14951 ctx1->Exit();
mstarzinger@chromium.org88d326b2012-04-23 12:57:22 +000014952 }
mstarzinger@chromium.org88d326b2012-04-23 12:57:22 +000014953}
14954
14955
ulan@chromium.org57ff8812013-05-10 08:16:55 +000014956static v8::Local<Context> calling_context0;
14957static v8::Local<Context> calling_context1;
14958static v8::Local<Context> calling_context2;
ager@chromium.org1bf0cd02009-05-20 11:34:19 +000014959
14960
14961// Check that the call to the callback is initiated in
14962// calling_context2, the directly calling context is calling_context1
14963// and the callback itself is in calling_context0.
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000014964static void GetCallingContextCallback(
14965 const v8::FunctionCallbackInfo<v8::Value>& args) {
ager@chromium.org1bf0cd02009-05-20 11:34:19 +000014966 ApiTestFuzzer::Fuzz();
mvstanton@chromium.org40ce96b2013-04-09 09:52:22 +000014967 CHECK(args.GetIsolate()->GetCurrentContext() == calling_context0);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014968 CHECK(args.GetIsolate()->GetCallingContext() == calling_context1);
14969 CHECK(args.GetIsolate()->GetEnteredContext() == calling_context2);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000014970 args.GetReturnValue().Set(42);
14971}
14972
14973
14974THREADED_TEST(GetCurrentContextWhenNotInContext) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014975 i::Isolate* isolate = CcTest::i_isolate();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000014976 CHECK(isolate != NULL);
14977 CHECK(isolate->context() == NULL);
14978 v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
14979 v8::HandleScope scope(v8_isolate);
14980 // The following should not crash, but return an empty handle.
14981 v8::Local<v8::Context> current = v8_isolate->GetCurrentContext();
14982 CHECK(current.IsEmpty());
ager@chromium.org1bf0cd02009-05-20 11:34:19 +000014983}
14984
14985
14986THREADED_TEST(GetCallingContext) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014987 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000014988 v8::HandleScope scope(isolate);
ager@chromium.org1bf0cd02009-05-20 11:34:19 +000014989
ulan@chromium.org57ff8812013-05-10 08:16:55 +000014990 Local<Context> calling_context0(Context::New(isolate));
14991 Local<Context> calling_context1(Context::New(isolate));
14992 Local<Context> calling_context2(Context::New(isolate));
14993 ::calling_context0 = calling_context0;
14994 ::calling_context1 = calling_context1;
14995 ::calling_context2 = calling_context2;
ager@chromium.org1bf0cd02009-05-20 11:34:19 +000014996
14997 // Allow cross-domain access.
14998 Local<String> token = v8_str("<security token>");
14999 calling_context0->SetSecurityToken(token);
15000 calling_context1->SetSecurityToken(token);
15001 calling_context2->SetSecurityToken(token);
15002
15003 // Create an object with a C++ callback in context0.
15004 calling_context0->Enter();
15005 Local<v8::FunctionTemplate> callback_templ =
15006 v8::FunctionTemplate::New(GetCallingContextCallback);
15007 calling_context0->Global()->Set(v8_str("callback"),
15008 callback_templ->GetFunction());
15009 calling_context0->Exit();
15010
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000015011 // Expose context0 in context1 and set up a function that calls the
ager@chromium.org1bf0cd02009-05-20 11:34:19 +000015012 // callback function.
15013 calling_context1->Enter();
15014 calling_context1->Global()->Set(v8_str("context0"),
15015 calling_context0->Global());
15016 CompileRun("function f() { context0.callback() }");
15017 calling_context1->Exit();
15018
15019 // Expose context1 in context2 and call the callback function in
15020 // context0 indirectly through f in context1.
15021 calling_context2->Enter();
15022 calling_context2->Global()->Set(v8_str("context1"),
15023 calling_context1->Global());
15024 CompileRun("context1.f()");
15025 calling_context2->Exit();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000015026 ::calling_context0.Clear();
15027 ::calling_context1.Clear();
15028 ::calling_context2.Clear();
ager@chromium.org1bf0cd02009-05-20 11:34:19 +000015029}
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000015030
15031
15032// Check that a variable declaration with no explicit initialization
erik.corry@gmail.comed49e962012-04-17 11:57:53 +000015033// value does shadow an existing property in the prototype chain.
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000015034THREADED_TEST(InitGlobalVarInProtoChain) {
mstarzinger@chromium.org88d326b2012-04-23 12:57:22 +000015035 i::FLAG_es52_globals = true;
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000015036 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015037 v8::HandleScope scope(context->GetIsolate());
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000015038 // Introduce a variable in the prototype chain.
15039 CompileRun("__proto__.x = 42");
erik.corry@gmail.comed49e962012-04-17 11:57:53 +000015040 v8::Handle<v8::Value> result = CompileRun("var x = 43; x");
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000015041 CHECK(!result->IsUndefined());
erik.corry@gmail.comed49e962012-04-17 11:57:53 +000015042 CHECK_EQ(43, result->Int32Value());
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000015043}
kasperl@chromium.org68ac0092009-07-09 06:00:35 +000015044
15045
15046// Regression test for issue 398.
15047// If a function is added to an object, creating a constant function
15048// field, and the result is cloned, replacing the constant function on the
15049// original should not affect the clone.
15050// See http://code.google.com/p/v8/issues/detail?id=398
15051THREADED_TEST(ReplaceConstantFunction) {
kasperl@chromium.org68ac0092009-07-09 06:00:35 +000015052 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015053 v8::HandleScope scope(context->GetIsolate());
kasperl@chromium.org68ac0092009-07-09 06:00:35 +000015054 v8::Handle<v8::Object> obj = v8::Object::New();
15055 v8::Handle<v8::FunctionTemplate> func_templ = v8::FunctionTemplate::New();
15056 v8::Handle<v8::String> foo_string = v8::String::New("foo");
15057 obj->Set(foo_string, func_templ->GetFunction());
15058 v8::Handle<v8::Object> obj_clone = obj->Clone();
15059 obj_clone->Set(foo_string, v8::String::New("Hello"));
15060 CHECK(!obj->Get(foo_string)->IsUndefined());
15061}
kasperl@chromium.orge959c182009-07-27 08:59:04 +000015062
15063
15064// Regression test for http://crbug.com/16276.
15065THREADED_TEST(Regress16276) {
kasperl@chromium.orge959c182009-07-27 08:59:04 +000015066 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015067 v8::HandleScope scope(context->GetIsolate());
kasperl@chromium.orge959c182009-07-27 08:59:04 +000015068 // Force the IC in f to be a dictionary load IC.
15069 CompileRun("function f(obj) { return obj.x; }\n"
15070 "var obj = { x: { foo: 42 }, y: 87 };\n"
15071 "var x = obj.x;\n"
15072 "delete obj.y;\n"
15073 "for (var i = 0; i < 5; i++) f(obj);");
15074 // Detach the global object to make 'this' refer directly to the
15075 // global object (not the proxy), and make sure that the dictionary
15076 // load IC doesn't mess up loading directly from the global object.
15077 context->DetachGlobal();
15078 CHECK_EQ(42, CompileRun("f(this).foo")->Int32Value());
15079}
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015080
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015081static void CheckElementValue(i::Isolate* isolate,
15082 int expected,
15083 i::Handle<i::Object> obj,
15084 int offset) {
15085 i::Object* element = obj->GetElement(isolate, offset)->ToObjectChecked();
15086 CHECK_EQ(expected, i::Smi::cast(element)->value());
15087}
15088
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015089
15090THREADED_TEST(PixelArray) {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015091 LocalContext context;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015092 i::Isolate* isolate = CcTest::i_isolate();
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015093 i::Factory* factory = isolate->factory();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015094 v8::HandleScope scope(context->GetIsolate());
ager@chromium.orgc4c92722009-11-18 14:12:51 +000015095 const int kElementCount = 260;
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015096 uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(kElementCount));
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000015097 i::Handle<i::ExternalPixelArray> pixels =
15098 i::Handle<i::ExternalPixelArray>::cast(
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000015099 factory->NewExternalArray(kElementCount,
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000015100 v8::kExternalPixelArray,
15101 pixel_data));
15102 // Force GC to trigger verification.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015103 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015104 for (int i = 0; i < kElementCount; i++) {
ager@chromium.orgc4c92722009-11-18 14:12:51 +000015105 pixels->set(i, i % 256);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015106 }
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000015107 // Force GC to trigger verification.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015108 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015109 for (int i = 0; i < kElementCount; i++) {
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +000015110 CHECK_EQ(i % 256, pixels->get_scalar(i));
ager@chromium.orgc4c92722009-11-18 14:12:51 +000015111 CHECK_EQ(i % 256, pixel_data[i]);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015112 }
15113
15114 v8::Handle<v8::Object> obj = v8::Object::New();
15115 i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
15116 // Set the elements to be the pixels.
15117 // jsobj->set_elements(*pixels);
15118 obj->SetIndexedPropertiesToPixelData(pixel_data, kElementCount);
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015119 CheckElementValue(isolate, 1, jsobj, 1);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015120 obj->Set(v8_str("field"), v8::Int32::New(1503));
15121 context->Global()->Set(v8_str("pixels"), obj);
15122 v8::Handle<v8::Value> result = CompileRun("pixels.field");
15123 CHECK_EQ(1503, result->Int32Value());
15124 result = CompileRun("pixels[1]");
15125 CHECK_EQ(1, result->Int32Value());
sgjesse@chromium.org9eceac12009-09-30 07:18:41 +000015126
15127 result = CompileRun("var sum = 0;"
15128 "for (var i = 0; i < 8; i++) {"
15129 " sum += pixels[i] = pixels[i] = -i;"
15130 "}"
15131 "sum;");
15132 CHECK_EQ(-28, result->Int32Value());
15133
15134 result = CompileRun("var sum = 0;"
15135 "for (var i = 0; i < 8; i++) {"
15136 " sum += pixels[i] = pixels[i] = 0;"
15137 "}"
15138 "sum;");
15139 CHECK_EQ(0, result->Int32Value());
15140
15141 result = CompileRun("var sum = 0;"
15142 "for (var i = 0; i < 8; i++) {"
15143 " sum += pixels[i] = pixels[i] = 255;"
15144 "}"
15145 "sum;");
15146 CHECK_EQ(8 * 255, result->Int32Value());
15147
15148 result = CompileRun("var sum = 0;"
15149 "for (var i = 0; i < 8; i++) {"
15150 " sum += pixels[i] = pixels[i] = 256 + i;"
15151 "}"
15152 "sum;");
15153 CHECK_EQ(2076, result->Int32Value());
15154
15155 result = CompileRun("var sum = 0;"
15156 "for (var i = 0; i < 8; i++) {"
15157 " sum += pixels[i] = pixels[i] = i;"
15158 "}"
15159 "sum;");
15160 CHECK_EQ(28, result->Int32Value());
15161
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015162 result = CompileRun("var sum = 0;"
15163 "for (var i = 0; i < 8; i++) {"
15164 " sum += pixels[i];"
15165 "}"
15166 "sum;");
15167 CHECK_EQ(28, result->Int32Value());
15168
ulan@chromium.org09d7ab52013-02-25 15:50:35 +000015169 i::Handle<i::Smi> value(i::Smi::FromInt(2),
15170 reinterpret_cast<i::Isolate*>(context->GetIsolate()));
jkummerow@chromium.org486075a2011-09-07 12:44:28 +000015171 i::Handle<i::Object> no_failure;
yangguo@chromium.orgab30bb82012-02-24 14:41:46 +000015172 no_failure =
15173 i::JSObject::SetElement(jsobj, 1, value, NONE, i::kNonStrictMode);
jkummerow@chromium.org486075a2011-09-07 12:44:28 +000015174 ASSERT(!no_failure.is_null());
15175 i::USE(no_failure);
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015176 CheckElementValue(isolate, 2, jsobj, 1);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015177 *value.location() = i::Smi::FromInt(256);
yangguo@chromium.orgab30bb82012-02-24 14:41:46 +000015178 no_failure =
15179 i::JSObject::SetElement(jsobj, 1, value, NONE, i::kNonStrictMode);
jkummerow@chromium.org486075a2011-09-07 12:44:28 +000015180 ASSERT(!no_failure.is_null());
15181 i::USE(no_failure);
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015182 CheckElementValue(isolate, 255, jsobj, 1);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015183 *value.location() = i::Smi::FromInt(-1);
yangguo@chromium.orgab30bb82012-02-24 14:41:46 +000015184 no_failure =
15185 i::JSObject::SetElement(jsobj, 1, value, NONE, i::kNonStrictMode);
jkummerow@chromium.org486075a2011-09-07 12:44:28 +000015186 ASSERT(!no_failure.is_null());
15187 i::USE(no_failure);
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015188 CheckElementValue(isolate, 0, jsobj, 1);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015189
15190 result = CompileRun("for (var i = 0; i < 8; i++) {"
15191 " pixels[i] = (i * 65) - 109;"
15192 "}"
15193 "pixels[1] + pixels[6];");
15194 CHECK_EQ(255, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015195 CheckElementValue(isolate, 0, jsobj, 0);
15196 CheckElementValue(isolate, 0, jsobj, 1);
15197 CheckElementValue(isolate, 21, jsobj, 2);
15198 CheckElementValue(isolate, 86, jsobj, 3);
15199 CheckElementValue(isolate, 151, jsobj, 4);
15200 CheckElementValue(isolate, 216, jsobj, 5);
15201 CheckElementValue(isolate, 255, jsobj, 6);
15202 CheckElementValue(isolate, 255, jsobj, 7);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015203 result = CompileRun("var sum = 0;"
15204 "for (var i = 0; i < 8; i++) {"
15205 " sum += pixels[i];"
15206 "}"
15207 "sum;");
15208 CHECK_EQ(984, result->Int32Value());
15209
15210 result = CompileRun("for (var i = 0; i < 8; i++) {"
15211 " pixels[i] = (i * 1.1);"
15212 "}"
15213 "pixels[1] + pixels[6];");
15214 CHECK_EQ(8, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015215 CheckElementValue(isolate, 0, jsobj, 0);
15216 CheckElementValue(isolate, 1, jsobj, 1);
15217 CheckElementValue(isolate, 2, jsobj, 2);
15218 CheckElementValue(isolate, 3, jsobj, 3);
15219 CheckElementValue(isolate, 4, jsobj, 4);
15220 CheckElementValue(isolate, 6, jsobj, 5);
15221 CheckElementValue(isolate, 7, jsobj, 6);
15222 CheckElementValue(isolate, 8, jsobj, 7);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015223
15224 result = CompileRun("for (var i = 0; i < 8; i++) {"
15225 " pixels[7] = undefined;"
15226 "}"
15227 "pixels[7];");
15228 CHECK_EQ(0, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015229 CheckElementValue(isolate, 0, jsobj, 7);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015230
15231 result = CompileRun("for (var i = 0; i < 8; i++) {"
15232 " pixels[6] = '2.3';"
15233 "}"
15234 "pixels[6];");
15235 CHECK_EQ(2, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015236 CheckElementValue(isolate, 2, jsobj, 6);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015237
15238 result = CompileRun("for (var i = 0; i < 8; i++) {"
15239 " pixels[5] = NaN;"
15240 "}"
15241 "pixels[5];");
15242 CHECK_EQ(0, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015243 CheckElementValue(isolate, 0, jsobj, 5);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015244
15245 result = CompileRun("for (var i = 0; i < 8; i++) {"
15246 " pixels[8] = Infinity;"
15247 "}"
15248 "pixels[8];");
15249 CHECK_EQ(255, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015250 CheckElementValue(isolate, 255, jsobj, 8);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015251
15252 result = CompileRun("for (var i = 0; i < 8; i++) {"
15253 " pixels[9] = -Infinity;"
15254 "}"
15255 "pixels[9];");
15256 CHECK_EQ(0, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015257 CheckElementValue(isolate, 0, jsobj, 9);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015258
15259 result = CompileRun("pixels[3] = 33;"
15260 "delete pixels[3];"
15261 "pixels[3];");
15262 CHECK_EQ(33, result->Int32Value());
15263
15264 result = CompileRun("pixels[0] = 10; pixels[1] = 11;"
15265 "pixels[2] = 12; pixels[3] = 13;"
15266 "pixels.__defineGetter__('2',"
15267 "function() { return 120; });"
15268 "pixels[2];");
15269 CHECK_EQ(12, result->Int32Value());
15270
15271 result = CompileRun("var js_array = new Array(40);"
15272 "js_array[0] = 77;"
15273 "js_array;");
15274 CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
15275
15276 result = CompileRun("pixels[1] = 23;"
15277 "pixels.__proto__ = [];"
15278 "js_array.__proto__ = pixels;"
15279 "js_array.concat(pixels);");
15280 CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
15281 CHECK_EQ(23, v8::Object::Cast(*result)->Get(v8_str("1"))->Int32Value());
15282
sgjesse@chromium.org9eceac12009-09-30 07:18:41 +000015283 result = CompileRun("pixels[1] = 23;");
15284 CHECK_EQ(23, result->Int32Value());
15285
ager@chromium.orgc4c92722009-11-18 14:12:51 +000015286 // Test for index greater than 255. Regression test for:
15287 // http://code.google.com/p/chromium/issues/detail?id=26337.
15288 result = CompileRun("pixels[256] = 255;");
15289 CHECK_EQ(255, result->Int32Value());
15290 result = CompileRun("var i = 0;"
15291 "for (var j = 0; j < 8; j++) { i = pixels[256]; }"
15292 "i");
15293 CHECK_EQ(255, result->Int32Value());
15294
ricow@chromium.org83aa5492011-02-07 12:42:56 +000015295 // Make sure that pixel array ICs recognize when a non-pixel array
15296 // is passed to it.
15297 result = CompileRun("function pa_load(p) {"
15298 " var sum = 0;"
15299 " for (var j = 0; j < 256; j++) { sum += p[j]; }"
15300 " return sum;"
15301 "}"
15302 "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
15303 "for (var i = 0; i < 10; ++i) { pa_load(pixels); }"
15304 "just_ints = new Object();"
15305 "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
15306 "for (var i = 0; i < 10; ++i) {"
15307 " result = pa_load(just_ints);"
15308 "}"
15309 "result");
15310 CHECK_EQ(32640, result->Int32Value());
15311
15312 // Make sure that pixel array ICs recognize out-of-bound accesses.
15313 result = CompileRun("function pa_load(p, start) {"
15314 " var sum = 0;"
15315 " for (var j = start; j < 256; j++) { sum += p[j]; }"
15316 " return sum;"
15317 "}"
15318 "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
15319 "for (var i = 0; i < 10; ++i) { pa_load(pixels,0); }"
15320 "for (var i = 0; i < 10; ++i) {"
15321 " result = pa_load(pixels,-10);"
15322 "}"
15323 "result");
15324 CHECK_EQ(0, result->Int32Value());
15325
15326 // Make sure that generic ICs properly handles a pixel array.
15327 result = CompileRun("function pa_load(p) {"
15328 " var sum = 0;"
15329 " for (var j = 0; j < 256; j++) { sum += p[j]; }"
15330 " return sum;"
15331 "}"
15332 "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
15333 "just_ints = new Object();"
15334 "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
15335 "for (var i = 0; i < 10; ++i) { pa_load(just_ints); }"
15336 "for (var i = 0; i < 10; ++i) {"
15337 " result = pa_load(pixels);"
15338 "}"
15339 "result");
15340 CHECK_EQ(32640, result->Int32Value());
15341
15342 // Make sure that generic load ICs recognize out-of-bound accesses in
15343 // pixel arrays.
15344 result = CompileRun("function pa_load(p, start) {"
15345 " var sum = 0;"
15346 " for (var j = start; j < 256; j++) { sum += p[j]; }"
15347 " return sum;"
15348 "}"
15349 "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
15350 "just_ints = new Object();"
15351 "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
15352 "for (var i = 0; i < 10; ++i) { pa_load(just_ints,0); }"
15353 "for (var i = 0; i < 10; ++i) { pa_load(pixels,0); }"
15354 "for (var i = 0; i < 10; ++i) {"
15355 " result = pa_load(pixels,-10);"
15356 "}"
15357 "result");
15358 CHECK_EQ(0, result->Int32Value());
15359
15360 // Make sure that generic ICs properly handles other types than pixel
15361 // arrays (that the inlined fast pixel array test leaves the right information
15362 // in the right registers).
15363 result = CompileRun("function pa_load(p) {"
15364 " var sum = 0;"
15365 " for (var j = 0; j < 256; j++) { sum += p[j]; }"
15366 " return sum;"
15367 "}"
15368 "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
15369 "just_ints = new Object();"
15370 "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
15371 "for (var i = 0; i < 10; ++i) { pa_load(just_ints); }"
15372 "for (var i = 0; i < 10; ++i) { pa_load(pixels); }"
15373 "sparse_array = new Object();"
15374 "for (var i = 0; i < 256; ++i) { sparse_array[i] = i; }"
15375 "sparse_array[1000000] = 3;"
15376 "for (var i = 0; i < 10; ++i) {"
15377 " result = pa_load(sparse_array);"
15378 "}"
15379 "result");
15380 CHECK_EQ(32640, result->Int32Value());
15381
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +000015382 // Make sure that pixel array store ICs clamp values correctly.
15383 result = CompileRun("function pa_store(p) {"
15384 " for (var j = 0; j < 256; j++) { p[j] = j * 2; }"
15385 "}"
15386 "pa_store(pixels);"
15387 "var sum = 0;"
15388 "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
15389 "sum");
15390 CHECK_EQ(48896, result->Int32Value());
15391
15392 // Make sure that pixel array stores correctly handle accesses outside
15393 // of the pixel array..
15394 result = CompileRun("function pa_store(p,start) {"
15395 " for (var j = 0; j < 256; j++) {"
15396 " p[j+start] = j * 2;"
15397 " }"
15398 "}"
15399 "pa_store(pixels,0);"
15400 "pa_store(pixels,-128);"
15401 "var sum = 0;"
15402 "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
15403 "sum");
15404 CHECK_EQ(65280, result->Int32Value());
15405
15406 // Make sure that the generic store stub correctly handle accesses outside
15407 // of the pixel array..
15408 result = CompileRun("function pa_store(p,start) {"
15409 " for (var j = 0; j < 256; j++) {"
15410 " p[j+start] = j * 2;"
15411 " }"
15412 "}"
15413 "pa_store(pixels,0);"
15414 "just_ints = new Object();"
15415 "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
15416 "pa_store(just_ints, 0);"
15417 "pa_store(pixels,-128);"
15418 "var sum = 0;"
15419 "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
15420 "sum");
15421 CHECK_EQ(65280, result->Int32Value());
15422
15423 // Make sure that the generic keyed store stub clamps pixel array values
15424 // correctly.
15425 result = CompileRun("function pa_store(p) {"
15426 " for (var j = 0; j < 256; j++) { p[j] = j * 2; }"
15427 "}"
15428 "pa_store(pixels);"
15429 "just_ints = new Object();"
15430 "pa_store(just_ints);"
15431 "pa_store(pixels);"
15432 "var sum = 0;"
15433 "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
15434 "sum");
15435 CHECK_EQ(48896, result->Int32Value());
15436
15437 // Make sure that pixel array loads are optimized by crankshaft.
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000015438 result = CompileRun("function pa_load(p) {"
15439 " var sum = 0;"
15440 " for (var i=0; i<256; ++i) {"
15441 " sum += p[i];"
15442 " }"
15443 " return sum; "
15444 "}"
15445 "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000015446 "for (var i = 0; i < 5000; ++i) {"
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000015447 " result = pa_load(pixels);"
15448 "}"
15449 "result");
15450 CHECK_EQ(32640, result->Int32Value());
15451
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000015452 // Make sure that pixel array stores are optimized by crankshaft.
15453 result = CompileRun("function pa_init(p) {"
15454 "for (var i = 0; i < 256; ++i) { p[i] = i; }"
15455 "}"
15456 "function pa_load(p) {"
15457 " var sum = 0;"
15458 " for (var i=0; i<256; ++i) {"
15459 " sum += p[i];"
15460 " }"
15461 " return sum; "
15462 "}"
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000015463 "for (var i = 0; i < 5000; ++i) {"
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000015464 " pa_init(pixels);"
15465 "}"
15466 "result = pa_load(pixels);"
15467 "result");
15468 CHECK_EQ(32640, result->Int32Value());
15469
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015470 free(pixel_data);
15471}
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000015472
ager@chromium.org96c75b52009-08-26 09:13:16 +000015473
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000015474THREADED_TEST(PixelArrayInfo) {
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000015475 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015476 v8::HandleScope scope(context->GetIsolate());
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000015477 for (int size = 0; size < 100; size += 10) {
15478 uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(size));
15479 v8::Handle<v8::Object> obj = v8::Object::New();
15480 obj->SetIndexedPropertiesToPixelData(pixel_data, size);
15481 CHECK(obj->HasIndexedPropertiesInPixelData());
15482 CHECK_EQ(pixel_data, obj->GetIndexedPropertiesPixelData());
15483 CHECK_EQ(size, obj->GetIndexedPropertiesPixelDataLength());
15484 free(pixel_data);
15485 }
15486}
15487
15488
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015489static void NotHandledIndexedPropertyGetter(
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000015490 uint32_t index,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015491 const v8::PropertyCallbackInfo<v8::Value>& info) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000015492 ApiTestFuzzer::Fuzz();
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000015493}
15494
15495
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015496static void NotHandledIndexedPropertySetter(
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000015497 uint32_t index,
15498 Local<Value> value,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015499 const v8::PropertyCallbackInfo<v8::Value>& info) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000015500 ApiTestFuzzer::Fuzz();
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000015501}
15502
15503
15504THREADED_TEST(PixelArrayWithInterceptor) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000015505 LocalContext context;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015506 i::Factory* factory = CcTest::i_isolate()->factory();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015507 v8::HandleScope scope(context->GetIsolate());
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000015508 const int kElementCount = 260;
15509 uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(kElementCount));
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000015510 i::Handle<i::ExternalPixelArray> pixels =
15511 i::Handle<i::ExternalPixelArray>::cast(
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000015512 factory->NewExternalArray(kElementCount,
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000015513 v8::kExternalPixelArray,
15514 pixel_data));
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000015515 for (int i = 0; i < kElementCount; i++) {
15516 pixels->set(i, i % 256);
15517 }
15518 v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
15519 templ->SetIndexedPropertyHandler(NotHandledIndexedPropertyGetter,
15520 NotHandledIndexedPropertySetter);
15521 v8::Handle<v8::Object> obj = templ->NewInstance();
15522 obj->SetIndexedPropertiesToPixelData(pixel_data, kElementCount);
15523 context->Global()->Set(v8_str("pixels"), obj);
15524 v8::Handle<v8::Value> result = CompileRun("pixels[1]");
15525 CHECK_EQ(1, result->Int32Value());
15526 result = CompileRun("var sum = 0;"
15527 "for (var i = 0; i < 8; i++) {"
15528 " sum += pixels[i] = pixels[i] = -i;"
15529 "}"
15530 "sum;");
15531 CHECK_EQ(-28, result->Int32Value());
15532 result = CompileRun("pixels.hasOwnProperty('1')");
15533 CHECK(result->BooleanValue());
15534 free(pixel_data);
15535}
15536
15537
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000015538static int ExternalArrayElementSize(v8::ExternalArrayType array_type) {
15539 switch (array_type) {
15540 case v8::kExternalByteArray:
15541 case v8::kExternalUnsignedByteArray:
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000015542 case v8::kExternalPixelArray:
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000015543 return 1;
15544 break;
15545 case v8::kExternalShortArray:
15546 case v8::kExternalUnsignedShortArray:
15547 return 2;
15548 break;
15549 case v8::kExternalIntArray:
15550 case v8::kExternalUnsignedIntArray:
15551 case v8::kExternalFloatArray:
15552 return 4;
15553 break;
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +000015554 case v8::kExternalDoubleArray:
15555 return 8;
15556 break;
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000015557 default:
15558 UNREACHABLE();
15559 return -1;
15560 }
15561 UNREACHABLE();
15562 return -1;
15563}
15564
15565
ager@chromium.org3811b432009-10-28 14:53:37 +000015566template <class ExternalArrayClass, class ElementType>
danno@chromium.orgf005df62013-04-30 16:36:45 +000015567static void ObjectWithExternalArrayTestHelper(
15568 Handle<Context> context,
15569 v8::Handle<Object> obj,
15570 int element_count,
15571 v8::ExternalArrayType array_type,
15572 int64_t low, int64_t high) {
ager@chromium.org3811b432009-10-28 14:53:37 +000015573 i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015574 i::Isolate* isolate = jsobj->GetIsolate();
ager@chromium.org3811b432009-10-28 14:53:37 +000015575 obj->Set(v8_str("field"), v8::Int32::New(1503));
15576 context->Global()->Set(v8_str("ext_array"), obj);
15577 v8::Handle<v8::Value> result = CompileRun("ext_array.field");
15578 CHECK_EQ(1503, result->Int32Value());
15579 result = CompileRun("ext_array[1]");
15580 CHECK_EQ(1, result->Int32Value());
15581
15582 // Check pass through of assigned smis
15583 result = CompileRun("var sum = 0;"
15584 "for (var i = 0; i < 8; i++) {"
15585 " sum += ext_array[i] = ext_array[i] = -i;"
15586 "}"
15587 "sum;");
15588 CHECK_EQ(-28, result->Int32Value());
15589
15590 // Check assigned smis
15591 result = CompileRun("for (var i = 0; i < 8; i++) {"
15592 " ext_array[i] = i;"
15593 "}"
15594 "var sum = 0;"
15595 "for (var i = 0; i < 8; i++) {"
15596 " sum += ext_array[i];"
15597 "}"
15598 "sum;");
15599 CHECK_EQ(28, result->Int32Value());
15600
15601 // Check assigned smis in reverse order
15602 result = CompileRun("for (var i = 8; --i >= 0; ) {"
15603 " ext_array[i] = i;"
15604 "}"
15605 "var sum = 0;"
15606 "for (var i = 0; i < 8; i++) {"
15607 " sum += ext_array[i];"
15608 "}"
15609 "sum;");
15610 CHECK_EQ(28, result->Int32Value());
15611
15612 // Check pass through of assigned HeapNumbers
15613 result = CompileRun("var sum = 0;"
15614 "for (var i = 0; i < 16; i+=2) {"
15615 " sum += ext_array[i] = ext_array[i] = (-i * 0.5);"
15616 "}"
15617 "sum;");
15618 CHECK_EQ(-28, result->Int32Value());
15619
15620 // Check assigned HeapNumbers
15621 result = CompileRun("for (var i = 0; i < 16; i+=2) {"
15622 " ext_array[i] = (i * 0.5);"
15623 "}"
15624 "var sum = 0;"
15625 "for (var i = 0; i < 16; i+=2) {"
15626 " sum += ext_array[i];"
15627 "}"
15628 "sum;");
15629 CHECK_EQ(28, result->Int32Value());
15630
15631 // Check assigned HeapNumbers in reverse order
15632 result = CompileRun("for (var i = 14; i >= 0; i-=2) {"
15633 " ext_array[i] = (i * 0.5);"
15634 "}"
15635 "var sum = 0;"
15636 "for (var i = 0; i < 16; i+=2) {"
15637 " sum += ext_array[i];"
15638 "}"
15639 "sum;");
15640 CHECK_EQ(28, result->Int32Value());
15641
15642 i::ScopedVector<char> test_buf(1024);
15643
15644 // Check legal boundary conditions.
15645 // The repeated loads and stores ensure the ICs are exercised.
15646 const char* boundary_program =
15647 "var res = 0;"
15648 "for (var i = 0; i < 16; i++) {"
15649 " ext_array[i] = %lld;"
15650 " if (i > 8) {"
15651 " res = ext_array[i];"
15652 " }"
15653 "}"
15654 "res;";
15655 i::OS::SNPrintF(test_buf,
15656 boundary_program,
15657 low);
15658 result = CompileRun(test_buf.start());
15659 CHECK_EQ(low, result->IntegerValue());
15660
15661 i::OS::SNPrintF(test_buf,
15662 boundary_program,
15663 high);
15664 result = CompileRun(test_buf.start());
15665 CHECK_EQ(high, result->IntegerValue());
15666
15667 // Check misprediction of type in IC.
15668 result = CompileRun("var tmp_array = ext_array;"
15669 "var sum = 0;"
15670 "for (var i = 0; i < 8; i++) {"
15671 " tmp_array[i] = i;"
15672 " sum += tmp_array[i];"
15673 " if (i == 4) {"
15674 " tmp_array = {};"
15675 " }"
15676 "}"
15677 "sum;");
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000015678 // Force GC to trigger verification.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015679 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org3811b432009-10-28 14:53:37 +000015680 CHECK_EQ(28, result->Int32Value());
15681
15682 // Make sure out-of-range loads do not throw.
15683 i::OS::SNPrintF(test_buf,
15684 "var caught_exception = false;"
15685 "try {"
15686 " ext_array[%d];"
15687 "} catch (e) {"
15688 " caught_exception = true;"
15689 "}"
15690 "caught_exception;",
danno@chromium.orgf005df62013-04-30 16:36:45 +000015691 element_count);
ager@chromium.org3811b432009-10-28 14:53:37 +000015692 result = CompileRun(test_buf.start());
15693 CHECK_EQ(false, result->BooleanValue());
15694
15695 // Make sure out-of-range stores do not throw.
15696 i::OS::SNPrintF(test_buf,
15697 "var caught_exception = false;"
15698 "try {"
15699 " ext_array[%d] = 1;"
15700 "} catch (e) {"
15701 " caught_exception = true;"
15702 "}"
15703 "caught_exception;",
danno@chromium.orgf005df62013-04-30 16:36:45 +000015704 element_count);
ager@chromium.org3811b432009-10-28 14:53:37 +000015705 result = CompileRun(test_buf.start());
15706 CHECK_EQ(false, result->BooleanValue());
15707
15708 // Check other boundary conditions, values and operations.
15709 result = CompileRun("for (var i = 0; i < 8; i++) {"
15710 " ext_array[7] = undefined;"
15711 "}"
15712 "ext_array[7];");
15713 CHECK_EQ(0, result->Int32Value());
yangguo@chromium.org56454712012-02-16 15:33:53 +000015714 if (array_type == v8::kExternalDoubleArray ||
15715 array_type == v8::kExternalFloatArray) {
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015716 CHECK_EQ(static_cast<int>(i::OS::nan_value()),
15717 static_cast<int>(
15718 jsobj->GetElement(isolate, 7)->ToObjectChecked()->Number()));
yangguo@chromium.org56454712012-02-16 15:33:53 +000015719 } else {
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015720 CheckElementValue(isolate, 0, jsobj, 7);
yangguo@chromium.org56454712012-02-16 15:33:53 +000015721 }
ager@chromium.org3811b432009-10-28 14:53:37 +000015722
15723 result = CompileRun("for (var i = 0; i < 8; i++) {"
15724 " ext_array[6] = '2.3';"
15725 "}"
15726 "ext_array[6];");
15727 CHECK_EQ(2, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015728 CHECK_EQ(2,
15729 static_cast<int>(
15730 jsobj->GetElement(isolate, 6)->ToObjectChecked()->Number()));
ager@chromium.org3811b432009-10-28 14:53:37 +000015731
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +000015732 if (array_type != v8::kExternalFloatArray &&
15733 array_type != v8::kExternalDoubleArray) {
ager@chromium.org3811b432009-10-28 14:53:37 +000015734 // Though the specification doesn't state it, be explicit about
15735 // converting NaNs and +/-Infinity to zero.
15736 result = CompileRun("for (var i = 0; i < 8; i++) {"
15737 " ext_array[i] = 5;"
15738 "}"
15739 "for (var i = 0; i < 8; i++) {"
15740 " ext_array[i] = NaN;"
15741 "}"
15742 "ext_array[5];");
15743 CHECK_EQ(0, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015744 CheckElementValue(isolate, 0, jsobj, 5);
ager@chromium.org3811b432009-10-28 14:53:37 +000015745
15746 result = CompileRun("for (var i = 0; i < 8; i++) {"
15747 " ext_array[i] = 5;"
15748 "}"
15749 "for (var i = 0; i < 8; i++) {"
15750 " ext_array[i] = Infinity;"
15751 "}"
15752 "ext_array[5];");
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000015753 int expected_value =
15754 (array_type == v8::kExternalPixelArray) ? 255 : 0;
15755 CHECK_EQ(expected_value, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015756 CheckElementValue(isolate, expected_value, jsobj, 5);
ager@chromium.org3811b432009-10-28 14:53:37 +000015757
15758 result = CompileRun("for (var i = 0; i < 8; i++) {"
15759 " ext_array[i] = 5;"
15760 "}"
15761 "for (var i = 0; i < 8; i++) {"
15762 " ext_array[i] = -Infinity;"
15763 "}"
15764 "ext_array[5];");
15765 CHECK_EQ(0, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015766 CheckElementValue(isolate, 0, jsobj, 5);
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +000015767
15768 // Check truncation behavior of integral arrays.
15769 const char* unsigned_data =
15770 "var source_data = [0.6, 10.6];"
15771 "var expected_results = [0, 10];";
15772 const char* signed_data =
15773 "var source_data = [0.6, 10.6, -0.6, -10.6];"
15774 "var expected_results = [0, 10, 0, -10];";
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000015775 const char* pixel_data =
15776 "var source_data = [0.6, 10.6];"
15777 "var expected_results = [1, 11];";
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +000015778 bool is_unsigned =
15779 (array_type == v8::kExternalUnsignedByteArray ||
15780 array_type == v8::kExternalUnsignedShortArray ||
15781 array_type == v8::kExternalUnsignedIntArray);
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000015782 bool is_pixel_data = array_type == v8::kExternalPixelArray;
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +000015783
15784 i::OS::SNPrintF(test_buf,
15785 "%s"
15786 "var all_passed = true;"
15787 "for (var i = 0; i < source_data.length; i++) {"
15788 " for (var j = 0; j < 8; j++) {"
15789 " ext_array[j] = source_data[i];"
15790 " }"
15791 " all_passed = all_passed &&"
15792 " (ext_array[5] == expected_results[i]);"
15793 "}"
15794 "all_passed;",
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000015795 (is_unsigned ?
15796 unsigned_data :
15797 (is_pixel_data ? pixel_data : signed_data)));
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +000015798 result = CompileRun(test_buf.start());
15799 CHECK_EQ(true, result->BooleanValue());
ager@chromium.org3811b432009-10-28 14:53:37 +000015800 }
15801
danno@chromium.orgf005df62013-04-30 16:36:45 +000015802 i::Handle<ExternalArrayClass> array(
15803 ExternalArrayClass::cast(jsobj->elements()));
15804 for (int i = 0; i < element_count; i++) {
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000015805 array->set(i, static_cast<ElementType>(i));
15806 }
danno@chromium.orgf005df62013-04-30 16:36:45 +000015807
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000015808 // Test complex assignments
15809 result = CompileRun("function ee_op_test_complex_func(sum) {"
15810 " for (var i = 0; i < 40; ++i) {"
15811 " sum += (ext_array[i] += 1);"
15812 " sum += (ext_array[i] -= 1);"
15813 " } "
15814 " return sum;"
15815 "}"
15816 "sum=0;"
15817 "for (var i=0;i<10000;++i) {"
15818 " sum=ee_op_test_complex_func(sum);"
15819 "}"
15820 "sum;");
15821 CHECK_EQ(16000000, result->Int32Value());
15822
15823 // Test count operations
15824 result = CompileRun("function ee_op_test_count_func(sum) {"
15825 " for (var i = 0; i < 40; ++i) {"
15826 " sum += (++ext_array[i]);"
15827 " sum += (--ext_array[i]);"
15828 " } "
15829 " return sum;"
15830 "}"
15831 "sum=0;"
15832 "for (var i=0;i<10000;++i) {"
15833 " sum=ee_op_test_count_func(sum);"
15834 "}"
15835 "sum;");
15836 CHECK_EQ(16000000, result->Int32Value());
15837
ager@chromium.org3811b432009-10-28 14:53:37 +000015838 result = CompileRun("ext_array[3] = 33;"
15839 "delete ext_array[3];"
15840 "ext_array[3];");
15841 CHECK_EQ(33, result->Int32Value());
15842
15843 result = CompileRun("ext_array[0] = 10; ext_array[1] = 11;"
15844 "ext_array[2] = 12; ext_array[3] = 13;"
15845 "ext_array.__defineGetter__('2',"
15846 "function() { return 120; });"
15847 "ext_array[2];");
15848 CHECK_EQ(12, result->Int32Value());
15849
15850 result = CompileRun("var js_array = new Array(40);"
15851 "js_array[0] = 77;"
15852 "js_array;");
15853 CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
15854
15855 result = CompileRun("ext_array[1] = 23;"
15856 "ext_array.__proto__ = [];"
15857 "js_array.__proto__ = ext_array;"
15858 "js_array.concat(ext_array);");
15859 CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
15860 CHECK_EQ(23, v8::Object::Cast(*result)->Get(v8_str("1"))->Int32Value());
15861
15862 result = CompileRun("ext_array[1] = 23;");
15863 CHECK_EQ(23, result->Int32Value());
danno@chromium.orgf005df62013-04-30 16:36:45 +000015864}
15865
15866
15867template <class ExternalArrayClass, class ElementType>
15868static void ExternalArrayTestHelper(v8::ExternalArrayType array_type,
15869 int64_t low,
15870 int64_t high) {
15871 LocalContext context;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015872 i::Isolate* isolate = CcTest::i_isolate();
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015873 i::Factory* factory = isolate->factory();
danno@chromium.orgf005df62013-04-30 16:36:45 +000015874 v8::HandleScope scope(context->GetIsolate());
15875 const int kElementCount = 40;
15876 int element_size = ExternalArrayElementSize(array_type);
15877 ElementType* array_data =
15878 static_cast<ElementType*>(malloc(kElementCount * element_size));
15879 i::Handle<ExternalArrayClass> array =
15880 i::Handle<ExternalArrayClass>::cast(
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000015881 factory->NewExternalArray(kElementCount, array_type, array_data));
danno@chromium.orgf005df62013-04-30 16:36:45 +000015882 // Force GC to trigger verification.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015883 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
danno@chromium.orgf005df62013-04-30 16:36:45 +000015884 for (int i = 0; i < kElementCount; i++) {
15885 array->set(i, static_cast<ElementType>(i));
15886 }
15887 // Force GC to trigger verification.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015888 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
danno@chromium.orgf005df62013-04-30 16:36:45 +000015889 for (int i = 0; i < kElementCount; i++) {
15890 CHECK_EQ(static_cast<int64_t>(i),
15891 static_cast<int64_t>(array->get_scalar(i)));
15892 CHECK_EQ(static_cast<int64_t>(i), static_cast<int64_t>(array_data[i]));
15893 }
15894
15895 v8::Handle<v8::Object> obj = v8::Object::New();
15896 i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
15897 // Set the elements to be the external array.
15898 obj->SetIndexedPropertiesToExternalArrayData(array_data,
15899 array_type,
15900 kElementCount);
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015901 CHECK_EQ(1,
15902 static_cast<int>(
15903 jsobj->GetElement(isolate, 1)->ToObjectChecked()->Number()));
danno@chromium.orgf005df62013-04-30 16:36:45 +000015904
15905 ObjectWithExternalArrayTestHelper<ExternalArrayClass, ElementType>(
15906 context.local(), obj, kElementCount, array_type, low, high);
15907
15908 v8::Handle<v8::Value> result;
ager@chromium.org3811b432009-10-28 14:53:37 +000015909
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +000015910 // Test more complex manipulations which cause eax to contain values
15911 // that won't be completely overwritten by loads from the arrays.
15912 // This catches bugs in the instructions used for the KeyedLoadIC
15913 // for byte and word types.
15914 {
15915 const int kXSize = 300;
15916 const int kYSize = 300;
15917 const int kLargeElementCount = kXSize * kYSize * 4;
15918 ElementType* large_array_data =
15919 static_cast<ElementType*>(malloc(kLargeElementCount * element_size));
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +000015920 v8::Handle<v8::Object> large_obj = v8::Object::New();
15921 // Set the elements to be the external array.
15922 large_obj->SetIndexedPropertiesToExternalArrayData(large_array_data,
15923 array_type,
15924 kLargeElementCount);
15925 context->Global()->Set(v8_str("large_array"), large_obj);
15926 // Initialize contents of a few rows.
15927 for (int x = 0; x < 300; x++) {
15928 int row = 0;
15929 int offset = row * 300 * 4;
15930 large_array_data[offset + 4 * x + 0] = (ElementType) 127;
15931 large_array_data[offset + 4 * x + 1] = (ElementType) 0;
15932 large_array_data[offset + 4 * x + 2] = (ElementType) 0;
15933 large_array_data[offset + 4 * x + 3] = (ElementType) 127;
15934 row = 150;
15935 offset = row * 300 * 4;
15936 large_array_data[offset + 4 * x + 0] = (ElementType) 127;
15937 large_array_data[offset + 4 * x + 1] = (ElementType) 0;
15938 large_array_data[offset + 4 * x + 2] = (ElementType) 0;
15939 large_array_data[offset + 4 * x + 3] = (ElementType) 127;
15940 row = 298;
15941 offset = row * 300 * 4;
15942 large_array_data[offset + 4 * x + 0] = (ElementType) 127;
15943 large_array_data[offset + 4 * x + 1] = (ElementType) 0;
15944 large_array_data[offset + 4 * x + 2] = (ElementType) 0;
15945 large_array_data[offset + 4 * x + 3] = (ElementType) 127;
15946 }
15947 // The goal of the code below is to make "offset" large enough
15948 // that the computation of the index (which goes into eax) has
15949 // high bits set which will not be overwritten by a byte or short
15950 // load.
15951 result = CompileRun("var failed = false;"
15952 "var offset = 0;"
15953 "for (var i = 0; i < 300; i++) {"
15954 " if (large_array[4 * i] != 127 ||"
15955 " large_array[4 * i + 1] != 0 ||"
15956 " large_array[4 * i + 2] != 0 ||"
15957 " large_array[4 * i + 3] != 127) {"
15958 " failed = true;"
15959 " }"
15960 "}"
15961 "offset = 150 * 300 * 4;"
15962 "for (var i = 0; i < 300; i++) {"
15963 " if (large_array[offset + 4 * i] != 127 ||"
15964 " large_array[offset + 4 * i + 1] != 0 ||"
15965 " large_array[offset + 4 * i + 2] != 0 ||"
15966 " large_array[offset + 4 * i + 3] != 127) {"
15967 " failed = true;"
15968 " }"
15969 "}"
15970 "offset = 298 * 300 * 4;"
15971 "for (var i = 0; i < 300; i++) {"
15972 " if (large_array[offset + 4 * i] != 127 ||"
15973 " large_array[offset + 4 * i + 1] != 0 ||"
15974 " large_array[offset + 4 * i + 2] != 0 ||"
15975 " large_array[offset + 4 * i + 3] != 127) {"
15976 " failed = true;"
15977 " }"
15978 "}"
15979 "!failed;");
15980 CHECK_EQ(true, result->BooleanValue());
15981 free(large_array_data);
15982 }
15983
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000015984 // The "" property descriptor is overloaded to store information about
15985 // the external array. Ensure that setting and accessing the "" property
15986 // works (it should overwrite the information cached about the external
15987 // array in the DescriptorArray) in various situations.
15988 result = CompileRun("ext_array[''] = 23; ext_array['']");
15989 CHECK_EQ(23, result->Int32Value());
15990
15991 // Property "" set after the external array is associated with the object.
15992 {
15993 v8::Handle<v8::Object> obj2 = v8::Object::New();
15994 obj2->Set(v8_str("ee_test_field"), v8::Int32::New(256));
15995 obj2->Set(v8_str(""), v8::Int32::New(1503));
15996 // Set the elements to be the external array.
15997 obj2->SetIndexedPropertiesToExternalArrayData(array_data,
15998 array_type,
15999 kElementCount);
16000 context->Global()->Set(v8_str("ext_array"), obj2);
16001 result = CompileRun("ext_array['']");
16002 CHECK_EQ(1503, result->Int32Value());
16003 }
16004
16005 // Property "" set after the external array is associated with the object.
16006 {
16007 v8::Handle<v8::Object> obj2 = v8::Object::New();
16008 obj2->Set(v8_str("ee_test_field_2"), v8::Int32::New(256));
16009 // Set the elements to be the external array.
16010 obj2->SetIndexedPropertiesToExternalArrayData(array_data,
16011 array_type,
16012 kElementCount);
16013 obj2->Set(v8_str(""), v8::Int32::New(1503));
16014 context->Global()->Set(v8_str("ext_array"), obj2);
16015 result = CompileRun("ext_array['']");
16016 CHECK_EQ(1503, result->Int32Value());
16017 }
16018
16019 // Should reuse the map from previous test.
16020 {
16021 v8::Handle<v8::Object> obj2 = v8::Object::New();
16022 obj2->Set(v8_str("ee_test_field_2"), v8::Int32::New(256));
16023 // Set the elements to be the external array. Should re-use the map
16024 // from previous test.
16025 obj2->SetIndexedPropertiesToExternalArrayData(array_data,
16026 array_type,
16027 kElementCount);
16028 context->Global()->Set(v8_str("ext_array"), obj2);
16029 result = CompileRun("ext_array['']");
16030 }
16031
16032 // Property "" is a constant function that shouldn't not be interfered with
16033 // when an external array is set.
16034 {
16035 v8::Handle<v8::Object> obj2 = v8::Object::New();
16036 // Start
16037 obj2->Set(v8_str("ee_test_field3"), v8::Int32::New(256));
16038
16039 // Add a constant function to an object.
16040 context->Global()->Set(v8_str("ext_array"), obj2);
16041 result = CompileRun("ext_array[''] = function() {return 1503;};"
16042 "ext_array['']();");
16043
16044 // Add an external array transition to the same map that
16045 // has the constant transition.
16046 v8::Handle<v8::Object> obj3 = v8::Object::New();
16047 obj3->Set(v8_str("ee_test_field3"), v8::Int32::New(256));
16048 obj3->SetIndexedPropertiesToExternalArrayData(array_data,
16049 array_type,
16050 kElementCount);
16051 context->Global()->Set(v8_str("ext_array"), obj3);
16052 }
16053
16054 // If a external array transition is in the map, it should get clobbered
16055 // by a constant function.
16056 {
16057 // Add an external array transition.
16058 v8::Handle<v8::Object> obj3 = v8::Object::New();
16059 obj3->Set(v8_str("ee_test_field4"), v8::Int32::New(256));
16060 obj3->SetIndexedPropertiesToExternalArrayData(array_data,
16061 array_type,
16062 kElementCount);
16063
16064 // Add a constant function to the same map that just got an external array
16065 // transition.
16066 v8::Handle<v8::Object> obj2 = v8::Object::New();
16067 obj2->Set(v8_str("ee_test_field4"), v8::Int32::New(256));
16068 context->Global()->Set(v8_str("ext_array"), obj2);
16069 result = CompileRun("ext_array[''] = function() {return 1503;};"
16070 "ext_array['']();");
16071 }
16072
ager@chromium.org3811b432009-10-28 14:53:37 +000016073 free(array_data);
16074}
16075
16076
16077THREADED_TEST(ExternalByteArray) {
lrn@chromium.org32d961d2010-06-30 09:09:34 +000016078 ExternalArrayTestHelper<i::ExternalByteArray, int8_t>(
ager@chromium.org3811b432009-10-28 14:53:37 +000016079 v8::kExternalByteArray,
16080 -128,
16081 127);
16082}
16083
16084
16085THREADED_TEST(ExternalUnsignedByteArray) {
lrn@chromium.org32d961d2010-06-30 09:09:34 +000016086 ExternalArrayTestHelper<i::ExternalUnsignedByteArray, uint8_t>(
ager@chromium.org3811b432009-10-28 14:53:37 +000016087 v8::kExternalUnsignedByteArray,
16088 0,
16089 255);
16090}
16091
16092
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000016093THREADED_TEST(ExternalPixelArray) {
16094 ExternalArrayTestHelper<i::ExternalPixelArray, uint8_t>(
16095 v8::kExternalPixelArray,
16096 0,
16097 255);
16098}
16099
16100
ager@chromium.org3811b432009-10-28 14:53:37 +000016101THREADED_TEST(ExternalShortArray) {
lrn@chromium.org32d961d2010-06-30 09:09:34 +000016102 ExternalArrayTestHelper<i::ExternalShortArray, int16_t>(
ager@chromium.org3811b432009-10-28 14:53:37 +000016103 v8::kExternalShortArray,
16104 -32768,
16105 32767);
16106}
16107
16108
16109THREADED_TEST(ExternalUnsignedShortArray) {
lrn@chromium.org32d961d2010-06-30 09:09:34 +000016110 ExternalArrayTestHelper<i::ExternalUnsignedShortArray, uint16_t>(
ager@chromium.org3811b432009-10-28 14:53:37 +000016111 v8::kExternalUnsignedShortArray,
16112 0,
16113 65535);
16114}
16115
16116
16117THREADED_TEST(ExternalIntArray) {
lrn@chromium.org32d961d2010-06-30 09:09:34 +000016118 ExternalArrayTestHelper<i::ExternalIntArray, int32_t>(
ager@chromium.org3811b432009-10-28 14:53:37 +000016119 v8::kExternalIntArray,
16120 INT_MIN, // -2147483648
16121 INT_MAX); // 2147483647
16122}
16123
16124
16125THREADED_TEST(ExternalUnsignedIntArray) {
lrn@chromium.org32d961d2010-06-30 09:09:34 +000016126 ExternalArrayTestHelper<i::ExternalUnsignedIntArray, uint32_t>(
ager@chromium.org3811b432009-10-28 14:53:37 +000016127 v8::kExternalUnsignedIntArray,
16128 0,
16129 UINT_MAX); // 4294967295
16130}
16131
16132
16133THREADED_TEST(ExternalFloatArray) {
lrn@chromium.org32d961d2010-06-30 09:09:34 +000016134 ExternalArrayTestHelper<i::ExternalFloatArray, float>(
ager@chromium.org3811b432009-10-28 14:53:37 +000016135 v8::kExternalFloatArray,
16136 -500,
16137 500);
16138}
16139
16140
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +000016141THREADED_TEST(ExternalDoubleArray) {
16142 ExternalArrayTestHelper<i::ExternalDoubleArray, double>(
16143 v8::kExternalDoubleArray,
16144 -500,
16145 500);
16146}
16147
16148
ager@chromium.org3811b432009-10-28 14:53:37 +000016149THREADED_TEST(ExternalArrays) {
16150 TestExternalByteArray();
16151 TestExternalUnsignedByteArray();
16152 TestExternalShortArray();
16153 TestExternalUnsignedShortArray();
16154 TestExternalIntArray();
16155 TestExternalUnsignedIntArray();
16156 TestExternalFloatArray();
16157}
16158
16159
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016160void ExternalArrayInfoTestHelper(v8::ExternalArrayType array_type) {
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016161 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016162 v8::HandleScope scope(context->GetIsolate());
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016163 for (int size = 0; size < 100; size += 10) {
16164 int element_size = ExternalArrayElementSize(array_type);
16165 void* external_data = malloc(size * element_size);
16166 v8::Handle<v8::Object> obj = v8::Object::New();
16167 obj->SetIndexedPropertiesToExternalArrayData(
16168 external_data, array_type, size);
16169 CHECK(obj->HasIndexedPropertiesInExternalArrayData());
16170 CHECK_EQ(external_data, obj->GetIndexedPropertiesExternalArrayData());
16171 CHECK_EQ(array_type, obj->GetIndexedPropertiesExternalArrayDataType());
16172 CHECK_EQ(size, obj->GetIndexedPropertiesExternalArrayDataLength());
16173 free(external_data);
16174 }
16175}
16176
16177
16178THREADED_TEST(ExternalArrayInfo) {
16179 ExternalArrayInfoTestHelper(v8::kExternalByteArray);
16180 ExternalArrayInfoTestHelper(v8::kExternalUnsignedByteArray);
16181 ExternalArrayInfoTestHelper(v8::kExternalShortArray);
16182 ExternalArrayInfoTestHelper(v8::kExternalUnsignedShortArray);
16183 ExternalArrayInfoTestHelper(v8::kExternalIntArray);
16184 ExternalArrayInfoTestHelper(v8::kExternalUnsignedIntArray);
16185 ExternalArrayInfoTestHelper(v8::kExternalFloatArray);
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +000016186 ExternalArrayInfoTestHelper(v8::kExternalDoubleArray);
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000016187 ExternalArrayInfoTestHelper(v8::kExternalPixelArray);
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016188}
16189
16190
danno@chromium.org412fa512012-09-14 13:28:26 +000016191void ExternalArrayLimitTestHelper(v8::ExternalArrayType array_type, int size) {
16192 v8::Handle<v8::Object> obj = v8::Object::New();
16193 v8::V8::SetFatalErrorHandler(StoringErrorCallback);
16194 last_location = last_message = NULL;
16195 obj->SetIndexedPropertiesToExternalArrayData(NULL, array_type, size);
16196 CHECK(!obj->HasIndexedPropertiesInExternalArrayData());
16197 CHECK_NE(NULL, last_location);
16198 CHECK_NE(NULL, last_message);
16199}
16200
16201
16202TEST(ExternalArrayLimits) {
danno@chromium.org412fa512012-09-14 13:28:26 +000016203 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016204 v8::HandleScope scope(context->GetIsolate());
danno@chromium.org412fa512012-09-14 13:28:26 +000016205 ExternalArrayLimitTestHelper(v8::kExternalByteArray, 0x40000000);
16206 ExternalArrayLimitTestHelper(v8::kExternalByteArray, 0xffffffff);
16207 ExternalArrayLimitTestHelper(v8::kExternalUnsignedByteArray, 0x40000000);
16208 ExternalArrayLimitTestHelper(v8::kExternalUnsignedByteArray, 0xffffffff);
16209 ExternalArrayLimitTestHelper(v8::kExternalShortArray, 0x40000000);
16210 ExternalArrayLimitTestHelper(v8::kExternalShortArray, 0xffffffff);
16211 ExternalArrayLimitTestHelper(v8::kExternalUnsignedShortArray, 0x40000000);
16212 ExternalArrayLimitTestHelper(v8::kExternalUnsignedShortArray, 0xffffffff);
16213 ExternalArrayLimitTestHelper(v8::kExternalIntArray, 0x40000000);
16214 ExternalArrayLimitTestHelper(v8::kExternalIntArray, 0xffffffff);
16215 ExternalArrayLimitTestHelper(v8::kExternalUnsignedIntArray, 0x40000000);
16216 ExternalArrayLimitTestHelper(v8::kExternalUnsignedIntArray, 0xffffffff);
16217 ExternalArrayLimitTestHelper(v8::kExternalFloatArray, 0x40000000);
16218 ExternalArrayLimitTestHelper(v8::kExternalFloatArray, 0xffffffff);
16219 ExternalArrayLimitTestHelper(v8::kExternalDoubleArray, 0x40000000);
16220 ExternalArrayLimitTestHelper(v8::kExternalDoubleArray, 0xffffffff);
16221 ExternalArrayLimitTestHelper(v8::kExternalPixelArray, 0x40000000);
16222 ExternalArrayLimitTestHelper(v8::kExternalPixelArray, 0xffffffff);
16223}
16224
16225
danno@chromium.orgf005df62013-04-30 16:36:45 +000016226template <typename ElementType, typename TypedArray,
16227 class ExternalArrayClass>
16228void TypedArrayTestHelper(v8::ExternalArrayType array_type,
16229 int64_t low, int64_t high) {
16230 const int kElementCount = 50;
danno@chromium.orgf005df62013-04-30 16:36:45 +000016231
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +000016232 i::ScopedVector<ElementType> backing_store(kElementCount+2);
16233
danno@chromium.orgf005df62013-04-30 16:36:45 +000016234 LocalContext env;
16235 v8::Isolate* isolate = env->GetIsolate();
16236 v8::HandleScope handle_scope(isolate);
16237
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +000016238 Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(
16239 backing_store.start(), (kElementCount+2)*sizeof(ElementType));
danno@chromium.orgf005df62013-04-30 16:36:45 +000016240 Local<TypedArray> ta =
16241 TypedArray::New(ab, 2*sizeof(ElementType), kElementCount);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000016242 CheckInternalFieldsAreZero<v8::ArrayBufferView>(ta);
danno@chromium.orgf005df62013-04-30 16:36:45 +000016243 CHECK_EQ(kElementCount, static_cast<int>(ta->Length()));
16244 CHECK_EQ(2*sizeof(ElementType), static_cast<int>(ta->ByteOffset()));
16245 CHECK_EQ(kElementCount*sizeof(ElementType),
16246 static_cast<int>(ta->ByteLength()));
16247 CHECK_EQ(ab, ta->Buffer());
16248
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +000016249 ElementType* data = backing_store.start() + 2;
danno@chromium.orgf005df62013-04-30 16:36:45 +000016250 for (int i = 0; i < kElementCount; i++) {
16251 data[i] = static_cast<ElementType>(i);
16252 }
16253
16254 ObjectWithExternalArrayTestHelper<ExternalArrayClass, ElementType>(
16255 env.local(), ta, kElementCount, array_type, low, high);
16256}
16257
16258
16259THREADED_TEST(Uint8Array) {
16260 TypedArrayTestHelper<uint8_t, v8::Uint8Array, i::ExternalUnsignedByteArray>(
16261 v8::kExternalUnsignedByteArray, 0, 0xFF);
16262}
16263
16264
16265THREADED_TEST(Int8Array) {
16266 TypedArrayTestHelper<int8_t, v8::Int8Array, i::ExternalByteArray>(
16267 v8::kExternalByteArray, -0x80, 0x7F);
16268}
16269
16270
16271THREADED_TEST(Uint16Array) {
16272 TypedArrayTestHelper<uint16_t,
16273 v8::Uint16Array,
16274 i::ExternalUnsignedShortArray>(
16275 v8::kExternalUnsignedShortArray, 0, 0xFFFF);
16276}
16277
16278
16279THREADED_TEST(Int16Array) {
16280 TypedArrayTestHelper<int16_t, v8::Int16Array, i::ExternalShortArray>(
16281 v8::kExternalShortArray, -0x8000, 0x7FFF);
16282}
16283
16284
16285THREADED_TEST(Uint32Array) {
16286 TypedArrayTestHelper<uint32_t, v8::Uint32Array, i::ExternalUnsignedIntArray>(
16287 v8::kExternalUnsignedIntArray, 0, UINT_MAX);
16288}
16289
16290
16291THREADED_TEST(Int32Array) {
16292 TypedArrayTestHelper<int32_t, v8::Int32Array, i::ExternalIntArray>(
16293 v8::kExternalIntArray, INT_MIN, INT_MAX);
16294}
16295
16296
16297THREADED_TEST(Float32Array) {
16298 TypedArrayTestHelper<float, v8::Float32Array, i::ExternalFloatArray>(
16299 v8::kExternalFloatArray, -500, 500);
16300}
16301
16302
16303THREADED_TEST(Float64Array) {
16304 TypedArrayTestHelper<double, v8::Float64Array, i::ExternalDoubleArray>(
16305 v8::kExternalDoubleArray, -500, 500);
16306}
16307
16308
ulan@chromium.org57ff8812013-05-10 08:16:55 +000016309THREADED_TEST(Uint8ClampedArray) {
16310 TypedArrayTestHelper<uint8_t, v8::Uint8ClampedArray, i::ExternalPixelArray>(
16311 v8::kExternalPixelArray, 0, 0xFF);
16312}
16313
16314
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000016315THREADED_TEST(DataView) {
16316 const int kSize = 50;
16317
16318 i::ScopedVector<uint8_t> backing_store(kSize+2);
16319
16320 LocalContext env;
16321 v8::Isolate* isolate = env->GetIsolate();
16322 v8::HandleScope handle_scope(isolate);
16323
16324 Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(
16325 backing_store.start(), 2 + kSize);
16326 Local<v8::DataView> dv =
16327 v8::DataView::New(ab, 2, kSize);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000016328 CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000016329 CHECK_EQ(2, static_cast<int>(dv->ByteOffset()));
16330 CHECK_EQ(kSize, static_cast<int>(dv->ByteLength()));
16331 CHECK_EQ(ab, dv->Buffer());
16332}
16333
16334
16335#define IS_ARRAY_BUFFER_VIEW_TEST(View) \
16336 THREADED_TEST(Is##View) { \
ulan@chromium.org57ff8812013-05-10 08:16:55 +000016337 LocalContext env; \
16338 v8::Isolate* isolate = env->GetIsolate(); \
16339 v8::HandleScope handle_scope(isolate); \
16340 \
16341 Handle<Value> result = CompileRun( \
16342 "var ab = new ArrayBuffer(128);" \
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000016343 "new " #View "(ab)"); \
16344 CHECK(result->IsArrayBufferView()); \
16345 CHECK(result->Is##View()); \
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000016346 CheckInternalFieldsAreZero<v8::ArrayBufferView>(result.As<v8::View>()); \
ulan@chromium.org57ff8812013-05-10 08:16:55 +000016347 }
16348
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000016349IS_ARRAY_BUFFER_VIEW_TEST(Uint8Array)
16350IS_ARRAY_BUFFER_VIEW_TEST(Int8Array)
16351IS_ARRAY_BUFFER_VIEW_TEST(Uint16Array)
16352IS_ARRAY_BUFFER_VIEW_TEST(Int16Array)
16353IS_ARRAY_BUFFER_VIEW_TEST(Uint32Array)
16354IS_ARRAY_BUFFER_VIEW_TEST(Int32Array)
16355IS_ARRAY_BUFFER_VIEW_TEST(Float32Array)
16356IS_ARRAY_BUFFER_VIEW_TEST(Float64Array)
16357IS_ARRAY_BUFFER_VIEW_TEST(Uint8ClampedArray)
16358IS_ARRAY_BUFFER_VIEW_TEST(DataView)
ulan@chromium.org57ff8812013-05-10 08:16:55 +000016359
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000016360#undef IS_ARRAY_BUFFER_VIEW_TEST
ulan@chromium.org57ff8812013-05-10 08:16:55 +000016361
16362
16363
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000016364THREADED_TEST(ScriptContextDependence) {
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000016365 LocalContext c1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016366 v8::HandleScope scope(c1->GetIsolate());
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000016367 const char *source = "foo";
16368 v8::Handle<v8::Script> dep = v8::Script::Compile(v8::String::New(source));
16369 v8::Handle<v8::Script> indep = v8::Script::New(v8::String::New(source));
16370 c1->Global()->Set(v8::String::New("foo"), v8::Integer::New(100));
16371 CHECK_EQ(dep->Run()->Int32Value(), 100);
16372 CHECK_EQ(indep->Run()->Int32Value(), 100);
16373 LocalContext c2;
16374 c2->Global()->Set(v8::String::New("foo"), v8::Integer::New(101));
16375 CHECK_EQ(dep->Run()->Int32Value(), 100);
16376 CHECK_EQ(indep->Run()->Int32Value(), 101);
16377}
16378
ager@chromium.org96c75b52009-08-26 09:13:16 +000016379
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000016380THREADED_TEST(StackTrace) {
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000016381 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016382 v8::HandleScope scope(context->GetIsolate());
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000016383 v8::TryCatch try_catch;
16384 const char *source = "function foo() { FAIL.FAIL; }; foo();";
16385 v8::Handle<v8::String> src = v8::String::New(source);
16386 v8::Handle<v8::String> origin = v8::String::New("stack-trace-test");
16387 v8::Script::New(src, origin)->Run();
16388 CHECK(try_catch.HasCaught());
16389 v8::String::Utf8Value stack(try_catch.StackTrace());
16390 CHECK(strstr(*stack, "at foo (stack-trace-test") != NULL);
16391}
ager@chromium.org96c75b52009-08-26 09:13:16 +000016392
16393
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000016394// Checks that a StackFrame has certain expected values.
16395void checkStackFrame(const char* expected_script_name,
16396 const char* expected_func_name, int expected_line_number,
16397 int expected_column, bool is_eval, bool is_constructor,
16398 v8::Handle<v8::StackFrame> frame) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000016399 v8::HandleScope scope(CcTest::isolate());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000016400 v8::String::Utf8Value func_name(frame->GetFunctionName());
16401 v8::String::Utf8Value script_name(frame->GetScriptName());
16402 if (*script_name == NULL) {
16403 // The situation where there is no associated script, like for evals.
16404 CHECK(expected_script_name == NULL);
16405 } else {
16406 CHECK(strstr(*script_name, expected_script_name) != NULL);
16407 }
16408 CHECK(strstr(*func_name, expected_func_name) != NULL);
16409 CHECK_EQ(expected_line_number, frame->GetLineNumber());
16410 CHECK_EQ(expected_column, frame->GetColumn());
16411 CHECK_EQ(is_eval, frame->IsEval());
16412 CHECK_EQ(is_constructor, frame->IsConstructor());
16413}
16414
16415
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000016416void AnalyzeStackInNativeCode(const v8::FunctionCallbackInfo<v8::Value>& args) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016417 v8::HandleScope scope(args.GetIsolate());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000016418 const char* origin = "capture-stack-trace-test";
16419 const int kOverviewTest = 1;
16420 const int kDetailedTest = 2;
16421
16422 ASSERT(args.Length() == 1);
16423
16424 int testGroup = args[0]->Int32Value();
16425 if (testGroup == kOverviewTest) {
16426 v8::Handle<v8::StackTrace> stackTrace =
16427 v8::StackTrace::CurrentStackTrace(10, v8::StackTrace::kOverview);
16428 CHECK_EQ(4, stackTrace->GetFrameCount());
16429 checkStackFrame(origin, "bar", 2, 10, false, false,
16430 stackTrace->GetFrame(0));
16431 checkStackFrame(origin, "foo", 6, 3, false, false,
16432 stackTrace->GetFrame(1));
whesse@chromium.org030d38e2011-07-13 13:23:34 +000016433 // This is the source string inside the eval which has the call to foo.
16434 checkStackFrame(NULL, "", 1, 5, false, false,
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000016435 stackTrace->GetFrame(2));
whesse@chromium.org030d38e2011-07-13 13:23:34 +000016436 // The last frame is an anonymous function which has the initial eval call.
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000016437 checkStackFrame(origin, "", 8, 7, false, false,
16438 stackTrace->GetFrame(3));
16439
16440 CHECK(stackTrace->AsArray()->IsArray());
16441 } else if (testGroup == kDetailedTest) {
16442 v8::Handle<v8::StackTrace> stackTrace =
16443 v8::StackTrace::CurrentStackTrace(10, v8::StackTrace::kDetailed);
16444 CHECK_EQ(4, stackTrace->GetFrameCount());
16445 checkStackFrame(origin, "bat", 4, 22, false, false,
16446 stackTrace->GetFrame(0));
16447 checkStackFrame(origin, "baz", 8, 3, false, true,
16448 stackTrace->GetFrame(1));
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +000016449#ifdef ENABLE_DEBUGGER_SUPPORT
16450 bool is_eval = true;
16451#else // ENABLE_DEBUGGER_SUPPORT
16452 bool is_eval = false;
16453#endif // ENABLE_DEBUGGER_SUPPORT
16454
whesse@chromium.org030d38e2011-07-13 13:23:34 +000016455 // This is the source string inside the eval which has the call to baz.
16456 checkStackFrame(NULL, "", 1, 5, is_eval, false,
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000016457 stackTrace->GetFrame(2));
whesse@chromium.org030d38e2011-07-13 13:23:34 +000016458 // The last frame is an anonymous function which has the initial eval call.
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000016459 checkStackFrame(origin, "", 10, 1, false, false,
16460 stackTrace->GetFrame(3));
16461
16462 CHECK(stackTrace->AsArray()->IsArray());
16463 }
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000016464}
16465
16466
16467// Tests the C++ StackTrace API.
kasperl@chromium.orga5551262010-12-07 12:49:48 +000016468// TODO(3074796): Reenable this as a THREADED_TEST once it passes.
16469// THREADED_TEST(CaptureStackTrace) {
16470TEST(CaptureStackTrace) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000016471 v8::HandleScope scope(CcTest::isolate());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000016472 v8::Handle<v8::String> origin = v8::String::New("capture-stack-trace-test");
16473 Local<ObjectTemplate> templ = ObjectTemplate::New();
16474 templ->Set(v8_str("AnalyzeStackInNativeCode"),
16475 v8::FunctionTemplate::New(AnalyzeStackInNativeCode));
16476 LocalContext context(0, templ);
16477
16478 // Test getting OVERVIEW information. Should ignore information that is not
16479 // script name, function name, line number, and column offset.
16480 const char *overview_source =
16481 "function bar() {\n"
16482 " var y; AnalyzeStackInNativeCode(1);\n"
16483 "}\n"
16484 "function foo() {\n"
16485 "\n"
16486 " bar();\n"
16487 "}\n"
16488 "var x;eval('new foo();');";
16489 v8::Handle<v8::String> overview_src = v8::String::New(overview_source);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000016490 v8::Handle<Value> overview_result(
16491 v8::Script::New(overview_src, origin)->Run());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000016492 CHECK(!overview_result.IsEmpty());
16493 CHECK(overview_result->IsObject());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000016494
16495 // Test getting DETAILED information.
16496 const char *detailed_source =
16497 "function bat() {AnalyzeStackInNativeCode(2);\n"
16498 "}\n"
16499 "\n"
16500 "function baz() {\n"
16501 " bat();\n"
16502 "}\n"
16503 "eval('new baz();');";
16504 v8::Handle<v8::String> detailed_src = v8::String::New(detailed_source);
16505 // Make the script using a non-zero line and column offset.
16506 v8::Handle<v8::Integer> line_offset = v8::Integer::New(3);
16507 v8::Handle<v8::Integer> column_offset = v8::Integer::New(5);
16508 v8::ScriptOrigin detailed_origin(origin, line_offset, column_offset);
16509 v8::Handle<v8::Script> detailed_script(
16510 v8::Script::New(detailed_src, &detailed_origin));
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000016511 v8::Handle<Value> detailed_result(detailed_script->Run());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000016512 CHECK(!detailed_result.IsEmpty());
16513 CHECK(detailed_result->IsObject());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000016514}
16515
16516
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000016517static void StackTraceForUncaughtExceptionListener(
16518 v8::Handle<v8::Message> message,
16519 v8::Handle<Value>) {
16520 v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
16521 CHECK_EQ(2, stack_trace->GetFrameCount());
16522 checkStackFrame("origin", "foo", 2, 3, false, false,
16523 stack_trace->GetFrame(0));
16524 checkStackFrame("origin", "bar", 5, 3, false, false,
16525 stack_trace->GetFrame(1));
16526}
16527
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000016528
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000016529TEST(CaptureStackTraceForUncaughtException) {
16530 report_count = 0;
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000016531 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016532 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000016533 v8::V8::AddMessageListener(StackTraceForUncaughtExceptionListener);
16534 v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
16535
16536 Script::Compile(v8_str("function foo() {\n"
16537 " throw 1;\n"
16538 "};\n"
16539 "function bar() {\n"
16540 " foo();\n"
16541 "};"),
16542 v8_str("origin"))->Run();
16543 v8::Local<v8::Object> global = env->Global();
16544 Local<Value> trouble = global->Get(v8_str("bar"));
16545 CHECK(trouble->IsFunction());
16546 Function::Cast(*trouble)->Call(global, 0, NULL);
16547 v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
16548 v8::V8::RemoveMessageListeners(StackTraceForUncaughtExceptionListener);
16549}
16550
16551
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000016552TEST(CaptureStackTraceForUncaughtExceptionAndSetters) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000016553 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016554 v8::HandleScope scope(env->GetIsolate());
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000016555 v8::V8::SetCaptureStackTraceForUncaughtExceptions(true,
16556 1024,
16557 v8::StackTrace::kDetailed);
16558
16559 CompileRun(
16560 "var setters = ['column', 'lineNumber', 'scriptName',\n"
16561 " 'scriptNameOrSourceURL', 'functionName', 'isEval',\n"
16562 " 'isConstructor'];\n"
16563 "for (var i = 0; i < setters.length; i++) {\n"
16564 " var prop = setters[i];\n"
16565 " Object.prototype.__defineSetter__(prop, function() { throw prop; });\n"
16566 "}\n");
16567 CompileRun("throw 'exception';");
16568 v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
16569}
16570
16571
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000016572static void RethrowStackTraceHandler(v8::Handle<v8::Message> message,
16573 v8::Handle<v8::Value> data) {
16574 // Use the frame where JavaScript is called from.
16575 v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
16576 CHECK(!stack_trace.IsEmpty());
16577 int frame_count = stack_trace->GetFrameCount();
16578 CHECK_EQ(3, frame_count);
16579 int line_number[] = {1, 2, 5};
16580 for (int i = 0; i < frame_count; i++) {
16581 CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber());
16582 }
16583}
16584
16585
16586// Test that we only return the stack trace at the site where the exception
16587// is first thrown (not where it is rethrown).
16588TEST(RethrowStackTrace) {
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000016589 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016590 v8::HandleScope scope(env->GetIsolate());
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000016591 // We make sure that
16592 // - the stack trace of the ReferenceError in g() is reported.
16593 // - the stack trace is not overwritten when e1 is rethrown by t().
16594 // - the stack trace of e2 does not overwrite that of e1.
16595 const char* source =
16596 "function g() { error; } \n"
16597 "function f() { g(); } \n"
16598 "function t(e) { throw e; } \n"
16599 "try { \n"
16600 " f(); \n"
16601 "} catch (e1) { \n"
16602 " try { \n"
16603 " error; \n"
16604 " } catch (e2) { \n"
16605 " t(e1); \n"
16606 " } \n"
16607 "} \n";
16608 v8::V8::AddMessageListener(RethrowStackTraceHandler);
16609 v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
16610 CompileRun(source);
16611 v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
16612 v8::V8::RemoveMessageListeners(RethrowStackTraceHandler);
16613}
16614
16615
16616static void RethrowPrimitiveStackTraceHandler(v8::Handle<v8::Message> message,
16617 v8::Handle<v8::Value> data) {
16618 v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
16619 CHECK(!stack_trace.IsEmpty());
16620 int frame_count = stack_trace->GetFrameCount();
16621 CHECK_EQ(2, frame_count);
16622 int line_number[] = {3, 7};
16623 for (int i = 0; i < frame_count; i++) {
16624 CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber());
16625 }
16626}
16627
16628
16629// Test that we do not recognize identity for primitive exceptions.
16630TEST(RethrowPrimitiveStackTrace) {
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000016631 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016632 v8::HandleScope scope(env->GetIsolate());
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000016633 // We do not capture stack trace for non Error objects on creation time.
16634 // Instead, we capture the stack trace on last throw.
16635 const char* source =
16636 "function g() { throw 404; } \n"
16637 "function f() { g(); } \n"
16638 "function t(e) { throw e; } \n"
16639 "try { \n"
16640 " f(); \n"
16641 "} catch (e1) { \n"
16642 " t(e1) \n"
16643 "} \n";
16644 v8::V8::AddMessageListener(RethrowPrimitiveStackTraceHandler);
16645 v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
16646 CompileRun(source);
16647 v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
16648 v8::V8::RemoveMessageListeners(RethrowPrimitiveStackTraceHandler);
16649}
16650
16651
16652static void RethrowExistingStackTraceHandler(v8::Handle<v8::Message> message,
16653 v8::Handle<v8::Value> data) {
16654 // Use the frame where JavaScript is called from.
16655 v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
16656 CHECK(!stack_trace.IsEmpty());
16657 CHECK_EQ(1, stack_trace->GetFrameCount());
16658 CHECK_EQ(1, stack_trace->GetFrame(0)->GetLineNumber());
16659}
16660
16661
16662// Test that the stack trace is captured when the error object is created and
16663// not where it is thrown.
16664TEST(RethrowExistingStackTrace) {
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000016665 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016666 v8::HandleScope scope(env->GetIsolate());
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000016667 const char* source =
16668 "var e = new Error(); \n"
16669 "throw e; \n";
16670 v8::V8::AddMessageListener(RethrowExistingStackTraceHandler);
16671 v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
16672 CompileRun(source);
16673 v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
16674 v8::V8::RemoveMessageListeners(RethrowExistingStackTraceHandler);
16675}
16676
16677
16678static void RethrowBogusErrorStackTraceHandler(v8::Handle<v8::Message> message,
16679 v8::Handle<v8::Value> data) {
16680 // Use the frame where JavaScript is called from.
16681 v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
16682 CHECK(!stack_trace.IsEmpty());
16683 CHECK_EQ(1, stack_trace->GetFrameCount());
16684 CHECK_EQ(2, stack_trace->GetFrame(0)->GetLineNumber());
16685}
16686
16687
16688// Test that the stack trace is captured where the bogus Error object is thrown.
16689TEST(RethrowBogusErrorStackTrace) {
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000016690 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016691 v8::HandleScope scope(env->GetIsolate());
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000016692 const char* source =
16693 "var e = {__proto__: new Error()} \n"
16694 "throw e; \n";
16695 v8::V8::AddMessageListener(RethrowBogusErrorStackTraceHandler);
16696 v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
16697 CompileRun(source);
16698 v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
16699 v8::V8::RemoveMessageListeners(RethrowBogusErrorStackTraceHandler);
16700}
16701
16702
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000016703void AnalyzeStackOfEvalWithSourceURL(
16704 const v8::FunctionCallbackInfo<v8::Value>& args) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016705 v8::HandleScope scope(args.GetIsolate());
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000016706 v8::Handle<v8::StackTrace> stackTrace =
16707 v8::StackTrace::CurrentStackTrace(10, v8::StackTrace::kDetailed);
16708 CHECK_EQ(5, stackTrace->GetFrameCount());
16709 v8::Handle<v8::String> url = v8_str("eval_url");
16710 for (int i = 0; i < 3; i++) {
16711 v8::Handle<v8::String> name =
16712 stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
16713 CHECK(!name.IsEmpty());
16714 CHECK_EQ(url, name);
16715 }
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000016716}
16717
16718
16719TEST(SourceURLInStackTrace) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000016720 v8::HandleScope scope(CcTest::isolate());
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000016721 Local<ObjectTemplate> templ = ObjectTemplate::New();
16722 templ->Set(v8_str("AnalyzeStackOfEvalWithSourceURL"),
16723 v8::FunctionTemplate::New(AnalyzeStackOfEvalWithSourceURL));
16724 LocalContext context(0, templ);
16725
16726 const char *source =
16727 "function outer() {\n"
16728 "function bar() {\n"
16729 " AnalyzeStackOfEvalWithSourceURL();\n"
16730 "}\n"
16731 "function foo() {\n"
16732 "\n"
16733 " bar();\n"
16734 "}\n"
16735 "foo();\n"
16736 "}\n"
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000016737 "eval('(' + outer +')()%s');";
16738
16739 i::ScopedVector<char> code(1024);
16740 i::OS::SNPrintF(code, source, "//# sourceURL=eval_url");
16741 CHECK(CompileRun(code.start())->IsUndefined());
16742 i::OS::SNPrintF(code, source, "//@ sourceURL=eval_url");
16743 CHECK(CompileRun(code.start())->IsUndefined());
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000016744}
16745
16746
jkummerow@chromium.org8fa5bd92013-09-02 11:45:09 +000016747static int scriptIdInStack[2];
16748
16749void AnalyzeScriptIdInStack(
16750 const v8::FunctionCallbackInfo<v8::Value>& args) {
16751 v8::HandleScope scope(args.GetIsolate());
16752 v8::Handle<v8::StackTrace> stackTrace =
16753 v8::StackTrace::CurrentStackTrace(10, v8::StackTrace::kScriptId);
16754 CHECK_EQ(2, stackTrace->GetFrameCount());
16755 for (int i = 0; i < 2; i++) {
16756 scriptIdInStack[i] = stackTrace->GetFrame(i)->GetScriptId();
16757 }
16758}
16759
16760
16761TEST(ScriptIdInStackTrace) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000016762 v8::HandleScope scope(CcTest::isolate());
jkummerow@chromium.org8fa5bd92013-09-02 11:45:09 +000016763 Local<ObjectTemplate> templ = ObjectTemplate::New();
16764 templ->Set(v8_str("AnalyzeScriptIdInStack"),
16765 v8::FunctionTemplate::New(AnalyzeScriptIdInStack));
16766 LocalContext context(0, templ);
16767
16768 v8::Handle<v8::String> scriptSource = v8::String::New(
16769 "function foo() {\n"
16770 " AnalyzeScriptIdInStack();"
16771 "}\n"
16772 "foo();\n");
16773 v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::New("test"));
16774 v8::Local<v8::Script> script(v8::Script::Compile(scriptSource, &origin));
16775 script->Run();
16776 for (int i = 0; i < 2; i++) {
16777 CHECK(scriptIdInStack[i] != v8::Message::kNoScriptIdInfo);
16778 CHECK_EQ(scriptIdInStack[i], script->GetId());
16779 }
16780}
16781
16782
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000016783void AnalyzeStackOfInlineScriptWithSourceURL(
16784 const v8::FunctionCallbackInfo<v8::Value>& args) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016785 v8::HandleScope scope(args.GetIsolate());
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000016786 v8::Handle<v8::StackTrace> stackTrace =
16787 v8::StackTrace::CurrentStackTrace(10, v8::StackTrace::kDetailed);
16788 CHECK_EQ(4, stackTrace->GetFrameCount());
16789 v8::Handle<v8::String> url = v8_str("url");
16790 for (int i = 0; i < 3; i++) {
16791 v8::Handle<v8::String> name =
16792 stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
16793 CHECK(!name.IsEmpty());
16794 CHECK_EQ(url, name);
16795 }
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000016796}
16797
16798
16799TEST(InlineScriptWithSourceURLInStackTrace) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000016800 v8::HandleScope scope(CcTest::isolate());
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000016801 Local<ObjectTemplate> templ = ObjectTemplate::New();
16802 templ->Set(v8_str("AnalyzeStackOfInlineScriptWithSourceURL"),
16803 v8::FunctionTemplate::New(
16804 AnalyzeStackOfInlineScriptWithSourceURL));
16805 LocalContext context(0, templ);
16806
16807 const char *source =
16808 "function outer() {\n"
16809 "function bar() {\n"
16810 " AnalyzeStackOfInlineScriptWithSourceURL();\n"
16811 "}\n"
16812 "function foo() {\n"
16813 "\n"
16814 " bar();\n"
16815 "}\n"
16816 "foo();\n"
16817 "}\n"
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000016818 "outer()\n%s";
16819
16820 i::ScopedVector<char> code(1024);
16821 i::OS::SNPrintF(code, source, "//# sourceURL=source_url");
16822 CHECK(CompileRunWithOrigin(code.start(), "url", 0, 1)->IsUndefined());
16823 i::OS::SNPrintF(code, source, "//@ sourceURL=source_url");
16824 CHECK(CompileRunWithOrigin(code.start(), "url", 0, 1)->IsUndefined());
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000016825}
16826
16827
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000016828void AnalyzeStackOfDynamicScriptWithSourceURL(
16829 const v8::FunctionCallbackInfo<v8::Value>& args) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016830 v8::HandleScope scope(args.GetIsolate());
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000016831 v8::Handle<v8::StackTrace> stackTrace =
16832 v8::StackTrace::CurrentStackTrace(10, v8::StackTrace::kDetailed);
16833 CHECK_EQ(4, stackTrace->GetFrameCount());
16834 v8::Handle<v8::String> url = v8_str("source_url");
16835 for (int i = 0; i < 3; i++) {
16836 v8::Handle<v8::String> name =
16837 stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
16838 CHECK(!name.IsEmpty());
16839 CHECK_EQ(url, name);
16840 }
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000016841}
16842
16843
16844TEST(DynamicWithSourceURLInStackTrace) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000016845 v8::HandleScope scope(CcTest::isolate());
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000016846 Local<ObjectTemplate> templ = ObjectTemplate::New();
16847 templ->Set(v8_str("AnalyzeStackOfDynamicScriptWithSourceURL"),
16848 v8::FunctionTemplate::New(
16849 AnalyzeStackOfDynamicScriptWithSourceURL));
16850 LocalContext context(0, templ);
16851
16852 const char *source =
16853 "function outer() {\n"
16854 "function bar() {\n"
16855 " AnalyzeStackOfDynamicScriptWithSourceURL();\n"
16856 "}\n"
16857 "function foo() {\n"
16858 "\n"
16859 " bar();\n"
16860 "}\n"
16861 "foo();\n"
16862 "}\n"
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000016863 "outer()\n%s";
16864
16865 i::ScopedVector<char> code(1024);
16866 i::OS::SNPrintF(code, source, "//# sourceURL=source_url");
16867 CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined());
16868 i::OS::SNPrintF(code, source, "//@ sourceURL=source_url");
16869 CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined());
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000016870}
16871
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000016872
danno@chromium.org2c26cb12012-05-03 09:06:43 +000016873static void CreateGarbageInOldSpace() {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000016874 i::Factory* factory = CcTest::i_isolate()->factory();
16875 v8::HandleScope scope(CcTest::isolate());
danno@chromium.org2c26cb12012-05-03 09:06:43 +000016876 i::AlwaysAllocateScope always_allocate;
16877 for (int i = 0; i < 1000; i++) {
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000016878 factory->NewFixedArray(1000, i::TENURED);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000016879 }
svenpanne@chromium.orgecb9dd62011-12-01 08:22:35 +000016880}
16881
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000016882
svenpanne@chromium.orgecb9dd62011-12-01 08:22:35 +000016883// Test that idle notification can be handled and eventually returns true.
danno@chromium.org2c26cb12012-05-03 09:06:43 +000016884TEST(IdleNotification) {
16885 const intptr_t MB = 1024 * 1024;
danno@chromium.org2c26cb12012-05-03 09:06:43 +000016886 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016887 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org528ce022013-09-23 14:09:36 +000016888 intptr_t initial_size = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000016889 CreateGarbageInOldSpace();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000016890 intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000016891 CHECK_GT(size_with_garbage, initial_size + MB);
16892 bool finished = false;
16893 for (int i = 0; i < 200 && !finished; i++) {
16894 finished = v8::V8::IdleNotification();
16895 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +000016896 intptr_t final_size = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000016897 CHECK(finished);
16898 CHECK_LT(final_size, initial_size + 1);
16899}
16900
16901
16902// Test that idle notification can be handled and eventually collects garbage.
yangguo@chromium.org56454712012-02-16 15:33:53 +000016903TEST(IdleNotificationWithSmallHint) {
danno@chromium.org2c26cb12012-05-03 09:06:43 +000016904 const intptr_t MB = 1024 * 1024;
16905 const int IdlePauseInMs = 900;
svenpanne@chromium.orgecb9dd62011-12-01 08:22:35 +000016906 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016907 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org528ce022013-09-23 14:09:36 +000016908 intptr_t initial_size = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000016909 CreateGarbageInOldSpace();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000016910 intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000016911 CHECK_GT(size_with_garbage, initial_size + MB);
16912 bool finished = false;
16913 for (int i = 0; i < 200 && !finished; i++) {
16914 finished = v8::V8::IdleNotification(IdlePauseInMs);
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000016915 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +000016916 intptr_t final_size = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000016917 CHECK(finished);
16918 CHECK_LT(final_size, initial_size + 1);
yangguo@chromium.org56454712012-02-16 15:33:53 +000016919}
16920
16921
danno@chromium.org2c26cb12012-05-03 09:06:43 +000016922// Test that idle notification can be handled and eventually collects garbage.
yangguo@chromium.org56454712012-02-16 15:33:53 +000016923TEST(IdleNotificationWithLargeHint) {
danno@chromium.org2c26cb12012-05-03 09:06:43 +000016924 const intptr_t MB = 1024 * 1024;
16925 const int IdlePauseInMs = 900;
yangguo@chromium.org56454712012-02-16 15:33:53 +000016926 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016927 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org528ce022013-09-23 14:09:36 +000016928 intptr_t initial_size = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000016929 CreateGarbageInOldSpace();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000016930 intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000016931 CHECK_GT(size_with_garbage, initial_size + MB);
16932 bool finished = false;
16933 for (int i = 0; i < 200 && !finished; i++) {
16934 finished = v8::V8::IdleNotification(IdlePauseInMs);
yangguo@chromium.org56454712012-02-16 15:33:53 +000016935 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +000016936 intptr_t final_size = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000016937 CHECK(finished);
16938 CHECK_LT(final_size, initial_size + 1);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000016939}
16940
16941
danno@chromium.org2c26cb12012-05-03 09:06:43 +000016942TEST(Regress2107) {
16943 const intptr_t MB = 1024 * 1024;
16944 const int kShortIdlePauseInMs = 100;
16945 const int kLongIdlePauseInMs = 1000;
danno@chromium.org2c26cb12012-05-03 09:06:43 +000016946 LocalContext env;
ulan@chromium.org57ff8812013-05-10 08:16:55 +000016947 v8::Isolate* isolate = env->GetIsolate();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016948 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org528ce022013-09-23 14:09:36 +000016949 intptr_t initial_size = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000016950 // Send idle notification to start a round of incremental GCs.
16951 v8::V8::IdleNotification(kShortIdlePauseInMs);
16952 // Emulate 7 page reloads.
16953 for (int i = 0; i < 7; i++) {
ulan@chromium.org57ff8812013-05-10 08:16:55 +000016954 {
16955 v8::HandleScope inner_scope(env->GetIsolate());
16956 v8::Local<v8::Context> ctx = v8::Context::New(isolate);
16957 ctx->Enter();
16958 CreateGarbageInOldSpace();
16959 ctx->Exit();
16960 }
danno@chromium.org2c26cb12012-05-03 09:06:43 +000016961 v8::V8::ContextDisposedNotification();
16962 v8::V8::IdleNotification(kLongIdlePauseInMs);
16963 }
16964 // Create garbage and check that idle notification still collects it.
16965 CreateGarbageInOldSpace();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000016966 intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000016967 CHECK_GT(size_with_garbage, initial_size + MB);
16968 bool finished = false;
16969 for (int i = 0; i < 200 && !finished; i++) {
16970 finished = v8::V8::IdleNotification(kShortIdlePauseInMs);
16971 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +000016972 intptr_t final_size = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000016973 CHECK_LT(final_size, initial_size + 1);
16974}
16975
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000016976static uint32_t* stack_limit;
16977
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000016978static void GetStackLimitCallback(
16979 const v8::FunctionCallbackInfo<v8::Value>& args) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000016980 stack_limit = reinterpret_cast<uint32_t*>(
machenbach@chromium.org528ce022013-09-23 14:09:36 +000016981 CcTest::i_isolate()->stack_guard()->real_climit());
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000016982}
16983
16984
16985// Uses the address of a local variable to determine the stack top now.
16986// Given a size, returns an address that is that far from the current
16987// top of stack.
16988static uint32_t* ComputeStackLimit(uint32_t size) {
16989 uint32_t* answer = &size - (size / sizeof(size));
16990 // If the size is very large and the stack is very near the bottom of
16991 // memory then the calculation above may wrap around and give an address
16992 // that is above the (downwards-growing) stack. In that case we return
16993 // a very low address.
16994 if (answer > &size) return reinterpret_cast<uint32_t*>(sizeof(size));
16995 return answer;
16996}
16997
16998
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +000016999// We need at least 165kB for an x64 debug build with clang and ASAN.
17000static const int stack_breathing_room = 256 * i::KB;
17001
17002
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017003TEST(SetResourceConstraints) {
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +000017004 uint32_t* set_limit = ComputeStackLimit(stack_breathing_room);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017005
17006 // Set stack limit.
17007 v8::ResourceConstraints constraints;
17008 constraints.set_stack_limit(set_limit);
17009 CHECK(v8::SetResourceConstraints(&constraints));
17010
17011 // Execute a script.
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017012 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017013 v8::HandleScope scope(env->GetIsolate());
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017014 Local<v8::FunctionTemplate> fun_templ =
17015 v8::FunctionTemplate::New(GetStackLimitCallback);
17016 Local<Function> fun = fun_templ->GetFunction();
17017 env->Global()->Set(v8_str("get_stack_limit"), fun);
17018 CompileRun("get_stack_limit();");
17019
17020 CHECK(stack_limit == set_limit);
17021}
17022
17023
17024TEST(SetResourceConstraintsInThread) {
17025 uint32_t* set_limit;
17026 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017027 v8::Locker locker(CcTest::isolate());
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +000017028 set_limit = ComputeStackLimit(stack_breathing_room);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017029
17030 // Set stack limit.
17031 v8::ResourceConstraints constraints;
17032 constraints.set_stack_limit(set_limit);
17033 CHECK(v8::SetResourceConstraints(&constraints));
17034
17035 // Execute a script.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017036 v8::HandleScope scope(CcTest::isolate());
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017037 LocalContext env;
17038 Local<v8::FunctionTemplate> fun_templ =
17039 v8::FunctionTemplate::New(GetStackLimitCallback);
17040 Local<Function> fun = fun_templ->GetFunction();
17041 env->Global()->Set(v8_str("get_stack_limit"), fun);
17042 CompileRun("get_stack_limit();");
17043
17044 CHECK(stack_limit == set_limit);
17045 }
17046 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017047 v8::Locker locker(CcTest::isolate());
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017048 CHECK(stack_limit == set_limit);
17049 }
ager@chromium.org96c75b52009-08-26 09:13:16 +000017050}
ager@chromium.org3811b432009-10-28 14:53:37 +000017051
17052
17053THREADED_TEST(GetHeapStatistics) {
ager@chromium.org3811b432009-10-28 14:53:37 +000017054 LocalContext c1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017055 v8::HandleScope scope(c1->GetIsolate());
ager@chromium.org3811b432009-10-28 14:53:37 +000017056 v8::HeapStatistics heap_statistics;
ager@chromium.orgc4c92722009-11-18 14:12:51 +000017057 CHECK_EQ(static_cast<int>(heap_statistics.total_heap_size()), 0);
17058 CHECK_EQ(static_cast<int>(heap_statistics.used_heap_size()), 0);
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +000017059 c1->GetIsolate()->GetHeapStatistics(&heap_statistics);
ager@chromium.orgc4c92722009-11-18 14:12:51 +000017060 CHECK_NE(static_cast<int>(heap_statistics.total_heap_size()), 0);
17061 CHECK_NE(static_cast<int>(heap_statistics.used_heap_size()), 0);
ager@chromium.org3811b432009-10-28 14:53:37 +000017062}
17063
17064
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017065class VisitorImpl : public v8::ExternalResourceVisitor {
17066 public:
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017067 explicit VisitorImpl(TestResource** resource) {
17068 for (int i = 0; i < 4; i++) {
17069 resource_[i] = resource[i];
17070 found_resource_[i] = false;
17071 }
17072 }
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017073 virtual ~VisitorImpl() {}
17074 virtual void VisitExternalString(v8::Handle<v8::String> string) {
17075 if (!string->IsExternal()) {
17076 CHECK(string->IsExternalAscii());
17077 return;
17078 }
17079 v8::String::ExternalStringResource* resource =
17080 string->GetExternalStringResource();
17081 CHECK(resource);
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017082 for (int i = 0; i < 4; i++) {
17083 if (resource_[i] == resource) {
17084 CHECK(!found_resource_[i]);
17085 found_resource_[i] = true;
17086 }
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017087 }
17088 }
17089 void CheckVisitedResources() {
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017090 for (int i = 0; i < 4; i++) {
17091 CHECK(found_resource_[i]);
17092 }
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017093 }
17094
17095 private:
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017096 v8::String::ExternalStringResource* resource_[4];
17097 bool found_resource_[4];
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017098};
17099
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000017100
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017101TEST(VisitExternalStrings) {
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017102 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017103 v8::HandleScope scope(env->GetIsolate());
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017104 const char* string = "Some string";
17105 uint16_t* two_byte_string = AsciiToTwoByteString(string);
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017106 TestResource* resource[4];
17107 resource[0] = new TestResource(two_byte_string);
17108 v8::Local<v8::String> string0 = v8::String::NewExternal(resource[0]);
17109 resource[1] = new TestResource(two_byte_string);
17110 v8::Local<v8::String> string1 = v8::String::NewExternal(resource[1]);
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017111
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017112 // Externalized symbol.
17113 resource[2] = new TestResource(two_byte_string);
17114 v8::Local<v8::String> string2 = v8::String::NewSymbol(string);
17115 CHECK(string2->MakeExternal(resource[2]));
17116
17117 // Symbolized External.
17118 resource[3] = new TestResource(AsciiToTwoByteString("Some other string"));
17119 v8::Local<v8::String> string3 = v8::String::NewExternal(resource[3]);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017120 CcTest::heap()->CollectAllAvailableGarbage(); // Tenure string.
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017121 // Turn into a symbol.
17122 i::Handle<i::String> string3_i = v8::Utils::OpenHandle(*string3);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017123 CHECK(!CcTest::heap()->InternalizeString(*string3_i)->IsFailure());
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +000017124 CHECK(string3_i->IsInternalizedString());
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017125
17126 // We need to add usages for string* to avoid warnings in GCC 4.7
17127 CHECK(string0->IsExternal());
ulan@chromium.org2efb9002012-01-19 15:36:35 +000017128 CHECK(string1->IsExternal());
17129 CHECK(string2->IsExternal());
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017130 CHECK(string3->IsExternal());
ulan@chromium.org2efb9002012-01-19 15:36:35 +000017131
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017132 VisitorImpl visitor(resource);
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017133 v8::V8::VisitExternalResources(&visitor);
17134 visitor.CheckVisitedResources();
17135}
17136
17137
ager@chromium.org3811b432009-10-28 14:53:37 +000017138static double DoubleFromBits(uint64_t value) {
17139 double target;
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +000017140 i::OS::MemCopy(&target, &value, sizeof(target));
ager@chromium.org3811b432009-10-28 14:53:37 +000017141 return target;
17142}
17143
17144
17145static uint64_t DoubleToBits(double value) {
17146 uint64_t target;
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +000017147 i::OS::MemCopy(&target, &value, sizeof(target));
ager@chromium.org3811b432009-10-28 14:53:37 +000017148 return target;
17149}
17150
17151
17152static double DoubleToDateTime(double input) {
17153 double date_limit = 864e13;
ulan@chromium.org77ca49a2013-04-22 09:43:56 +000017154 if (std::isnan(input) || input < -date_limit || input > date_limit) {
ager@chromium.org3811b432009-10-28 14:53:37 +000017155 return i::OS::nan_value();
17156 }
17157 return (input < 0) ? -(floor(-input)) : floor(input);
17158}
17159
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000017160
ager@chromium.org3811b432009-10-28 14:53:37 +000017161// We don't have a consistent way to write 64-bit constants syntactically, so we
17162// split them into two 32-bit constants and combine them programmatically.
17163static double DoubleFromBits(uint32_t high_bits, uint32_t low_bits) {
17164 return DoubleFromBits((static_cast<uint64_t>(high_bits) << 32) | low_bits);
17165}
17166
17167
17168THREADED_TEST(QuietSignalingNaNs) {
ager@chromium.org3811b432009-10-28 14:53:37 +000017169 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017170 v8::HandleScope scope(context->GetIsolate());
ager@chromium.org3811b432009-10-28 14:53:37 +000017171 v8::TryCatch try_catch;
17172
17173 // Special double values.
17174 double snan = DoubleFromBits(0x7ff00000, 0x00000001);
17175 double qnan = DoubleFromBits(0x7ff80000, 0x00000000);
17176 double infinity = DoubleFromBits(0x7ff00000, 0x00000000);
17177 double max_normal = DoubleFromBits(0x7fefffff, 0xffffffffu);
17178 double min_normal = DoubleFromBits(0x00100000, 0x00000000);
17179 double max_denormal = DoubleFromBits(0x000fffff, 0xffffffffu);
17180 double min_denormal = DoubleFromBits(0x00000000, 0x00000001);
17181
17182 // Date values are capped at +/-100000000 days (times 864e5 ms per day)
17183 // on either side of the epoch.
17184 double date_limit = 864e13;
17185
17186 double test_values[] = {
17187 snan,
17188 qnan,
17189 infinity,
17190 max_normal,
17191 date_limit + 1,
17192 date_limit,
17193 min_normal,
17194 max_denormal,
17195 min_denormal,
17196 0,
17197 -0,
17198 -min_denormal,
17199 -max_denormal,
17200 -min_normal,
17201 -date_limit,
17202 -date_limit - 1,
17203 -max_normal,
17204 -infinity,
17205 -qnan,
17206 -snan
17207 };
17208 int num_test_values = 20;
17209
17210 for (int i = 0; i < num_test_values; i++) {
17211 double test_value = test_values[i];
17212
17213 // Check that Number::New preserves non-NaNs and quiets SNaNs.
17214 v8::Handle<v8::Value> number = v8::Number::New(test_value);
17215 double stored_number = number->NumberValue();
ulan@chromium.org77ca49a2013-04-22 09:43:56 +000017216 if (!std::isnan(test_value)) {
ager@chromium.org3811b432009-10-28 14:53:37 +000017217 CHECK_EQ(test_value, stored_number);
17218 } else {
17219 uint64_t stored_bits = DoubleToBits(stored_number);
17220 // Check if quiet nan (bits 51..62 all set).
danno@chromium.orgc612e022011-11-10 11:38:15 +000017221#if defined(V8_TARGET_ARCH_MIPS) && !defined(USE_SIMULATOR)
17222 // Most significant fraction bit for quiet nan is set to 0
17223 // on MIPS architecture. Allowed by IEEE-754.
17224 CHECK_EQ(0xffe, static_cast<int>((stored_bits >> 51) & 0xfff));
17225#else
ager@chromium.org3811b432009-10-28 14:53:37 +000017226 CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff));
danno@chromium.orgc612e022011-11-10 11:38:15 +000017227#endif
ager@chromium.org3811b432009-10-28 14:53:37 +000017228 }
17229
17230 // Check that Date::New preserves non-NaNs in the date range and
17231 // quiets SNaNs.
17232 v8::Handle<v8::Value> date = v8::Date::New(test_value);
17233 double expected_stored_date = DoubleToDateTime(test_value);
17234 double stored_date = date->NumberValue();
ulan@chromium.org77ca49a2013-04-22 09:43:56 +000017235 if (!std::isnan(expected_stored_date)) {
ager@chromium.org3811b432009-10-28 14:53:37 +000017236 CHECK_EQ(expected_stored_date, stored_date);
17237 } else {
17238 uint64_t stored_bits = DoubleToBits(stored_date);
17239 // Check if quiet nan (bits 51..62 all set).
danno@chromium.orgc612e022011-11-10 11:38:15 +000017240#if defined(V8_TARGET_ARCH_MIPS) && !defined(USE_SIMULATOR)
17241 // Most significant fraction bit for quiet nan is set to 0
17242 // on MIPS architecture. Allowed by IEEE-754.
17243 CHECK_EQ(0xffe, static_cast<int>((stored_bits >> 51) & 0xfff));
17244#else
ager@chromium.org3811b432009-10-28 14:53:37 +000017245 CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff));
danno@chromium.orgc612e022011-11-10 11:38:15 +000017246#endif
ager@chromium.org3811b432009-10-28 14:53:37 +000017247 }
17248 }
17249}
christian.plesner.hansen@gmail.comb9ce6372009-11-03 11:38:18 +000017250
17251
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000017252static void SpaghettiIncident(
17253 const v8::FunctionCallbackInfo<v8::Value>& args) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017254 v8::HandleScope scope(args.GetIsolate());
christian.plesner.hansen@gmail.comb9ce6372009-11-03 11:38:18 +000017255 v8::TryCatch tc;
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000017256 v8::Handle<v8::String> str(args[0]->ToString());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000017257 USE(str);
christian.plesner.hansen@gmail.comb9ce6372009-11-03 11:38:18 +000017258 if (tc.HasCaught())
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000017259 tc.ReThrow();
christian.plesner.hansen@gmail.comb9ce6372009-11-03 11:38:18 +000017260}
17261
17262
17263// Test that an exception can be propagated down through a spaghetti
17264// stack using ReThrow.
17265THREADED_TEST(SpaghettiStackReThrow) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017266 v8::HandleScope scope(CcTest::isolate());
christian.plesner.hansen@gmail.comb9ce6372009-11-03 11:38:18 +000017267 LocalContext context;
17268 context->Global()->Set(
17269 v8::String::New("s"),
17270 v8::FunctionTemplate::New(SpaghettiIncident)->GetFunction());
17271 v8::TryCatch try_catch;
17272 CompileRun(
17273 "var i = 0;"
17274 "var o = {"
17275 " toString: function () {"
17276 " if (i == 10) {"
17277 " throw 'Hey!';"
17278 " } else {"
17279 " i++;"
17280 " return s(o);"
17281 " }"
17282 " }"
17283 "};"
17284 "s(o);");
17285 CHECK(try_catch.HasCaught());
17286 v8::String::Utf8Value value(try_catch.Exception());
17287 CHECK_EQ(0, strcmp(*value, "Hey!"));
17288}
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000017289
17290
sgjesse@chromium.org98180592009-12-02 08:17:28 +000017291TEST(Regress528) {
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000017292 v8::V8::Initialize();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017293 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000017294 v8::HandleScope scope(isolate);
17295 v8::Local<Context> other_context;
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000017296 int gc_count;
17297
ager@chromium.org60121232009-12-03 11:25:37 +000017298 // Create a context used to keep the code from aging in the compilation
17299 // cache.
ulan@chromium.org57ff8812013-05-10 08:16:55 +000017300 other_context = Context::New(isolate);
ager@chromium.org60121232009-12-03 11:25:37 +000017301
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000017302 // Context-dependent context data creates reference from the compilation
17303 // cache to the global object.
ager@chromium.org60121232009-12-03 11:25:37 +000017304 const char* source_simple = "1";
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000017305 {
ulan@chromium.org57ff8812013-05-10 08:16:55 +000017306 v8::HandleScope scope(isolate);
17307 v8::Local<Context> context = Context::New(isolate);
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000017308
17309 context->Enter();
17310 Local<v8::String> obj = v8::String::New("");
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000017311 context->SetEmbedderData(0, obj);
ager@chromium.org60121232009-12-03 11:25:37 +000017312 CompileRun(source_simple);
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000017313 context->Exit();
17314 }
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000017315 v8::V8::ContextDisposedNotification();
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000017316 for (gc_count = 1; gc_count < 10; gc_count++) {
ager@chromium.org60121232009-12-03 11:25:37 +000017317 other_context->Enter();
17318 CompileRun(source_simple);
17319 other_context->Exit();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017320 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org60121232009-12-03 11:25:37 +000017321 if (GetGlobalObjectsCount() == 1) break;
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000017322 }
ager@chromium.org60121232009-12-03 11:25:37 +000017323 CHECK_GE(2, gc_count);
17324 CHECK_EQ(1, GetGlobalObjectsCount());
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000017325
17326 // Eval in a function creates reference from the compilation cache to the
17327 // global object.
ager@chromium.org60121232009-12-03 11:25:37 +000017328 const char* source_eval = "function f(){eval('1')}; f()";
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000017329 {
ulan@chromium.org57ff8812013-05-10 08:16:55 +000017330 v8::HandleScope scope(isolate);
17331 v8::Local<Context> context = Context::New(isolate);
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000017332
17333 context->Enter();
ager@chromium.org60121232009-12-03 11:25:37 +000017334 CompileRun(source_eval);
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000017335 context->Exit();
17336 }
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000017337 v8::V8::ContextDisposedNotification();
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000017338 for (gc_count = 1; gc_count < 10; gc_count++) {
ager@chromium.org60121232009-12-03 11:25:37 +000017339 other_context->Enter();
17340 CompileRun(source_eval);
17341 other_context->Exit();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017342 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org60121232009-12-03 11:25:37 +000017343 if (GetGlobalObjectsCount() == 1) break;
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000017344 }
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +000017345 CHECK_GE(2, gc_count);
sgjesse@chromium.org98180592009-12-02 08:17:28 +000017346 CHECK_EQ(1, GetGlobalObjectsCount());
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000017347
17348 // Looking up the line number for an exception creates reference from the
17349 // compilation cache to the global object.
ager@chromium.org60121232009-12-03 11:25:37 +000017350 const char* source_exception = "function f(){throw 1;} f()";
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000017351 {
ulan@chromium.org57ff8812013-05-10 08:16:55 +000017352 v8::HandleScope scope(isolate);
17353 v8::Local<Context> context = Context::New(isolate);
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000017354
17355 context->Enter();
17356 v8::TryCatch try_catch;
ager@chromium.org60121232009-12-03 11:25:37 +000017357 CompileRun(source_exception);
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000017358 CHECK(try_catch.HasCaught());
17359 v8::Handle<v8::Message> message = try_catch.Message();
17360 CHECK(!message.IsEmpty());
17361 CHECK_EQ(1, message->GetLineNumber());
17362 context->Exit();
17363 }
svenpanne@chromium.orgc859c4f2012-10-15 11:51:39 +000017364 v8::V8::ContextDisposedNotification();
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000017365 for (gc_count = 1; gc_count < 10; gc_count++) {
ager@chromium.org60121232009-12-03 11:25:37 +000017366 other_context->Enter();
17367 CompileRun(source_exception);
17368 other_context->Exit();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017369 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org60121232009-12-03 11:25:37 +000017370 if (GetGlobalObjectsCount() == 1) break;
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000017371 }
ager@chromium.org60121232009-12-03 11:25:37 +000017372 CHECK_GE(2, gc_count);
17373 CHECK_EQ(1, GetGlobalObjectsCount());
17374
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000017375 v8::V8::ContextDisposedNotification();
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000017376}
ager@chromium.org5c838252010-02-19 08:53:10 +000017377
17378
17379THREADED_TEST(ScriptOrigin) {
ager@chromium.org5c838252010-02-19 08:53:10 +000017380 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017381 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org5c838252010-02-19 08:53:10 +000017382 v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::New("test"));
17383 v8::Handle<v8::String> script = v8::String::New(
17384 "function f() {}\n\nfunction g() {}");
17385 v8::Script::Compile(script, &origin)->Run();
17386 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
17387 env->Global()->Get(v8::String::New("f")));
17388 v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
17389 env->Global()->Get(v8::String::New("g")));
17390
17391 v8::ScriptOrigin script_origin_f = f->GetScriptOrigin();
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000017392 CHECK_EQ("test", *v8::String::Utf8Value(script_origin_f.ResourceName()));
ager@chromium.org5c838252010-02-19 08:53:10 +000017393 CHECK_EQ(0, script_origin_f.ResourceLineOffset()->Int32Value());
17394
17395 v8::ScriptOrigin script_origin_g = g->GetScriptOrigin();
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000017396 CHECK_EQ("test", *v8::String::Utf8Value(script_origin_g.ResourceName()));
ager@chromium.org5c838252010-02-19 08:53:10 +000017397 CHECK_EQ(0, script_origin_g.ResourceLineOffset()->Int32Value());
17398}
17399
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000017400
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000017401THREADED_TEST(FunctionGetInferredName) {
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000017402 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017403 v8::HandleScope scope(env->GetIsolate());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000017404 v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::New("test"));
17405 v8::Handle<v8::String> script = v8::String::New(
17406 "var foo = { bar : { baz : function() {}}}; var f = foo.bar.baz;");
17407 v8::Script::Compile(script, &origin)->Run();
17408 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
17409 env->Global()->Get(v8::String::New("f")));
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000017410 CHECK_EQ("foo.bar.baz", *v8::String::Utf8Value(f->GetInferredName()));
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000017411}
ager@chromium.org5c838252010-02-19 08:53:10 +000017412
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000017413
ager@chromium.org5c838252010-02-19 08:53:10 +000017414THREADED_TEST(ScriptLineNumber) {
ager@chromium.org5c838252010-02-19 08:53:10 +000017415 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017416 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org5c838252010-02-19 08:53:10 +000017417 v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::New("test"));
17418 v8::Handle<v8::String> script = v8::String::New(
17419 "function f() {}\n\nfunction g() {}");
17420 v8::Script::Compile(script, &origin)->Run();
17421 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
17422 env->Global()->Get(v8::String::New("f")));
17423 v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
17424 env->Global()->Get(v8::String::New("g")));
17425 CHECK_EQ(0, f->GetScriptLineNumber());
17426 CHECK_EQ(2, g->GetScriptLineNumber());
17427}
17428
17429
danno@chromium.orgc612e022011-11-10 11:38:15 +000017430THREADED_TEST(ScriptColumnNumber) {
danno@chromium.orgc612e022011-11-10 11:38:15 +000017431 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017432 v8::HandleScope scope(env->GetIsolate());
danno@chromium.orgc612e022011-11-10 11:38:15 +000017433 v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::New("test"),
17434 v8::Integer::New(3), v8::Integer::New(2));
17435 v8::Handle<v8::String> script = v8::String::New(
17436 "function foo() {}\n\n function bar() {}");
17437 v8::Script::Compile(script, &origin)->Run();
17438 v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
17439 env->Global()->Get(v8::String::New("foo")));
17440 v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
17441 env->Global()->Get(v8::String::New("bar")));
17442 CHECK_EQ(14, foo->GetScriptColumnNumber());
17443 CHECK_EQ(17, bar->GetScriptColumnNumber());
17444}
17445
17446
17447THREADED_TEST(FunctionGetScriptId) {
danno@chromium.orgc612e022011-11-10 11:38:15 +000017448 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017449 v8::HandleScope scope(env->GetIsolate());
danno@chromium.orgc612e022011-11-10 11:38:15 +000017450 v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::New("test"),
17451 v8::Integer::New(3), v8::Integer::New(2));
17452 v8::Handle<v8::String> scriptSource = v8::String::New(
17453 "function foo() {}\n\n function bar() {}");
17454 v8::Local<v8::Script> script(v8::Script::Compile(scriptSource, &origin));
17455 script->Run();
17456 v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
17457 env->Global()->Get(v8::String::New("foo")));
17458 v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
17459 env->Global()->Get(v8::String::New("bar")));
17460 CHECK_EQ(script->Id(), foo->GetScriptId());
17461 CHECK_EQ(script->Id(), bar->GetScriptId());
17462}
17463
17464
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000017465static void GetterWhichReturns42(
17466 Local<String> name,
17467 const v8::PropertyCallbackInfo<v8::Value>& info) {
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000017468 CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
17469 CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000017470 info.GetReturnValue().Set(v8_num(42));
ager@chromium.org5c838252010-02-19 08:53:10 +000017471}
17472
17473
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000017474static void SetterWhichSetsYOnThisTo23(
17475 Local<String> name,
17476 Local<Value> value,
17477 const v8::PropertyCallbackInfo<void>& info) {
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000017478 CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
17479 CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
ager@chromium.org5c838252010-02-19 08:53:10 +000017480 info.This()->Set(v8_str("y"), v8_num(23));
17481}
17482
17483
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000017484void FooGetInterceptor(Local<String> name,
17485 const v8::PropertyCallbackInfo<v8::Value>& info) {
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000017486 CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
17487 CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000017488 if (!name->Equals(v8_str("foo"))) return;
17489 info.GetReturnValue().Set(v8_num(42));
erik.corry@gmail.com88767242012-08-08 14:43:45 +000017490}
17491
17492
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000017493void FooSetInterceptor(Local<String> name,
17494 Local<Value> value,
17495 const v8::PropertyCallbackInfo<v8::Value>& info) {
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000017496 CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
17497 CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000017498 if (!name->Equals(v8_str("foo"))) return;
erik.corry@gmail.com88767242012-08-08 14:43:45 +000017499 info.This()->Set(v8_str("y"), v8_num(23));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000017500 info.GetReturnValue().Set(v8_num(23));
erik.corry@gmail.com88767242012-08-08 14:43:45 +000017501}
17502
17503
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000017504TEST(SetterOnConstructorPrototype) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017505 v8::HandleScope scope(CcTest::isolate());
ager@chromium.org5c838252010-02-19 08:53:10 +000017506 Local<ObjectTemplate> templ = ObjectTemplate::New();
17507 templ->SetAccessor(v8_str("x"),
17508 GetterWhichReturns42,
17509 SetterWhichSetsYOnThisTo23);
17510 LocalContext context;
17511 context->Global()->Set(v8_str("P"), templ->NewInstance());
17512 CompileRun("function C1() {"
17513 " this.x = 23;"
17514 "};"
17515 "C1.prototype = P;"
17516 "function C2() {"
17517 " this.x = 23"
17518 "};"
17519 "C2.prototype = { };"
17520 "C2.prototype.__proto__ = P;");
17521
17522 v8::Local<v8::Script> script;
17523 script = v8::Script::Compile(v8_str("new C1();"));
17524 for (int i = 0; i < 10; i++) {
17525 v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
17526 CHECK_EQ(42, c1->Get(v8_str("x"))->Int32Value());
17527 CHECK_EQ(23, c1->Get(v8_str("y"))->Int32Value());
17528 }
17529
17530 script = v8::Script::Compile(v8_str("new C2();"));
17531 for (int i = 0; i < 10; i++) {
17532 v8::Handle<v8::Object> c2 = v8::Handle<v8::Object>::Cast(script->Run());
17533 CHECK_EQ(42, c2->Get(v8_str("x"))->Int32Value());
17534 CHECK_EQ(23, c2->Get(v8_str("y"))->Int32Value());
17535 }
17536}
17537
17538
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000017539static void NamedPropertyGetterWhichReturns42(
17540 Local<String> name,
17541 const v8::PropertyCallbackInfo<v8::Value>& info) {
17542 info.GetReturnValue().Set(v8_num(42));
ager@chromium.org5c838252010-02-19 08:53:10 +000017543}
17544
17545
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000017546static void NamedPropertySetterWhichSetsYOnThisTo23(
17547 Local<String> name,
17548 Local<Value> value,
17549 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.org5c838252010-02-19 08:53:10 +000017550 if (name->Equals(v8_str("x"))) {
17551 info.This()->Set(v8_str("y"), v8_num(23));
17552 }
ager@chromium.org5c838252010-02-19 08:53:10 +000017553}
17554
17555
17556THREADED_TEST(InterceptorOnConstructorPrototype) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017557 v8::HandleScope scope(CcTest::isolate());
ager@chromium.org5c838252010-02-19 08:53:10 +000017558 Local<ObjectTemplate> templ = ObjectTemplate::New();
17559 templ->SetNamedPropertyHandler(NamedPropertyGetterWhichReturns42,
17560 NamedPropertySetterWhichSetsYOnThisTo23);
17561 LocalContext context;
17562 context->Global()->Set(v8_str("P"), templ->NewInstance());
17563 CompileRun("function C1() {"
17564 " this.x = 23;"
17565 "};"
17566 "C1.prototype = P;"
17567 "function C2() {"
17568 " this.x = 23"
17569 "};"
17570 "C2.prototype = { };"
17571 "C2.prototype.__proto__ = P;");
17572
17573 v8::Local<v8::Script> script;
17574 script = v8::Script::Compile(v8_str("new C1();"));
17575 for (int i = 0; i < 10; i++) {
17576 v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
17577 CHECK_EQ(23, c1->Get(v8_str("x"))->Int32Value());
17578 CHECK_EQ(42, c1->Get(v8_str("y"))->Int32Value());
17579 }
17580
17581 script = v8::Script::Compile(v8_str("new C2();"));
17582 for (int i = 0; i < 10; i++) {
17583 v8::Handle<v8::Object> c2 = v8::Handle<v8::Object>::Cast(script->Run());
17584 CHECK_EQ(23, c2->Get(v8_str("x"))->Int32Value());
17585 CHECK_EQ(42, c2->Get(v8_str("y"))->Int32Value());
17586 }
17587}
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000017588
17589
danno@chromium.orgf005df62013-04-30 16:36:45 +000017590TEST(Regress618) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000017591 const char* source = "function C1() {"
17592 " this.x = 23;"
17593 "};"
17594 "C1.prototype = P;";
17595
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000017596 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017597 v8::HandleScope scope(context->GetIsolate());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000017598 v8::Local<v8::Script> script;
17599
17600 // Use a simple object as prototype.
17601 v8::Local<v8::Object> prototype = v8::Object::New();
17602 prototype->Set(v8_str("y"), v8_num(42));
17603 context->Global()->Set(v8_str("P"), prototype);
17604
17605 // This compile will add the code to the compilation cache.
17606 CompileRun(source);
17607
17608 script = v8::Script::Compile(v8_str("new C1();"));
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +000017609 // Allow enough iterations for the inobject slack tracking logic
17610 // to finalize instance size and install the fast construct stub.
17611 for (int i = 0; i < 256; i++) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000017612 v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
17613 CHECK_EQ(23, c1->Get(v8_str("x"))->Int32Value());
17614 CHECK_EQ(42, c1->Get(v8_str("y"))->Int32Value());
17615 }
17616
17617 // Use an API object with accessors as prototype.
17618 Local<ObjectTemplate> templ = ObjectTemplate::New();
17619 templ->SetAccessor(v8_str("x"),
17620 GetterWhichReturns42,
17621 SetterWhichSetsYOnThisTo23);
17622 context->Global()->Set(v8_str("P"), templ->NewInstance());
17623
17624 // This compile will get the code from the compilation cache.
17625 CompileRun(source);
17626
17627 script = v8::Script::Compile(v8_str("new C1();"));
17628 for (int i = 0; i < 10; i++) {
17629 v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
17630 CHECK_EQ(42, c1->Get(v8_str("x"))->Int32Value());
17631 CHECK_EQ(23, c1->Get(v8_str("y"))->Int32Value());
17632 }
17633}
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000017634
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017635v8::Isolate* gc_callbacks_isolate = NULL;
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000017636int prologue_call_count = 0;
17637int epilogue_call_count = 0;
17638int prologue_call_count_second = 0;
17639int epilogue_call_count_second = 0;
17640
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017641void PrologueCallback(v8::GCType, v8::GCCallbackFlags flags) {
17642 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000017643 ++prologue_call_count;
17644}
17645
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000017646
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017647void PrologueCallback(v8::Isolate* isolate,
17648 v8::GCType,
17649 v8::GCCallbackFlags flags) {
17650 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
17651 CHECK_EQ(gc_callbacks_isolate, isolate);
17652 ++prologue_call_count;
17653}
17654
17655
17656void EpilogueCallback(v8::GCType, v8::GCCallbackFlags flags) {
17657 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000017658 ++epilogue_call_count;
17659}
17660
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000017661
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017662void EpilogueCallback(v8::Isolate* isolate,
17663 v8::GCType,
17664 v8::GCCallbackFlags flags) {
17665 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
17666 CHECK_EQ(gc_callbacks_isolate, isolate);
17667 ++epilogue_call_count;
17668}
17669
17670
17671void PrologueCallbackSecond(v8::GCType, v8::GCCallbackFlags flags) {
17672 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000017673 ++prologue_call_count_second;
17674}
17675
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000017676
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017677void PrologueCallbackSecond(v8::Isolate* isolate,
17678 v8::GCType,
17679 v8::GCCallbackFlags flags) {
17680 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
17681 CHECK_EQ(gc_callbacks_isolate, isolate);
17682 ++prologue_call_count_second;
17683}
17684
17685
17686void EpilogueCallbackSecond(v8::GCType, v8::GCCallbackFlags flags) {
17687 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000017688 ++epilogue_call_count_second;
17689}
17690
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000017691
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017692void EpilogueCallbackSecond(v8::Isolate* isolate,
17693 v8::GCType,
17694 v8::GCCallbackFlags flags) {
17695 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
17696 CHECK_EQ(gc_callbacks_isolate, isolate);
17697 ++epilogue_call_count_second;
17698}
17699
17700
17701TEST(GCCallbacksOld) {
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000017702 LocalContext context;
17703
17704 v8::V8::AddGCPrologueCallback(PrologueCallback);
17705 v8::V8::AddGCEpilogueCallback(EpilogueCallback);
17706 CHECK_EQ(0, prologue_call_count);
17707 CHECK_EQ(0, epilogue_call_count);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017708 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000017709 CHECK_EQ(1, prologue_call_count);
17710 CHECK_EQ(1, epilogue_call_count);
17711 v8::V8::AddGCPrologueCallback(PrologueCallbackSecond);
17712 v8::V8::AddGCEpilogueCallback(EpilogueCallbackSecond);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017713 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000017714 CHECK_EQ(2, prologue_call_count);
17715 CHECK_EQ(2, epilogue_call_count);
17716 CHECK_EQ(1, prologue_call_count_second);
17717 CHECK_EQ(1, epilogue_call_count_second);
17718 v8::V8::RemoveGCPrologueCallback(PrologueCallback);
17719 v8::V8::RemoveGCEpilogueCallback(EpilogueCallback);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017720 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000017721 CHECK_EQ(2, prologue_call_count);
17722 CHECK_EQ(2, epilogue_call_count);
17723 CHECK_EQ(2, prologue_call_count_second);
17724 CHECK_EQ(2, epilogue_call_count_second);
17725 v8::V8::RemoveGCPrologueCallback(PrologueCallbackSecond);
17726 v8::V8::RemoveGCEpilogueCallback(EpilogueCallbackSecond);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017727 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
17728 CHECK_EQ(2, prologue_call_count);
17729 CHECK_EQ(2, epilogue_call_count);
17730 CHECK_EQ(2, prologue_call_count_second);
17731 CHECK_EQ(2, epilogue_call_count_second);
17732}
17733
17734
17735TEST(GCCallbacks) {
17736 LocalContext context;
17737 v8::Isolate* isolate = context->GetIsolate();
17738 gc_callbacks_isolate = isolate;
17739 isolate->AddGCPrologueCallback(PrologueCallback);
17740 isolate->AddGCEpilogueCallback(EpilogueCallback);
17741 CHECK_EQ(0, prologue_call_count);
17742 CHECK_EQ(0, epilogue_call_count);
17743 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
17744 CHECK_EQ(1, prologue_call_count);
17745 CHECK_EQ(1, epilogue_call_count);
17746 isolate->AddGCPrologueCallback(PrologueCallbackSecond);
17747 isolate->AddGCEpilogueCallback(EpilogueCallbackSecond);
17748 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
17749 CHECK_EQ(2, prologue_call_count);
17750 CHECK_EQ(2, epilogue_call_count);
17751 CHECK_EQ(1, prologue_call_count_second);
17752 CHECK_EQ(1, epilogue_call_count_second);
17753 isolate->RemoveGCPrologueCallback(PrologueCallback);
17754 isolate->RemoveGCEpilogueCallback(EpilogueCallback);
17755 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
17756 CHECK_EQ(2, prologue_call_count);
17757 CHECK_EQ(2, epilogue_call_count);
17758 CHECK_EQ(2, prologue_call_count_second);
17759 CHECK_EQ(2, epilogue_call_count_second);
17760 isolate->RemoveGCPrologueCallback(PrologueCallbackSecond);
17761 isolate->RemoveGCEpilogueCallback(EpilogueCallbackSecond);
17762 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000017763 CHECK_EQ(2, prologue_call_count);
17764 CHECK_EQ(2, epilogue_call_count);
17765 CHECK_EQ(2, prologue_call_count_second);
17766 CHECK_EQ(2, epilogue_call_count_second);
17767}
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017768
17769
17770THREADED_TEST(AddToJSFunctionResultCache) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000017771 i::FLAG_stress_compaction = false;
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017772 i::FLAG_allow_natives_syntax = true;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017773 v8::HandleScope scope(CcTest::isolate());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017774
17775 LocalContext context;
17776
17777 const char* code =
17778 "(function() {"
17779 " var key0 = 'a';"
17780 " var key1 = 'b';"
17781 " var r0 = %_GetFromCache(0, key0);"
17782 " var r1 = %_GetFromCache(0, key1);"
17783 " var r0_ = %_GetFromCache(0, key0);"
17784 " if (r0 !== r0_)"
17785 " return 'Different results for ' + key0 + ': ' + r0 + ' vs. ' + r0_;"
17786 " var r1_ = %_GetFromCache(0, key1);"
17787 " if (r1 !== r1_)"
17788 " return 'Different results for ' + key1 + ': ' + r1 + ' vs. ' + r1_;"
17789 " return 'PASSED';"
17790 "})()";
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017791 CcTest::heap()->ClearJSFunctionResultCaches();
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017792 ExpectString(code, "PASSED");
17793}
17794
17795
17796static const int k0CacheSize = 16;
17797
17798THREADED_TEST(FillJSFunctionResultCache) {
17799 i::FLAG_allow_natives_syntax = true;
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017800 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017801 v8::HandleScope scope(context->GetIsolate());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017802
17803 const char* code =
17804 "(function() {"
17805 " var k = 'a';"
17806 " var r = %_GetFromCache(0, k);"
17807 " for (var i = 0; i < 16; i++) {"
17808 " %_GetFromCache(0, 'a' + i);"
17809 " };"
17810 " if (r === %_GetFromCache(0, k))"
17811 " return 'FAILED: k0CacheSize is too small';"
17812 " return 'PASSED';"
17813 "})()";
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017814 CcTest::heap()->ClearJSFunctionResultCaches();
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017815 ExpectString(code, "PASSED");
17816}
17817
17818
17819THREADED_TEST(RoundRobinGetFromCache) {
17820 i::FLAG_allow_natives_syntax = true;
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017821 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017822 v8::HandleScope scope(context->GetIsolate());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017823
17824 const char* code =
17825 "(function() {"
17826 " var keys = [];"
17827 " for (var i = 0; i < 16; i++) keys.push(i);"
17828 " var values = [];"
17829 " for (var i = 0; i < 16; i++) values[i] = %_GetFromCache(0, keys[i]);"
17830 " for (var i = 0; i < 16; i++) {"
17831 " var v = %_GetFromCache(0, keys[i]);"
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000017832 " if (v.toString() !== values[i].toString())"
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017833 " return 'Wrong value for ' + "
17834 " keys[i] + ': ' + v + ' vs. ' + values[i];"
17835 " };"
17836 " return 'PASSED';"
17837 "})()";
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017838 CcTest::heap()->ClearJSFunctionResultCaches();
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017839 ExpectString(code, "PASSED");
17840}
17841
17842
17843THREADED_TEST(ReverseGetFromCache) {
17844 i::FLAG_allow_natives_syntax = true;
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017845 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017846 v8::HandleScope scope(context->GetIsolate());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017847
17848 const char* code =
17849 "(function() {"
17850 " var keys = [];"
17851 " for (var i = 0; i < 16; i++) keys.push(i);"
17852 " var values = [];"
17853 " for (var i = 0; i < 16; i++) values[i] = %_GetFromCache(0, keys[i]);"
17854 " for (var i = 15; i >= 16; i--) {"
17855 " var v = %_GetFromCache(0, keys[i]);"
17856 " if (v !== values[i])"
17857 " return 'Wrong value for ' + "
17858 " keys[i] + ': ' + v + ' vs. ' + values[i];"
17859 " };"
17860 " return 'PASSED';"
17861 "})()";
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017862 CcTest::heap()->ClearJSFunctionResultCaches();
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017863 ExpectString(code, "PASSED");
17864}
17865
17866
17867THREADED_TEST(TestEviction) {
17868 i::FLAG_allow_natives_syntax = true;
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017869 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017870 v8::HandleScope scope(context->GetIsolate());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017871
17872 const char* code =
17873 "(function() {"
17874 " for (var i = 0; i < 2*16; i++) {"
17875 " %_GetFromCache(0, 'a' + i);"
17876 " };"
17877 " return 'PASSED';"
17878 "})()";
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017879 CcTest::heap()->ClearJSFunctionResultCaches();
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017880 ExpectString(code, "PASSED");
17881}
lrn@chromium.org32d961d2010-06-30 09:09:34 +000017882
17883
17884THREADED_TEST(TwoByteStringInAsciiCons) {
17885 // See Chromium issue 47824.
lrn@chromium.org32d961d2010-06-30 09:09:34 +000017886 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017887 v8::HandleScope scope(context->GetIsolate());
17888
lrn@chromium.org32d961d2010-06-30 09:09:34 +000017889 const char* init_code =
17890 "var str1 = 'abelspendabel';"
17891 "var str2 = str1 + str1 + str1;"
17892 "str2;";
17893 Local<Value> result = CompileRun(init_code);
17894
ricow@chromium.orgddd545c2011-08-24 12:02:41 +000017895 Local<Value> indexof = CompileRun("str2.indexOf('els')");
17896 Local<Value> lastindexof = CompileRun("str2.lastIndexOf('dab')");
17897
lrn@chromium.org32d961d2010-06-30 09:09:34 +000017898 CHECK(result->IsString());
17899 i::Handle<i::String> string = v8::Utils::OpenHandle(String::Cast(*result));
17900 int length = string->length();
ulan@chromium.org8e8d8822012-11-23 14:36:46 +000017901 CHECK(string->IsOneByteRepresentation());
lrn@chromium.org32d961d2010-06-30 09:09:34 +000017902
17903 FlattenString(string);
17904 i::Handle<i::String> flat_string = FlattenGetString(string);
17905
ulan@chromium.org8e8d8822012-11-23 14:36:46 +000017906 CHECK(string->IsOneByteRepresentation());
17907 CHECK(flat_string->IsOneByteRepresentation());
lrn@chromium.org32d961d2010-06-30 09:09:34 +000017908
17909 // Create external resource.
17910 uint16_t* uc16_buffer = new uint16_t[length + 1];
17911
17912 i::String::WriteToFlat(*flat_string, uc16_buffer, 0, length);
17913 uc16_buffer[length] = 0;
17914
17915 TestResource resource(uc16_buffer);
17916
17917 flat_string->MakeExternal(&resource);
17918
17919 CHECK(flat_string->IsTwoByteRepresentation());
17920
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +000017921 // If the cons string has been short-circuited, skip the following checks.
17922 if (!string.is_identical_to(flat_string)) {
17923 // At this point, we should have a Cons string which is flat and ASCII,
17924 // with a first half that is a two-byte string (although it only contains
17925 // ASCII characters). This is a valid sequence of steps, and it can happen
17926 // in real pages.
17927 CHECK(string->IsOneByteRepresentation());
17928 i::ConsString* cons = i::ConsString::cast(*string);
17929 CHECK_EQ(0, cons->second()->length());
17930 CHECK(cons->first()->IsTwoByteRepresentation());
17931 }
lrn@chromium.org32d961d2010-06-30 09:09:34 +000017932
17933 // Check that some string operations work.
17934
17935 // Atom RegExp.
17936 Local<Value> reresult = CompileRun("str2.match(/abel/g).length;");
17937 CHECK_EQ(6, reresult->Int32Value());
17938
17939 // Nonatom RegExp.
17940 reresult = CompileRun("str2.match(/abe./g).length;");
17941 CHECK_EQ(6, reresult->Int32Value());
17942
17943 reresult = CompileRun("str2.search(/bel/g);");
17944 CHECK_EQ(1, reresult->Int32Value());
17945
17946 reresult = CompileRun("str2.search(/be./g);");
17947 CHECK_EQ(1, reresult->Int32Value());
17948
17949 ExpectTrue("/bel/g.test(str2);");
17950
17951 ExpectTrue("/be./g.test(str2);");
17952
17953 reresult = CompileRun("/bel/g.exec(str2);");
17954 CHECK(!reresult->IsNull());
17955
17956 reresult = CompileRun("/be./g.exec(str2);");
17957 CHECK(!reresult->IsNull());
17958
17959 ExpectString("str2.substring(2, 10);", "elspenda");
17960
17961 ExpectString("str2.substring(2, 20);", "elspendabelabelspe");
17962
17963 ExpectString("str2.charAt(2);", "e");
17964
ricow@chromium.orgddd545c2011-08-24 12:02:41 +000017965 ExpectObject("str2.indexOf('els');", indexof);
17966
17967 ExpectObject("str2.lastIndexOf('dab');", lastindexof);
17968
lrn@chromium.org32d961d2010-06-30 09:09:34 +000017969 reresult = CompileRun("str2.charCodeAt(2);");
17970 CHECK_EQ(static_cast<int32_t>('e'), reresult->Int32Value());
17971}
ager@chromium.orgea4f62e2010-08-16 16:28:43 +000017972
17973
ulan@chromium.orgdfe53072013-06-06 14:14:51 +000017974TEST(ContainsOnlyOneByte) {
17975 v8::V8::Initialize();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017976 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.orgdfe53072013-06-06 14:14:51 +000017977 v8::HandleScope scope(isolate);
17978 // Make a buffer long enough that it won't automatically be converted.
verwaest@chromium.org8a00e822013-06-10 15:11:22 +000017979 const int length = 512;
17980 // Ensure word aligned assignment.
17981 const int aligned_length = length*sizeof(uintptr_t)/sizeof(uint16_t);
17982 i::SmartArrayPointer<uintptr_t>
17983 aligned_contents(new uintptr_t[aligned_length]);
17984 uint16_t* string_contents = reinterpret_cast<uint16_t*>(*aligned_contents);
ulan@chromium.orgdfe53072013-06-06 14:14:51 +000017985 // Set to contain only one byte.
17986 for (int i = 0; i < length-1; i++) {
17987 string_contents[i] = 0x41;
17988 }
17989 string_contents[length-1] = 0;
17990 // Simple case.
17991 Handle<String> string;
verwaest@chromium.org8a00e822013-06-10 15:11:22 +000017992 string = String::NewExternal(new TestResource(string_contents));
ulan@chromium.orgdfe53072013-06-06 14:14:51 +000017993 CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
17994 // Counter example.
verwaest@chromium.org8a00e822013-06-10 15:11:22 +000017995 string = String::NewFromTwoByte(isolate, string_contents);
ulan@chromium.orgdfe53072013-06-06 14:14:51 +000017996 CHECK(string->IsOneByte() && string->ContainsOnlyOneByte());
17997 // Test left right and balanced cons strings.
17998 Handle<String> base = String::NewFromUtf8(isolate, "a");
17999 Handle<String> left = base;
18000 Handle<String> right = base;
18001 for (int i = 0; i < 1000; i++) {
18002 left = String::Concat(base, left);
18003 right = String::Concat(right, base);
18004 }
18005 Handle<String> balanced = String::Concat(left, base);
18006 balanced = String::Concat(balanced, right);
18007 Handle<String> cons_strings[] = {left, balanced, right};
18008 Handle<String> two_byte =
verwaest@chromium.org8a00e822013-06-10 15:11:22 +000018009 String::NewExternal(new TestResource(string_contents));
ulan@chromium.orgdfe53072013-06-06 14:14:51 +000018010 for (size_t i = 0; i < ARRAY_SIZE(cons_strings); i++) {
18011 // Base assumptions.
18012 string = cons_strings[i];
18013 CHECK(string->IsOneByte() && string->ContainsOnlyOneByte());
18014 // Test left and right concatentation.
18015 string = String::Concat(two_byte, cons_strings[i]);
18016 CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
18017 string = String::Concat(cons_strings[i], two_byte);
18018 CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
18019 }
verwaest@chromium.org8a00e822013-06-10 15:11:22 +000018020 // Set bits in different positions
18021 // for strings of different lengths and alignments.
18022 for (int alignment = 0; alignment < 7; alignment++) {
18023 for (int size = 2; alignment + size < length; size *= 2) {
18024 int zero_offset = size + alignment;
18025 string_contents[zero_offset] = 0;
18026 for (int i = 0; i < size; i++) {
18027 int shift = 8 + (i % 7);
18028 string_contents[alignment + i] = 1 << shift;
18029 string =
18030 String::NewExternal(new TestResource(string_contents + alignment));
18031 CHECK_EQ(size, string->Length());
18032 CHECK(!string->ContainsOnlyOneByte());
18033 string_contents[alignment + i] = 0x41;
18034 }
18035 string_contents[zero_offset] = 0x41;
18036 }
18037 }
ulan@chromium.orgdfe53072013-06-06 14:14:51 +000018038}
18039
18040
ager@chromium.orgea4f62e2010-08-16 16:28:43 +000018041// Failed access check callback that performs a GC on each invocation.
18042void FailedAccessCheckCallbackGC(Local<v8::Object> target,
18043 v8::AccessType type,
18044 Local<v8::Value> data) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018045 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.orgea4f62e2010-08-16 16:28:43 +000018046}
18047
18048
18049TEST(GCInFailedAccessCheckCallback) {
18050 // Install a failed access check callback that performs a GC on each
18051 // invocation. Then force the callback to be called from va
18052
18053 v8::V8::Initialize();
18054 v8::V8::SetFailedAccessCheckCallbackFunction(&FailedAccessCheckCallbackGC);
18055
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018056 v8::HandleScope scope(CcTest::isolate());
ager@chromium.orgea4f62e2010-08-16 16:28:43 +000018057
18058 // Create an ObjectTemplate for global objects and install access
18059 // check callbacks that will block access.
18060 v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
18061 global_template->SetAccessCheckCallbacks(NamedGetAccessBlocker,
18062 IndexedGetAccessBlocker,
18063 v8::Handle<v8::Value>(),
18064 false);
18065
18066 // Create a context and set an x property on it's global object.
18067 LocalContext context0(NULL, global_template);
18068 context0->Global()->Set(v8_str("x"), v8_num(42));
18069 v8::Handle<v8::Object> global0 = context0->Global();
18070
18071 // Create a context with a different security token so that the
18072 // failed access check callback will be called on each access.
18073 LocalContext context1(NULL, global_template);
18074 context1->Global()->Set(v8_str("other"), global0);
18075
18076 // Get property with failed access check.
18077 ExpectUndefined("other.x");
18078
18079 // Get element with failed access check.
18080 ExpectUndefined("other[0]");
18081
18082 // Set property with failed access check.
18083 v8::Handle<v8::Value> result = CompileRun("other.x = new Object()");
18084 CHECK(result->IsObject());
18085
18086 // Set element with failed access check.
18087 result = CompileRun("other[0] = new Object()");
18088 CHECK(result->IsObject());
18089
18090 // Get property attribute with failed access check.
18091 ExpectFalse("\'x\' in other");
18092
18093 // Get property attribute for element with failed access check.
18094 ExpectFalse("0 in other");
18095
18096 // Delete property.
18097 ExpectFalse("delete other.x");
18098
18099 // Delete element.
18100 CHECK_EQ(false, global0->Delete(0));
18101
18102 // DefineAccessor.
18103 CHECK_EQ(false,
18104 global0->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("x")));
18105
18106 // Define JavaScript accessor.
18107 ExpectUndefined("Object.prototype.__defineGetter__.call("
18108 " other, \'x\', function() { return 42; })");
18109
18110 // LookupAccessor.
18111 ExpectUndefined("Object.prototype.__lookupGetter__.call("
18112 " other, \'x\')");
18113
18114 // HasLocalElement.
18115 ExpectFalse("Object.prototype.hasOwnProperty.call(other, \'0\')");
18116
18117 CHECK_EQ(false, global0->HasRealIndexedProperty(0));
18118 CHECK_EQ(false, global0->HasRealNamedProperty(v8_str("x")));
18119 CHECK_EQ(false, global0->HasRealNamedCallbackProperty(v8_str("x")));
18120
18121 // Reset the failed access check callback so it does not influence
18122 // the other tests.
18123 v8::V8::SetFailedAccessCheckCallbackFunction(NULL);
18124}
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000018125
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000018126
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000018127TEST(IsolateNewDispose) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018128 v8::Isolate* current_isolate = CcTest::isolate();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000018129 v8::Isolate* isolate = v8::Isolate::New();
18130 CHECK(isolate != NULL);
18131 CHECK(!reinterpret_cast<i::Isolate*>(isolate)->IsDefaultIsolate());
18132 CHECK(current_isolate != isolate);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018133 CHECK(current_isolate == CcTest::isolate());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000018134
18135 v8::V8::SetFatalErrorHandler(StoringErrorCallback);
18136 last_location = last_message = NULL;
18137 isolate->Dispose();
18138 CHECK_EQ(last_location, NULL);
18139 CHECK_EQ(last_message, NULL);
18140}
18141
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000018142
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018143UNINITIALIZED_TEST(DisposeIsolateWhenInUse) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000018144 v8::Isolate* isolate = v8::Isolate::New();
18145 CHECK(isolate);
18146 isolate->Enter();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018147 v8::HandleScope scope(isolate);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018148 LocalContext context(isolate);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000018149 // Run something in this isolate.
18150 ExpectTrue("true");
18151 v8::V8::SetFatalErrorHandler(StoringErrorCallback);
18152 last_location = last_message = NULL;
18153 // Still entered, should fail.
18154 isolate->Dispose();
18155 CHECK_NE(last_location, NULL);
18156 CHECK_NE(last_message, NULL);
18157}
18158
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000018159
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000018160TEST(RunTwoIsolatesOnSingleThread) {
18161 // Run isolate 1.
18162 v8::Isolate* isolate1 = v8::Isolate::New();
18163 isolate1->Enter();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000018164 v8::Persistent<v8::Context> context1;
18165 {
18166 v8::HandleScope scope(isolate1);
18167 context1.Reset(isolate1, Context::New(isolate1));
18168 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000018169
18170 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018171 v8::HandleScope scope(isolate1);
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000018172 v8::Local<v8::Context> context =
18173 v8::Local<v8::Context>::New(isolate1, context1);
18174 v8::Context::Scope context_scope(context);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000018175 // Run something in new isolate.
18176 CompileRun("var foo = 'isolate 1';");
18177 ExpectString("function f() { return foo; }; f()", "isolate 1");
18178 }
18179
18180 // Run isolate 2.
18181 v8::Isolate* isolate2 = v8::Isolate::New();
18182 v8::Persistent<v8::Context> context2;
18183
18184 {
18185 v8::Isolate::Scope iscope(isolate2);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018186 v8::HandleScope scope(isolate2);
ulan@chromium.org57ff8812013-05-10 08:16:55 +000018187 context2.Reset(isolate2, Context::New(isolate2));
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000018188 v8::Local<v8::Context> context =
18189 v8::Local<v8::Context>::New(isolate2, context2);
18190 v8::Context::Scope context_scope(context);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000018191
18192 // Run something in new isolate.
18193 CompileRun("var foo = 'isolate 2';");
18194 ExpectString("function f() { return foo; }; f()", "isolate 2");
18195 }
18196
18197 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018198 v8::HandleScope scope(isolate1);
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000018199 v8::Local<v8::Context> context =
18200 v8::Local<v8::Context>::New(isolate1, context1);
18201 v8::Context::Scope context_scope(context);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000018202 // Now again in isolate 1
18203 ExpectString("function f() { return foo; }; f()", "isolate 1");
18204 }
18205
18206 isolate1->Exit();
18207
18208 // Run some stuff in default isolate.
ulan@chromium.org57ff8812013-05-10 08:16:55 +000018209 v8::Persistent<v8::Context> context_default;
18210 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018211 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000018212 v8::Isolate::Scope iscope(isolate);
18213 v8::HandleScope scope(isolate);
18214 context_default.Reset(isolate, Context::New(isolate));
18215 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000018216
18217 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018218 v8::HandleScope scope(CcTest::isolate());
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000018219 v8::Local<v8::Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018220 v8::Local<v8::Context>::New(CcTest::isolate(), context_default);
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000018221 v8::Context::Scope context_scope(context);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000018222 // Variables in other isolates should be not available, verify there
18223 // is an exception.
18224 ExpectTrue("function f() {"
18225 " try {"
18226 " foo;"
18227 " return false;"
18228 " } catch(e) {"
18229 " return true;"
18230 " }"
18231 "};"
18232 "var isDefaultIsolate = true;"
18233 "f()");
18234 }
18235
18236 isolate1->Enter();
18237
18238 {
18239 v8::Isolate::Scope iscope(isolate2);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018240 v8::HandleScope scope(isolate2);
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000018241 v8::Local<v8::Context> context =
18242 v8::Local<v8::Context>::New(isolate2, context2);
18243 v8::Context::Scope context_scope(context);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000018244 ExpectString("function f() { return foo; }; f()", "isolate 2");
18245 }
18246
18247 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018248 v8::HandleScope scope(v8::Isolate::GetCurrent());
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000018249 v8::Local<v8::Context> context =
18250 v8::Local<v8::Context>::New(v8::Isolate::GetCurrent(), context1);
18251 v8::Context::Scope context_scope(context);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000018252 ExpectString("function f() { return foo; }; f()", "isolate 1");
18253 }
18254
18255 {
18256 v8::Isolate::Scope iscope(isolate2);
rossberg@chromium.org79e79022013-06-03 15:43:46 +000018257 context2.Dispose();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000018258 }
18259
rossberg@chromium.org79e79022013-06-03 15:43:46 +000018260 context1.Dispose();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000018261 isolate1->Exit();
18262
18263 v8::V8::SetFatalErrorHandler(StoringErrorCallback);
18264 last_location = last_message = NULL;
18265
18266 isolate1->Dispose();
18267 CHECK_EQ(last_location, NULL);
18268 CHECK_EQ(last_message, NULL);
18269
18270 isolate2->Dispose();
18271 CHECK_EQ(last_location, NULL);
18272 CHECK_EQ(last_message, NULL);
18273
18274 // Check that default isolate still runs.
18275 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018276 v8::HandleScope scope(CcTest::isolate());
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000018277 v8::Local<v8::Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018278 v8::Local<v8::Context>::New(CcTest::isolate(), context_default);
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000018279 v8::Context::Scope context_scope(context);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000018280 ExpectTrue("function f() { return isDefaultIsolate; }; f()");
18281 }
18282}
18283
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000018284
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000018285static int CalcFibonacci(v8::Isolate* isolate, int limit) {
18286 v8::Isolate::Scope isolate_scope(isolate);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018287 v8::HandleScope scope(isolate);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018288 LocalContext context(isolate);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000018289 i::ScopedVector<char> code(1024);
18290 i::OS::SNPrintF(code, "function fib(n) {"
18291 " if (n <= 2) return 1;"
18292 " return fib(n-1) + fib(n-2);"
18293 "}"
18294 "fib(%d)", limit);
18295 Local<Value> value = CompileRun(code.start());
18296 CHECK(value->IsNumber());
18297 return static_cast<int>(value->NumberValue());
18298}
18299
18300class IsolateThread : public v8::internal::Thread {
18301 public:
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000018302 IsolateThread(v8::Isolate* isolate, int fib_limit)
18303 : Thread("IsolateThread"),
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000018304 isolate_(isolate),
18305 fib_limit_(fib_limit),
18306 result_(0) { }
18307
18308 void Run() {
18309 result_ = CalcFibonacci(isolate_, fib_limit_);
18310 }
18311
18312 int result() { return result_; }
18313
18314 private:
18315 v8::Isolate* isolate_;
18316 int fib_limit_;
18317 int result_;
18318};
18319
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000018320
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000018321TEST(MultipleIsolatesOnIndividualThreads) {
18322 v8::Isolate* isolate1 = v8::Isolate::New();
18323 v8::Isolate* isolate2 = v8::Isolate::New();
18324
18325 IsolateThread thread1(isolate1, 21);
18326 IsolateThread thread2(isolate2, 12);
18327
18328 // Compute some fibonacci numbers on 3 threads in 3 isolates.
18329 thread1.Start();
18330 thread2.Start();
18331
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018332 int result1 = CalcFibonacci(CcTest::isolate(), 21);
18333 int result2 = CalcFibonacci(CcTest::isolate(), 12);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000018334
18335 thread1.Join();
18336 thread2.Join();
18337
18338 // Compare results. The actual fibonacci numbers for 12 and 21 are taken
18339 // (I'm lazy!) from http://en.wikipedia.org/wiki/Fibonacci_number
18340 CHECK_EQ(result1, 10946);
18341 CHECK_EQ(result2, 144);
18342 CHECK_EQ(result1, thread1.result());
18343 CHECK_EQ(result2, thread2.result());
18344
18345 isolate1->Dispose();
18346 isolate2->Dispose();
18347}
18348
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000018349
lrn@chromium.org1c092762011-05-09 09:42:16 +000018350TEST(IsolateDifferentContexts) {
18351 v8::Isolate* isolate = v8::Isolate::New();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000018352 Local<v8::Context> context;
lrn@chromium.org1c092762011-05-09 09:42:16 +000018353 {
18354 v8::Isolate::Scope isolate_scope(isolate);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018355 v8::HandleScope handle_scope(isolate);
ulan@chromium.org57ff8812013-05-10 08:16:55 +000018356 context = v8::Context::New(isolate);
lrn@chromium.org1c092762011-05-09 09:42:16 +000018357 v8::Context::Scope context_scope(context);
18358 Local<Value> v = CompileRun("2");
18359 CHECK(v->IsNumber());
18360 CHECK_EQ(2, static_cast<int>(v->NumberValue()));
18361 }
18362 {
18363 v8::Isolate::Scope isolate_scope(isolate);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018364 v8::HandleScope handle_scope(isolate);
ulan@chromium.org57ff8812013-05-10 08:16:55 +000018365 context = v8::Context::New(isolate);
lrn@chromium.org1c092762011-05-09 09:42:16 +000018366 v8::Context::Scope context_scope(context);
18367 Local<Value> v = CompileRun("22");
18368 CHECK(v->IsNumber());
18369 CHECK_EQ(22, static_cast<int>(v->NumberValue()));
18370 }
18371}
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000018372
18373class InitDefaultIsolateThread : public v8::internal::Thread {
18374 public:
sgjesse@chromium.orge0599052011-03-25 07:34:35 +000018375 enum TestCase {
18376 IgnoreOOM,
18377 SetResourceConstraints,
18378 SetFatalHandler,
18379 SetCounterFunction,
18380 SetCreateHistogramFunction,
18381 SetAddHistogramSampleFunction
18382 };
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000018383
18384 explicit InitDefaultIsolateThread(TestCase testCase)
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000018385 : Thread("InitDefaultIsolateThread"),
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000018386 testCase_(testCase),
18387 result_(false) { }
18388
18389 void Run() {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018390 v8::Isolate* isolate = v8::Isolate::New();
18391 isolate->Enter();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000018392 switch (testCase_) {
18393 case IgnoreOOM:
18394 v8::V8::IgnoreOutOfMemoryException();
18395 break;
18396
18397 case SetResourceConstraints: {
18398 static const int K = 1024;
18399 v8::ResourceConstraints constraints;
18400 constraints.set_max_young_space_size(256 * K);
18401 constraints.set_max_old_space_size(4 * K * K);
18402 v8::SetResourceConstraints(&constraints);
18403 break;
18404 }
18405
18406 case SetFatalHandler:
18407 v8::V8::SetFatalErrorHandler(NULL);
18408 break;
sgjesse@chromium.orge0599052011-03-25 07:34:35 +000018409
18410 case SetCounterFunction:
18411 v8::V8::SetCounterFunction(NULL);
18412 break;
18413
18414 case SetCreateHistogramFunction:
18415 v8::V8::SetCreateHistogramFunction(NULL);
18416 break;
18417
18418 case SetAddHistogramSampleFunction:
18419 v8::V8::SetAddHistogramSampleFunction(NULL);
18420 break;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000018421 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018422 isolate->Exit();
18423 isolate->Dispose();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000018424 result_ = true;
18425 }
18426
18427 bool result() { return result_; }
18428
18429 private:
18430 TestCase testCase_;
18431 bool result_;
18432};
18433
18434
18435static void InitializeTestHelper(InitDefaultIsolateThread::TestCase testCase) {
18436 InitDefaultIsolateThread thread(testCase);
18437 thread.Start();
18438 thread.Join();
18439 CHECK_EQ(thread.result(), true);
18440}
18441
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000018442
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000018443TEST(InitializeDefaultIsolateOnSecondaryThread1) {
18444 InitializeTestHelper(InitDefaultIsolateThread::IgnoreOOM);
18445}
18446
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000018447
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000018448TEST(InitializeDefaultIsolateOnSecondaryThread2) {
18449 InitializeTestHelper(InitDefaultIsolateThread::SetResourceConstraints);
18450}
18451
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000018452
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000018453TEST(InitializeDefaultIsolateOnSecondaryThread3) {
18454 InitializeTestHelper(InitDefaultIsolateThread::SetFatalHandler);
18455}
18456
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000018457
sgjesse@chromium.orge0599052011-03-25 07:34:35 +000018458TEST(InitializeDefaultIsolateOnSecondaryThread4) {
18459 InitializeTestHelper(InitDefaultIsolateThread::SetCounterFunction);
18460}
18461
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000018462
sgjesse@chromium.orge0599052011-03-25 07:34:35 +000018463TEST(InitializeDefaultIsolateOnSecondaryThread5) {
18464 InitializeTestHelper(InitDefaultIsolateThread::SetCreateHistogramFunction);
18465}
18466
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000018467
sgjesse@chromium.orge0599052011-03-25 07:34:35 +000018468TEST(InitializeDefaultIsolateOnSecondaryThread6) {
18469 InitializeTestHelper(InitDefaultIsolateThread::SetAddHistogramSampleFunction);
18470}
18471
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000018472
18473TEST(StringCheckMultipleContexts) {
18474 const char* code =
18475 "(function() { return \"a\".charAt(0); })()";
18476
18477 {
18478 // Run the code twice in the first context to initialize the call IC.
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000018479 LocalContext context1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018480 v8::HandleScope scope(context1->GetIsolate());
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000018481 ExpectString(code, "a");
18482 ExpectString(code, "a");
18483 }
18484
18485 {
18486 // Change the String.prototype in the second context and check
18487 // that the right function gets called.
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000018488 LocalContext context2;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018489 v8::HandleScope scope(context2->GetIsolate());
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000018490 CompileRun("String.prototype.charAt = function() { return \"not a\"; }");
18491 ExpectString(code, "not a");
18492 }
18493}
18494
18495
18496TEST(NumberCheckMultipleContexts) {
18497 const char* code =
18498 "(function() { return (42).toString(); })()";
18499
18500 {
18501 // Run the code twice in the first context to initialize the call IC.
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000018502 LocalContext context1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018503 v8::HandleScope scope(context1->GetIsolate());
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000018504 ExpectString(code, "42");
18505 ExpectString(code, "42");
18506 }
18507
18508 {
18509 // Change the Number.prototype in the second context and check
18510 // that the right function gets called.
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000018511 LocalContext context2;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018512 v8::HandleScope scope(context2->GetIsolate());
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000018513 CompileRun("Number.prototype.toString = function() { return \"not 42\"; }");
18514 ExpectString(code, "not 42");
18515 }
18516}
18517
18518
18519TEST(BooleanCheckMultipleContexts) {
18520 const char* code =
18521 "(function() { return true.toString(); })()";
18522
18523 {
18524 // Run the code twice in the first context to initialize the call IC.
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000018525 LocalContext context1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018526 v8::HandleScope scope(context1->GetIsolate());
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000018527 ExpectString(code, "true");
18528 ExpectString(code, "true");
18529 }
18530
18531 {
18532 // Change the Boolean.prototype in the second context and check
18533 // that the right function gets called.
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000018534 LocalContext context2;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018535 v8::HandleScope scope(context2->GetIsolate());
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000018536 CompileRun("Boolean.prototype.toString = function() { return \"\"; }");
18537 ExpectString(code, "");
18538 }
18539}
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000018540
18541
18542TEST(DontDeleteCellLoadIC) {
18543 const char* function_code =
18544 "function readCell() { while (true) { return cell; } }";
18545
18546 {
18547 // Run the code twice in the first context to initialize the load
18548 // IC for a don't delete cell.
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000018549 LocalContext context1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018550 v8::HandleScope scope(context1->GetIsolate());
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000018551 CompileRun("var cell = \"first\";");
18552 ExpectBoolean("delete cell", false);
18553 CompileRun(function_code);
18554 ExpectString("readCell()", "first");
18555 ExpectString("readCell()", "first");
18556 }
18557
18558 {
18559 // Use a deletable cell in the second context.
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000018560 LocalContext context2;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018561 v8::HandleScope scope(context2->GetIsolate());
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000018562 CompileRun("cell = \"second\";");
18563 CompileRun(function_code);
18564 ExpectString("readCell()", "second");
18565 ExpectBoolean("delete cell", true);
18566 ExpectString("(function() {"
18567 " try {"
18568 " return readCell();"
18569 " } catch(e) {"
18570 " return e.toString();"
18571 " }"
18572 "})()",
18573 "ReferenceError: cell is not defined");
18574 CompileRun("cell = \"new_second\";");
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018575 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000018576 ExpectString("readCell()", "new_second");
18577 ExpectString("readCell()", "new_second");
18578 }
18579}
18580
18581
18582TEST(DontDeleteCellLoadICForceDelete) {
18583 const char* function_code =
18584 "function readCell() { while (true) { return cell; } }";
18585
18586 // Run the code twice to initialize the load IC for a don't delete
18587 // cell.
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000018588 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018589 v8::HandleScope scope(context->GetIsolate());
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000018590 CompileRun("var cell = \"value\";");
18591 ExpectBoolean("delete cell", false);
18592 CompileRun(function_code);
18593 ExpectString("readCell()", "value");
18594 ExpectString("readCell()", "value");
18595
18596 // Delete the cell using the API and check the inlined code works
18597 // correctly.
18598 CHECK(context->Global()->ForceDelete(v8_str("cell")));
18599 ExpectString("(function() {"
18600 " try {"
18601 " return readCell();"
18602 " } catch(e) {"
18603 " return e.toString();"
18604 " }"
18605 "})()",
18606 "ReferenceError: cell is not defined");
18607}
18608
18609
18610TEST(DontDeleteCellLoadICAPI) {
18611 const char* function_code =
18612 "function readCell() { while (true) { return cell; } }";
18613
18614 // Run the code twice to initialize the load IC for a don't delete
18615 // cell created using the API.
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000018616 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018617 v8::HandleScope scope(context->GetIsolate());
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000018618 context->Global()->Set(v8_str("cell"), v8_str("value"), v8::DontDelete);
18619 ExpectBoolean("delete cell", false);
18620 CompileRun(function_code);
18621 ExpectString("readCell()", "value");
18622 ExpectString("readCell()", "value");
18623
18624 // Delete the cell using the API and check the inlined code works
18625 // correctly.
18626 CHECK(context->Global()->ForceDelete(v8_str("cell")));
18627 ExpectString("(function() {"
18628 " try {"
18629 " return readCell();"
18630 " } catch(e) {"
18631 " return e.toString();"
18632 " }"
18633 "})()",
18634 "ReferenceError: cell is not defined");
18635}
18636
18637
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000018638class Visitor42 : public v8::PersistentHandleVisitor {
18639 public:
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000018640 explicit Visitor42(v8::Persistent<v8::Object>* object)
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000018641 : counter_(0), object_(object) { }
18642
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000018643 virtual void VisitPersistentHandle(Persistent<Value>* value,
18644 uint16_t class_id) {
18645 if (class_id != 42) return;
18646 CHECK_EQ(42, value->WrapperClassId());
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018647 v8::Isolate* isolate = CcTest::isolate();
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000018648 v8::HandleScope handle_scope(isolate);
18649 v8::Handle<v8::Value> handle = v8::Local<v8::Value>::New(isolate, *value);
18650 v8::Handle<v8::Value> object =
18651 v8::Local<v8::Object>::New(isolate, *object_);
18652 CHECK(handle->IsObject());
18653 CHECK_EQ(Handle<Object>::Cast(handle), object);
18654 ++counter_;
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000018655 }
18656
18657 int counter_;
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000018658 v8::Persistent<v8::Object>* object_;
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000018659};
18660
18661
18662TEST(PersistentHandleVisitor) {
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000018663 LocalContext context;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000018664 v8::Isolate* isolate = context->GetIsolate();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018665 v8::HandleScope scope(isolate);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000018666 v8::Persistent<v8::Object> object(isolate, v8::Object::New());
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000018667 CHECK_EQ(0, object.WrapperClassId());
18668 object.SetWrapperClassId(42);
18669 CHECK_EQ(42, object.WrapperClassId());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000018670
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000018671 Visitor42 visitor(&object);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000018672 v8::V8::VisitHandlesWithClassIds(&visitor);
18673 CHECK_EQ(1, visitor.counter_);
18674
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000018675 object.Dispose();
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000018676}
18677
18678
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000018679TEST(WrapperClassId) {
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000018680 LocalContext context;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000018681 v8::Isolate* isolate = context->GetIsolate();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018682 v8::HandleScope scope(isolate);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000018683 v8::Persistent<v8::Object> object(isolate, v8::Object::New());
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000018684 CHECK_EQ(0, object.WrapperClassId());
18685 object.SetWrapperClassId(65535);
18686 CHECK_EQ(65535, object.WrapperClassId());
18687 object.Dispose();
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000018688}
18689
18690
yangguo@chromium.org003650e2013-01-24 16:31:08 +000018691TEST(PersistentHandleInNewSpaceVisitor) {
yangguo@chromium.org003650e2013-01-24 16:31:08 +000018692 LocalContext context;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000018693 v8::Isolate* isolate = context->GetIsolate();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018694 v8::HandleScope scope(isolate);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000018695 v8::Persistent<v8::Object> object1(isolate, v8::Object::New());
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000018696 CHECK_EQ(0, object1.WrapperClassId());
18697 object1.SetWrapperClassId(42);
18698 CHECK_EQ(42, object1.WrapperClassId());
yangguo@chromium.org003650e2013-01-24 16:31:08 +000018699
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018700 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
yangguo@chromium.org003650e2013-01-24 16:31:08 +000018701
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000018702 v8::Persistent<v8::Object> object2(isolate, v8::Object::New());
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000018703 CHECK_EQ(0, object2.WrapperClassId());
18704 object2.SetWrapperClassId(42);
18705 CHECK_EQ(42, object2.WrapperClassId());
yangguo@chromium.org003650e2013-01-24 16:31:08 +000018706
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000018707 Visitor42 visitor(&object2);
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000018708 v8::V8::VisitHandlesForPartialDependence(isolate, &visitor);
yangguo@chromium.org003650e2013-01-24 16:31:08 +000018709 CHECK_EQ(1, visitor.counter_);
18710
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000018711 object1.Dispose();
18712 object2.Dispose();
yangguo@chromium.org003650e2013-01-24 16:31:08 +000018713}
18714
18715
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000018716TEST(RegExp) {
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000018717 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018718 v8::HandleScope scope(context->GetIsolate());
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000018719
18720 v8::Handle<v8::RegExp> re = v8::RegExp::New(v8_str("foo"), v8::RegExp::kNone);
18721 CHECK(re->IsRegExp());
18722 CHECK(re->GetSource()->Equals(v8_str("foo")));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000018723 CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000018724
18725 re = v8::RegExp::New(v8_str("bar"),
18726 static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
18727 v8::RegExp::kGlobal));
18728 CHECK(re->IsRegExp());
18729 CHECK(re->GetSource()->Equals(v8_str("bar")));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000018730 CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kGlobal,
18731 static_cast<int>(re->GetFlags()));
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000018732
18733 re = v8::RegExp::New(v8_str("baz"),
18734 static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
18735 v8::RegExp::kMultiline));
18736 CHECK(re->IsRegExp());
18737 CHECK(re->GetSource()->Equals(v8_str("baz")));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000018738 CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
18739 static_cast<int>(re->GetFlags()));
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000018740
18741 re = CompileRun("/quux/").As<v8::RegExp>();
18742 CHECK(re->IsRegExp());
18743 CHECK(re->GetSource()->Equals(v8_str("quux")));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000018744 CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000018745
18746 re = CompileRun("/quux/gm").As<v8::RegExp>();
18747 CHECK(re->IsRegExp());
18748 CHECK(re->GetSource()->Equals(v8_str("quux")));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000018749 CHECK_EQ(v8::RegExp::kGlobal | v8::RegExp::kMultiline,
18750 static_cast<int>(re->GetFlags()));
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000018751
18752 // Override the RegExp constructor and check the API constructor
18753 // still works.
18754 CompileRun("RegExp = function() {}");
18755
18756 re = v8::RegExp::New(v8_str("foobar"), v8::RegExp::kNone);
18757 CHECK(re->IsRegExp());
18758 CHECK(re->GetSource()->Equals(v8_str("foobar")));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000018759 CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000018760
18761 re = v8::RegExp::New(v8_str("foobarbaz"),
18762 static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
18763 v8::RegExp::kMultiline));
18764 CHECK(re->IsRegExp());
18765 CHECK(re->GetSource()->Equals(v8_str("foobarbaz")));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000018766 CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
18767 static_cast<int>(re->GetFlags()));
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000018768
18769 context->Global()->Set(v8_str("re"), re);
18770 ExpectTrue("re.test('FoobarbaZ')");
18771
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000018772 // RegExps are objects on which you can set properties.
18773 re->Set(v8_str("property"), v8::Integer::New(32));
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000018774 v8::Handle<v8::Value> value(CompileRun("re.property"));
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000018775 CHECK_EQ(32, value->Int32Value());
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000018776
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000018777 v8::TryCatch try_catch;
18778 re = v8::RegExp::New(v8_str("foo["), v8::RegExp::kNone);
18779 CHECK(re.IsEmpty());
18780 CHECK(try_catch.HasCaught());
18781 context->Global()->Set(v8_str("ex"), try_catch.Exception());
18782 ExpectTrue("ex instanceof SyntaxError");
18783}
18784
18785
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000018786THREADED_TEST(Equals) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000018787 LocalContext localContext;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018788 v8::HandleScope handleScope(localContext->GetIsolate());
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000018789
18790 v8::Handle<v8::Object> globalProxy = localContext->Global();
18791 v8::Handle<Value> global = globalProxy->GetPrototype();
18792
18793 CHECK(global->StrictEquals(global));
18794 CHECK(!global->StrictEquals(globalProxy));
18795 CHECK(!globalProxy->StrictEquals(global));
18796 CHECK(globalProxy->StrictEquals(globalProxy));
18797
18798 CHECK(global->Equals(global));
18799 CHECK(!global->Equals(globalProxy));
18800 CHECK(!globalProxy->Equals(global));
18801 CHECK(globalProxy->Equals(globalProxy));
18802}
18803
18804
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018805static void Getter(v8::Local<v8::String> property,
18806 const v8::PropertyCallbackInfo<v8::Value>& info ) {
18807 info.GetReturnValue().Set(v8_str("42!"));
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000018808}
18809
18810
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018811static void Enumerator(const v8::PropertyCallbackInfo<v8::Array>& info) {
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000018812 v8::Handle<v8::Array> result = v8::Array::New();
18813 result->Set(0, v8_str("universalAnswer"));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018814 info.GetReturnValue().Set(result);
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000018815}
18816
18817
18818TEST(NamedEnumeratorAndForIn) {
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000018819 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018820 v8::HandleScope handle_scope(context->GetIsolate());
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000018821 v8::Context::Scope context_scope(context.local());
18822
18823 v8::Handle<v8::ObjectTemplate> tmpl = v8::ObjectTemplate::New();
18824 tmpl->SetNamedPropertyHandler(Getter, NULL, NULL, NULL, Enumerator);
18825 context->Global()->Set(v8_str("o"), tmpl->NewInstance());
18826 v8::Handle<v8::Array> result = v8::Handle<v8::Array>::Cast(CompileRun(
18827 "var result = []; for (var k in o) result.push(k); result"));
18828 CHECK_EQ(1, result->Length());
18829 CHECK_EQ(v8_str("universalAnswer"), result->Get(0));
18830}
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +000018831
18832
18833TEST(DefinePropertyPostDetach) {
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +000018834 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018835 v8::HandleScope scope(context->GetIsolate());
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +000018836 v8::Handle<v8::Object> proxy = context->Global();
18837 v8::Handle<v8::Function> define_property =
18838 CompileRun("(function() {"
18839 " Object.defineProperty("
18840 " this,"
18841 " 1,"
18842 " { configurable: true, enumerable: true, value: 3 });"
18843 "})").As<Function>();
18844 context->DetachGlobal();
18845 define_property->Call(proxy, 0, NULL);
18846}
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000018847
18848
18849static void InstallContextId(v8::Handle<Context> context, int id) {
18850 Context::Scope scope(context);
18851 CompileRun("Object.prototype").As<Object>()->
18852 Set(v8_str("context_id"), v8::Integer::New(id));
18853}
18854
18855
18856static void CheckContextId(v8::Handle<Object> object, int expected) {
18857 CHECK_EQ(expected, object->Get(v8_str("context_id"))->Int32Value());
18858}
18859
18860
18861THREADED_TEST(CreationContext) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018862 HandleScope handle_scope(CcTest::isolate());
18863 Handle<Context> context1 = Context::New(CcTest::isolate());
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000018864 InstallContextId(context1, 1);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018865 Handle<Context> context2 = Context::New(CcTest::isolate());
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000018866 InstallContextId(context2, 2);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018867 Handle<Context> context3 = Context::New(CcTest::isolate());
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000018868 InstallContextId(context3, 3);
18869
18870 Local<v8::FunctionTemplate> tmpl = v8::FunctionTemplate::New();
18871
18872 Local<Object> object1;
18873 Local<Function> func1;
18874 {
18875 Context::Scope scope(context1);
18876 object1 = Object::New();
18877 func1 = tmpl->GetFunction();
18878 }
18879
18880 Local<Object> object2;
18881 Local<Function> func2;
18882 {
18883 Context::Scope scope(context2);
18884 object2 = Object::New();
18885 func2 = tmpl->GetFunction();
18886 }
18887
18888 Local<Object> instance1;
18889 Local<Object> instance2;
18890
18891 {
18892 Context::Scope scope(context3);
18893 instance1 = func1->NewInstance();
18894 instance2 = func2->NewInstance();
18895 }
18896
18897 CHECK(object1->CreationContext() == context1);
18898 CheckContextId(object1, 1);
18899 CHECK(func1->CreationContext() == context1);
18900 CheckContextId(func1, 1);
18901 CHECK(instance1->CreationContext() == context1);
18902 CheckContextId(instance1, 1);
18903 CHECK(object2->CreationContext() == context2);
18904 CheckContextId(object2, 2);
18905 CHECK(func2->CreationContext() == context2);
18906 CheckContextId(func2, 2);
18907 CHECK(instance2->CreationContext() == context2);
18908 CheckContextId(instance2, 2);
18909
18910 {
18911 Context::Scope scope(context1);
18912 CHECK(object1->CreationContext() == context1);
18913 CheckContextId(object1, 1);
18914 CHECK(func1->CreationContext() == context1);
18915 CheckContextId(func1, 1);
18916 CHECK(instance1->CreationContext() == context1);
18917 CheckContextId(instance1, 1);
18918 CHECK(object2->CreationContext() == context2);
18919 CheckContextId(object2, 2);
18920 CHECK(func2->CreationContext() == context2);
18921 CheckContextId(func2, 2);
18922 CHECK(instance2->CreationContext() == context2);
18923 CheckContextId(instance2, 2);
18924 }
18925
18926 {
18927 Context::Scope scope(context2);
18928 CHECK(object1->CreationContext() == context1);
18929 CheckContextId(object1, 1);
18930 CHECK(func1->CreationContext() == context1);
18931 CheckContextId(func1, 1);
18932 CHECK(instance1->CreationContext() == context1);
18933 CheckContextId(instance1, 1);
18934 CHECK(object2->CreationContext() == context2);
18935 CheckContextId(object2, 2);
18936 CHECK(func2->CreationContext() == context2);
18937 CheckContextId(func2, 2);
18938 CHECK(instance2->CreationContext() == context2);
18939 CheckContextId(instance2, 2);
18940 }
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000018941}
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000018942
18943
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +000018944THREADED_TEST(CreationContextOfJsFunction) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018945 HandleScope handle_scope(CcTest::isolate());
18946 Handle<Context> context = Context::New(CcTest::isolate());
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +000018947 InstallContextId(context, 1);
18948
18949 Local<Object> function;
18950 {
18951 Context::Scope scope(context);
18952 function = CompileRun("function foo() {}; foo").As<Object>();
18953 }
18954
18955 CHECK(function->CreationContext() == context);
18956 CheckContextId(function, 1);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +000018957}
18958
18959
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018960void HasOwnPropertyIndexedPropertyGetter(
18961 uint32_t index,
18962 const v8::PropertyCallbackInfo<v8::Value>& info) {
18963 if (index == 42) info.GetReturnValue().Set(v8_str("yes"));
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000018964}
18965
18966
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018967void HasOwnPropertyNamedPropertyGetter(
18968 Local<String> property,
18969 const v8::PropertyCallbackInfo<v8::Value>& info) {
18970 if (property->Equals(v8_str("foo"))) info.GetReturnValue().Set(v8_str("yes"));
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000018971}
18972
18973
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018974void HasOwnPropertyIndexedPropertyQuery(
18975 uint32_t index, const v8::PropertyCallbackInfo<v8::Integer>& info) {
18976 if (index == 42) info.GetReturnValue().Set(1);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000018977}
18978
18979
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018980void HasOwnPropertyNamedPropertyQuery(
18981 Local<String> property,
18982 const v8::PropertyCallbackInfo<v8::Integer>& info) {
18983 if (property->Equals(v8_str("foo"))) info.GetReturnValue().Set(1);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000018984}
18985
18986
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018987void HasOwnPropertyNamedPropertyQuery2(
18988 Local<String> property,
18989 const v8::PropertyCallbackInfo<v8::Integer>& info) {
18990 if (property->Equals(v8_str("bar"))) info.GetReturnValue().Set(1);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000018991}
18992
18993
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018994void HasOwnPropertyAccessorGetter(
18995 Local<String> property,
18996 const v8::PropertyCallbackInfo<v8::Value>& info) {
18997 info.GetReturnValue().Set(v8_str("yes"));
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000018998}
18999
19000
19001TEST(HasOwnProperty) {
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019002 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019003 v8::HandleScope scope(env->GetIsolate());
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019004 { // Check normal properties and defined getters.
19005 Handle<Value> value = CompileRun(
19006 "function Foo() {"
19007 " this.foo = 11;"
19008 " this.__defineGetter__('baz', function() { return 1; });"
19009 "};"
19010 "function Bar() { "
19011 " this.bar = 13;"
19012 " this.__defineGetter__('bla', function() { return 2; });"
19013 "};"
19014 "Bar.prototype = new Foo();"
19015 "new Bar();");
19016 CHECK(value->IsObject());
19017 Handle<Object> object = value->ToObject();
19018 CHECK(object->Has(v8_str("foo")));
19019 CHECK(!object->HasOwnProperty(v8_str("foo")));
19020 CHECK(object->HasOwnProperty(v8_str("bar")));
19021 CHECK(object->Has(v8_str("baz")));
19022 CHECK(!object->HasOwnProperty(v8_str("baz")));
19023 CHECK(object->HasOwnProperty(v8_str("bla")));
19024 }
19025 { // Check named getter interceptors.
19026 Handle<ObjectTemplate> templ = ObjectTemplate::New();
19027 templ->SetNamedPropertyHandler(HasOwnPropertyNamedPropertyGetter);
19028 Handle<Object> instance = templ->NewInstance();
19029 CHECK(!instance->HasOwnProperty(v8_str("42")));
19030 CHECK(instance->HasOwnProperty(v8_str("foo")));
19031 CHECK(!instance->HasOwnProperty(v8_str("bar")));
19032 }
19033 { // Check indexed getter interceptors.
19034 Handle<ObjectTemplate> templ = ObjectTemplate::New();
19035 templ->SetIndexedPropertyHandler(HasOwnPropertyIndexedPropertyGetter);
19036 Handle<Object> instance = templ->NewInstance();
19037 CHECK(instance->HasOwnProperty(v8_str("42")));
19038 CHECK(!instance->HasOwnProperty(v8_str("43")));
19039 CHECK(!instance->HasOwnProperty(v8_str("foo")));
19040 }
19041 { // Check named query interceptors.
19042 Handle<ObjectTemplate> templ = ObjectTemplate::New();
19043 templ->SetNamedPropertyHandler(0, 0, HasOwnPropertyNamedPropertyQuery);
19044 Handle<Object> instance = templ->NewInstance();
19045 CHECK(instance->HasOwnProperty(v8_str("foo")));
19046 CHECK(!instance->HasOwnProperty(v8_str("bar")));
19047 }
19048 { // Check indexed query interceptors.
19049 Handle<ObjectTemplate> templ = ObjectTemplate::New();
19050 templ->SetIndexedPropertyHandler(0, 0, HasOwnPropertyIndexedPropertyQuery);
19051 Handle<Object> instance = templ->NewInstance();
19052 CHECK(instance->HasOwnProperty(v8_str("42")));
19053 CHECK(!instance->HasOwnProperty(v8_str("41")));
19054 }
19055 { // Check callbacks.
19056 Handle<ObjectTemplate> templ = ObjectTemplate::New();
19057 templ->SetAccessor(v8_str("foo"), HasOwnPropertyAccessorGetter);
19058 Handle<Object> instance = templ->NewInstance();
19059 CHECK(instance->HasOwnProperty(v8_str("foo")));
19060 CHECK(!instance->HasOwnProperty(v8_str("bar")));
19061 }
19062 { // Check that query wins on disagreement.
19063 Handle<ObjectTemplate> templ = ObjectTemplate::New();
19064 templ->SetNamedPropertyHandler(HasOwnPropertyNamedPropertyGetter,
19065 0,
19066 HasOwnPropertyNamedPropertyQuery2);
19067 Handle<Object> instance = templ->NewInstance();
19068 CHECK(!instance->HasOwnProperty(v8_str("foo")));
19069 CHECK(instance->HasOwnProperty(v8_str("bar")));
19070 }
19071}
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000019072
19073
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +000019074TEST(IndexedInterceptorWithStringProto) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019075 v8::HandleScope scope(CcTest::isolate());
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +000019076 Handle<ObjectTemplate> templ = ObjectTemplate::New();
19077 templ->SetIndexedPropertyHandler(NULL,
19078 NULL,
19079 HasOwnPropertyIndexedPropertyQuery);
19080 LocalContext context;
19081 context->Global()->Set(v8_str("obj"), templ->NewInstance());
19082 CompileRun("var s = new String('foobar'); obj.__proto__ = s;");
19083 // These should be intercepted.
19084 CHECK(CompileRun("42 in obj")->BooleanValue());
19085 CHECK(CompileRun("'42' in obj")->BooleanValue());
19086 // These should fall through to the String prototype.
19087 CHECK(CompileRun("0 in obj")->BooleanValue());
19088 CHECK(CompileRun("'0' in obj")->BooleanValue());
19089 // And these should both fail.
19090 CHECK(!CompileRun("32 in obj")->BooleanValue());
19091 CHECK(!CompileRun("'32' in obj")->BooleanValue());
19092}
19093
19094
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000019095void CheckCodeGenerationAllowed() {
19096 Handle<Value> result = CompileRun("eval('42')");
19097 CHECK_EQ(42, result->Int32Value());
19098 result = CompileRun("(function(e) { return e('42'); })(eval)");
19099 CHECK_EQ(42, result->Int32Value());
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000019100 result = CompileRun("var f = new Function('return 42'); f()");
19101 CHECK_EQ(42, result->Int32Value());
19102}
19103
19104
19105void CheckCodeGenerationDisallowed() {
19106 TryCatch try_catch;
19107
19108 Handle<Value> result = CompileRun("eval('42')");
19109 CHECK(result.IsEmpty());
19110 CHECK(try_catch.HasCaught());
19111 try_catch.Reset();
19112
19113 result = CompileRun("(function(e) { return e('42'); })(eval)");
19114 CHECK(result.IsEmpty());
19115 CHECK(try_catch.HasCaught());
19116 try_catch.Reset();
19117
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000019118 result = CompileRun("var f = new Function('return 42'); f()");
19119 CHECK(result.IsEmpty());
19120 CHECK(try_catch.HasCaught());
19121}
19122
19123
19124bool CodeGenerationAllowed(Local<Context> context) {
19125 ApiTestFuzzer::Fuzz();
19126 return true;
19127}
19128
19129
19130bool CodeGenerationDisallowed(Local<Context> context) {
19131 ApiTestFuzzer::Fuzz();
19132 return false;
19133}
19134
19135
19136THREADED_TEST(AllowCodeGenFromStrings) {
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000019137 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019138 v8::HandleScope scope(context->GetIsolate());
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000019139
ager@chromium.orgea91cc52011-05-23 06:06:11 +000019140 // eval and the Function constructor allowed by default.
jkummerow@chromium.org1145ef82012-02-02 16:21:15 +000019141 CHECK(context->IsCodeGenerationFromStringsAllowed());
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000019142 CheckCodeGenerationAllowed();
19143
ager@chromium.orgea91cc52011-05-23 06:06:11 +000019144 // Disallow eval and the Function constructor.
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000019145 context->AllowCodeGenerationFromStrings(false);
jkummerow@chromium.org1145ef82012-02-02 16:21:15 +000019146 CHECK(!context->IsCodeGenerationFromStringsAllowed());
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000019147 CheckCodeGenerationDisallowed();
19148
19149 // Allow again.
19150 context->AllowCodeGenerationFromStrings(true);
19151 CheckCodeGenerationAllowed();
19152
19153 // Disallow but setting a global callback that will allow the calls.
19154 context->AllowCodeGenerationFromStrings(false);
19155 V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationAllowed);
jkummerow@chromium.org1145ef82012-02-02 16:21:15 +000019156 CHECK(!context->IsCodeGenerationFromStringsAllowed());
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000019157 CheckCodeGenerationAllowed();
19158
19159 // Set a callback that disallows the code generation.
19160 V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationDisallowed);
jkummerow@chromium.org1145ef82012-02-02 16:21:15 +000019161 CHECK(!context->IsCodeGenerationFromStringsAllowed());
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000019162 CheckCodeGenerationDisallowed();
19163}
lrn@chromium.org1c092762011-05-09 09:42:16 +000019164
19165
ulan@chromium.org56c14af2012-09-20 12:51:09 +000019166TEST(SetErrorMessageForCodeGenFromStrings) {
ulan@chromium.org56c14af2012-09-20 12:51:09 +000019167 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019168 v8::HandleScope scope(context->GetIsolate());
ulan@chromium.org56c14af2012-09-20 12:51:09 +000019169 TryCatch try_catch;
19170
19171 Handle<String> message = v8_str("Message") ;
19172 Handle<String> expected_message = v8_str("Uncaught EvalError: Message");
19173 V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationDisallowed);
19174 context->AllowCodeGenerationFromStrings(false);
19175 context->SetErrorMessageForCodeGenerationFromStrings(message);
19176 Handle<Value> result = CompileRun("eval('42')");
19177 CHECK(result.IsEmpty());
19178 CHECK(try_catch.HasCaught());
19179 Handle<String> actual_message = try_catch.Message()->Get();
19180 CHECK(expected_message->Equals(actual_message));
19181}
19182
19183
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000019184static void NonObjectThis(const v8::FunctionCallbackInfo<v8::Value>& args) {
lrn@chromium.org1c092762011-05-09 09:42:16 +000019185}
19186
19187
19188THREADED_TEST(CallAPIFunctionOnNonObject) {
lrn@chromium.org1c092762011-05-09 09:42:16 +000019189 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019190 v8::HandleScope scope(context->GetIsolate());
lrn@chromium.org1c092762011-05-09 09:42:16 +000019191 Handle<FunctionTemplate> templ = v8::FunctionTemplate::New(NonObjectThis);
19192 Handle<Function> function = templ->GetFunction();
19193 context->Global()->Set(v8_str("f"), function);
19194 TryCatch try_catch;
19195 CompileRun("f.call(2)");
lrn@chromium.org1c092762011-05-09 09:42:16 +000019196}
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000019197
19198
19199// Regression test for issue 1470.
19200THREADED_TEST(ReadOnlyIndexedProperties) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019201 v8::HandleScope scope(CcTest::isolate());
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000019202 Local<ObjectTemplate> templ = ObjectTemplate::New();
19203
19204 LocalContext context;
19205 Local<v8::Object> obj = templ->NewInstance();
19206 context->Global()->Set(v8_str("obj"), obj);
19207 obj->Set(v8_str("1"), v8_str("DONT_CHANGE"), v8::ReadOnly);
19208 obj->Set(v8_str("1"), v8_str("foobar"));
19209 CHECK_EQ(v8_str("DONT_CHANGE"), obj->Get(v8_str("1")));
19210 obj->Set(v8_num(2), v8_str("DONT_CHANGE"), v8::ReadOnly);
19211 obj->Set(v8_num(2), v8_str("foobar"));
19212 CHECK_EQ(v8_str("DONT_CHANGE"), obj->Get(v8_num(2)));
19213
19214 // Test non-smi case.
19215 obj->Set(v8_str("2000000000"), v8_str("DONT_CHANGE"), v8::ReadOnly);
19216 obj->Set(v8_str("2000000000"), v8_str("foobar"));
19217 CHECK_EQ(v8_str("DONT_CHANGE"), obj->Get(v8_str("2000000000")));
19218}
ricow@chromium.org4f693d62011-07-04 14:01:31 +000019219
19220
19221THREADED_TEST(Regress1516) {
ricow@chromium.org4f693d62011-07-04 14:01:31 +000019222 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019223 v8::HandleScope scope(context->GetIsolate());
19224
19225 { v8::HandleScope temp_scope(context->GetIsolate());
ricow@chromium.org4f693d62011-07-04 14:01:31 +000019226 CompileRun("({'a': 0})");
19227 }
19228
19229 int elements;
19230 { i::MapCache* map_cache =
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019231 i::MapCache::cast(CcTest::i_isolate()->context()->map_cache());
ricow@chromium.org4f693d62011-07-04 14:01:31 +000019232 elements = map_cache->NumberOfElements();
19233 CHECK_LE(1, elements);
19234 }
19235
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019236 CcTest::heap()->CollectAllGarbage(
yangguo@chromium.orgd2899aa2012-06-21 11:16:20 +000019237 i::Heap::kAbortIncrementalMarkingMask);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019238 { i::Object* raw_map_cache = CcTest::i_isolate()->context()->map_cache();
19239 if (raw_map_cache != CcTest::heap()->undefined_value()) {
ricow@chromium.org4f693d62011-07-04 14:01:31 +000019240 i::MapCache* map_cache = i::MapCache::cast(raw_map_cache);
19241 CHECK_GT(elements, map_cache->NumberOfElements());
19242 }
19243 }
19244}
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000019245
19246
19247static bool BlockProtoNamedSecurityTestCallback(Local<v8::Object> global,
19248 Local<Value> name,
19249 v8::AccessType type,
19250 Local<Value> data) {
19251 // Only block read access to __proto__.
19252 if (type == v8::ACCESS_GET &&
19253 name->IsString() &&
19254 name->ToString()->Length() == 9 &&
19255 name->ToString()->Utf8Length() == 9) {
19256 char buffer[10];
19257 CHECK_EQ(10, name->ToString()->WriteUtf8(buffer));
19258 return strncmp(buffer, "__proto__", 9) != 0;
19259 }
19260
19261 return true;
19262}
19263
19264
19265THREADED_TEST(Regress93759) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019266 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000019267 HandleScope scope(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000019268
19269 // Template for object with security check.
19270 Local<ObjectTemplate> no_proto_template = v8::ObjectTemplate::New();
19271 // We don't do indexing, so any callback can be used for that.
19272 no_proto_template->SetAccessCheckCallbacks(
19273 BlockProtoNamedSecurityTestCallback,
19274 IndexedSecurityTestCallback);
19275
19276 // Templates for objects with hidden prototypes and possibly security check.
19277 Local<FunctionTemplate> hidden_proto_template = v8::FunctionTemplate::New();
19278 hidden_proto_template->SetHiddenPrototype(true);
19279
19280 Local<FunctionTemplate> protected_hidden_proto_template =
19281 v8::FunctionTemplate::New();
19282 protected_hidden_proto_template->InstanceTemplate()->SetAccessCheckCallbacks(
19283 BlockProtoNamedSecurityTestCallback,
19284 IndexedSecurityTestCallback);
19285 protected_hidden_proto_template->SetHiddenPrototype(true);
19286
19287 // Context for "foreign" objects used in test.
ulan@chromium.org57ff8812013-05-10 08:16:55 +000019288 Local<Context> context = v8::Context::New(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000019289 context->Enter();
19290
19291 // Plain object, no security check.
19292 Local<Object> simple_object = Object::New();
19293
19294 // Object with explicit security check.
19295 Local<Object> protected_object =
19296 no_proto_template->NewInstance();
19297
19298 // JSGlobalProxy object, always have security check.
19299 Local<Object> proxy_object =
19300 context->Global();
19301
19302 // Global object, the prototype of proxy_object. No security checks.
19303 Local<Object> global_object =
19304 proxy_object->GetPrototype()->ToObject();
19305
19306 // Hidden prototype without security check.
19307 Local<Object> hidden_prototype =
19308 hidden_proto_template->GetFunction()->NewInstance();
19309 Local<Object> object_with_hidden =
19310 Object::New();
19311 object_with_hidden->SetPrototype(hidden_prototype);
19312
19313 // Hidden prototype with security check on the hidden prototype.
19314 Local<Object> protected_hidden_prototype =
19315 protected_hidden_proto_template->GetFunction()->NewInstance();
19316 Local<Object> object_with_protected_hidden =
19317 Object::New();
19318 object_with_protected_hidden->SetPrototype(protected_hidden_prototype);
19319
19320 context->Exit();
19321
19322 // Template for object for second context. Values to test are put on it as
19323 // properties.
19324 Local<ObjectTemplate> global_template = ObjectTemplate::New();
19325 global_template->Set(v8_str("simple"), simple_object);
19326 global_template->Set(v8_str("protected"), protected_object);
19327 global_template->Set(v8_str("global"), global_object);
19328 global_template->Set(v8_str("proxy"), proxy_object);
19329 global_template->Set(v8_str("hidden"), object_with_hidden);
19330 global_template->Set(v8_str("phidden"), object_with_protected_hidden);
19331
19332 LocalContext context2(NULL, global_template);
19333
19334 Local<Value> result1 = CompileRun("Object.getPrototypeOf(simple)");
19335 CHECK(result1->Equals(simple_object->GetPrototype()));
19336
19337 Local<Value> result2 = CompileRun("Object.getPrototypeOf(protected)");
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000019338 CHECK(result2->Equals(Undefined(isolate)));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000019339
19340 Local<Value> result3 = CompileRun("Object.getPrototypeOf(global)");
19341 CHECK(result3->Equals(global_object->GetPrototype()));
19342
19343 Local<Value> result4 = CompileRun("Object.getPrototypeOf(proxy)");
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000019344 CHECK(result4->Equals(Undefined(isolate)));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000019345
19346 Local<Value> result5 = CompileRun("Object.getPrototypeOf(hidden)");
19347 CHECK(result5->Equals(
19348 object_with_hidden->GetPrototype()->ToObject()->GetPrototype()));
19349
19350 Local<Value> result6 = CompileRun("Object.getPrototypeOf(phidden)");
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000019351 CHECK(result6->Equals(Undefined(isolate)));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000019352}
19353
19354
jkummerow@chromium.org212d9642012-05-11 15:02:09 +000019355THREADED_TEST(Regress125988) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019356 v8::HandleScope scope(CcTest::isolate());
jkummerow@chromium.org212d9642012-05-11 15:02:09 +000019357 Handle<FunctionTemplate> intercept = FunctionTemplate::New();
19358 AddInterceptor(intercept, EmptyInterceptorGetter, EmptyInterceptorSetter);
19359 LocalContext env;
19360 env->Global()->Set(v8_str("Intercept"), intercept->GetFunction());
19361 CompileRun("var a = new Object();"
19362 "var b = new Intercept();"
19363 "var c = new Object();"
19364 "c.__proto__ = b;"
19365 "b.__proto__ = a;"
19366 "a.x = 23;"
19367 "for (var i = 0; i < 3; i++) c.x;");
19368 ExpectBoolean("c.hasOwnProperty('x')", false);
19369 ExpectInt32("c.x", 23);
19370 CompileRun("a.y = 42;"
19371 "for (var i = 0; i < 3; i++) c.x;");
19372 ExpectBoolean("c.hasOwnProperty('x')", false);
19373 ExpectInt32("c.x", 23);
19374 ExpectBoolean("c.hasOwnProperty('y')", false);
19375 ExpectInt32("c.y", 42);
19376}
19377
19378
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000019379static void TestReceiver(Local<Value> expected_result,
19380 Local<Value> expected_receiver,
19381 const char* code) {
19382 Local<Value> result = CompileRun(code);
19383 CHECK(result->IsObject());
19384 CHECK(expected_receiver->Equals(result->ToObject()->Get(1)));
19385 CHECK(expected_result->Equals(result->ToObject()->Get(0)));
19386}
19387
19388
19389THREADED_TEST(ForeignFunctionReceiver) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019390 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000019391 HandleScope scope(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000019392
19393 // Create two contexts with different "id" properties ('i' and 'o').
19394 // Call a function both from its own context and from a the foreign
19395 // context, and see what "this" is bound to (returning both "this"
19396 // and "this.id" for comparison).
19397
ulan@chromium.org57ff8812013-05-10 08:16:55 +000019398 Local<Context> foreign_context = v8::Context::New(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000019399 foreign_context->Enter();
19400 Local<Value> foreign_function =
19401 CompileRun("function func() { return { 0: this.id, "
19402 " 1: this, "
19403 " toString: function() { "
19404 " return this[0];"
19405 " }"
19406 " };"
19407 "}"
19408 "var id = 'i';"
19409 "func;");
19410 CHECK(foreign_function->IsFunction());
19411 foreign_context->Exit();
19412
19413 LocalContext context;
19414
19415 Local<String> password = v8_str("Password");
19416 // Don't get hit by security checks when accessing foreign_context's
19417 // global receiver (aka. global proxy).
19418 context->SetSecurityToken(password);
19419 foreign_context->SetSecurityToken(password);
19420
19421 Local<String> i = v8_str("i");
19422 Local<String> o = v8_str("o");
19423 Local<String> id = v8_str("id");
19424
19425 CompileRun("function ownfunc() { return { 0: this.id, "
19426 " 1: this, "
19427 " toString: function() { "
19428 " return this[0];"
19429 " }"
19430 " };"
19431 "}"
19432 "var id = 'o';"
19433 "ownfunc");
19434 context->Global()->Set(v8_str("func"), foreign_function);
19435
19436 // Sanity check the contexts.
19437 CHECK(i->Equals(foreign_context->Global()->Get(id)));
19438 CHECK(o->Equals(context->Global()->Get(id)));
19439
19440 // Checking local function's receiver.
19441 // Calling function using its call/apply methods.
19442 TestReceiver(o, context->Global(), "ownfunc.call()");
19443 TestReceiver(o, context->Global(), "ownfunc.apply()");
19444 // Making calls through built-in functions.
19445 TestReceiver(o, context->Global(), "[1].map(ownfunc)[0]");
19446 CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/,ownfunc)[1]")));
19447 CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/g,ownfunc)[1]")));
19448 CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/g,ownfunc)[3]")));
19449 // Calling with environment record as base.
19450 TestReceiver(o, context->Global(), "ownfunc()");
19451 // Calling with no base.
19452 TestReceiver(o, context->Global(), "(1,ownfunc)()");
19453
19454 // Checking foreign function return value.
19455 // Calling function using its call/apply methods.
19456 TestReceiver(i, foreign_context->Global(), "func.call()");
19457 TestReceiver(i, foreign_context->Global(), "func.apply()");
19458 // Calling function using another context's call/apply methods.
19459 TestReceiver(i, foreign_context->Global(),
19460 "Function.prototype.call.call(func)");
19461 TestReceiver(i, foreign_context->Global(),
19462 "Function.prototype.call.apply(func)");
19463 TestReceiver(i, foreign_context->Global(),
19464 "Function.prototype.apply.call(func)");
19465 TestReceiver(i, foreign_context->Global(),
19466 "Function.prototype.apply.apply(func)");
19467 // Making calls through built-in functions.
19468 TestReceiver(i, foreign_context->Global(), "[1].map(func)[0]");
19469 // ToString(func()) is func()[0], i.e., the returned this.id.
19470 CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/,func)[1]")));
19471 CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/g,func)[1]")));
19472 CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/g,func)[3]")));
19473
19474 // TODO(1547): Make the following also return "i".
19475 // Calling with environment record as base.
19476 TestReceiver(o, context->Global(), "func()");
19477 // Calling with no base.
19478 TestReceiver(o, context->Global(), "(1,func)()");
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000019479}
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000019480
19481
19482uint8_t callback_fired = 0;
19483
19484
19485void CallCompletedCallback1() {
19486 i::OS::Print("Firing callback 1.\n");
19487 callback_fired ^= 1; // Toggle first bit.
19488}
19489
19490
19491void CallCompletedCallback2() {
19492 i::OS::Print("Firing callback 2.\n");
19493 callback_fired ^= 2; // Toggle second bit.
19494}
19495
19496
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000019497void RecursiveCall(const v8::FunctionCallbackInfo<v8::Value>& args) {
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000019498 int32_t level = args[0]->Int32Value();
19499 if (level < 3) {
19500 level++;
19501 i::OS::Print("Entering recursion level %d.\n", level);
19502 char script[64];
19503 i::Vector<char> script_vector(script, sizeof(script));
19504 i::OS::SNPrintF(script_vector, "recursion(%d)", level);
19505 CompileRun(script_vector.start());
19506 i::OS::Print("Leaving recursion level %d.\n", level);
19507 CHECK_EQ(0, callback_fired);
19508 } else {
19509 i::OS::Print("Recursion ends.\n");
19510 CHECK_EQ(0, callback_fired);
19511 }
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000019512}
19513
19514
19515TEST(CallCompletedCallback) {
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000019516 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019517 v8::HandleScope scope(env->GetIsolate());
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000019518 v8::Handle<v8::FunctionTemplate> recursive_runtime =
19519 v8::FunctionTemplate::New(RecursiveCall);
19520 env->Global()->Set(v8_str("recursion"),
19521 recursive_runtime->GetFunction());
19522 // Adding the same callback a second time has no effect.
19523 v8::V8::AddCallCompletedCallback(CallCompletedCallback1);
19524 v8::V8::AddCallCompletedCallback(CallCompletedCallback1);
19525 v8::V8::AddCallCompletedCallback(CallCompletedCallback2);
19526 i::OS::Print("--- Script (1) ---\n");
19527 Local<Script> script =
19528 v8::Script::Compile(v8::String::New("recursion(0)"));
19529 script->Run();
19530 CHECK_EQ(3, callback_fired);
19531
19532 i::OS::Print("\n--- Script (2) ---\n");
19533 callback_fired = 0;
19534 v8::V8::RemoveCallCompletedCallback(CallCompletedCallback1);
19535 script->Run();
19536 CHECK_EQ(2, callback_fired);
19537
19538 i::OS::Print("\n--- Function ---\n");
19539 callback_fired = 0;
19540 Local<Function> recursive_function =
19541 Local<Function>::Cast(env->Global()->Get(v8_str("recursion")));
19542 v8::Handle<Value> args[] = { v8_num(0) };
19543 recursive_function->Call(env->Global(), 1, args);
19544 CHECK_EQ(2, callback_fired);
19545}
19546
19547
19548void CallCompletedCallbackNoException() {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019549 v8::HandleScope scope(CcTest::isolate());
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000019550 CompileRun("1+1;");
19551}
19552
19553
19554void CallCompletedCallbackException() {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019555 v8::HandleScope scope(CcTest::isolate());
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000019556 CompileRun("throw 'second exception';");
19557}
19558
19559
19560TEST(CallCompletedCallbackOneException) {
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000019561 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019562 v8::HandleScope scope(env->GetIsolate());
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000019563 v8::V8::AddCallCompletedCallback(CallCompletedCallbackNoException);
19564 CompileRun("throw 'exception';");
19565}
19566
19567
19568TEST(CallCompletedCallbackTwoExceptions) {
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000019569 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019570 v8::HandleScope scope(env->GetIsolate());
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000019571 v8::V8::AddCallCompletedCallback(CallCompletedCallbackException);
19572 CompileRun("throw 'first exception';");
19573}
ulan@chromium.org812308e2012-02-29 15:58:45 +000019574
19575
19576static int probes_counter = 0;
19577static int misses_counter = 0;
19578static int updates_counter = 0;
19579
19580
19581static int* LookupCounter(const char* name) {
19582 if (strcmp(name, "c:V8.MegamorphicStubCacheProbes") == 0) {
19583 return &probes_counter;
19584 } else if (strcmp(name, "c:V8.MegamorphicStubCacheMisses") == 0) {
19585 return &misses_counter;
19586 } else if (strcmp(name, "c:V8.MegamorphicStubCacheUpdates") == 0) {
19587 return &updates_counter;
19588 }
19589 return NULL;
19590}
19591
19592
19593static const char* kMegamorphicTestProgram =
19594 "function ClassA() { };"
19595 "function ClassB() { };"
19596 "ClassA.prototype.foo = function() { };"
19597 "ClassB.prototype.foo = function() { };"
19598 "function fooify(obj) { obj.foo(); };"
19599 "var a = new ClassA();"
19600 "var b = new ClassB();"
19601 "for (var i = 0; i < 10000; i++) {"
19602 " fooify(a);"
19603 " fooify(b);"
19604 "}";
19605
19606
19607static void StubCacheHelper(bool primary) {
19608 V8::SetCounterFunction(LookupCounter);
19609 USE(kMegamorphicTestProgram);
19610#ifdef DEBUG
19611 i::FLAG_native_code_counters = true;
19612 if (primary) {
19613 i::FLAG_test_primary_stub_cache = true;
19614 } else {
19615 i::FLAG_test_secondary_stub_cache = true;
19616 }
19617 i::FLAG_crankshaft = false;
ulan@chromium.org812308e2012-02-29 15:58:45 +000019618 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019619 v8::HandleScope scope(env->GetIsolate());
ulan@chromium.org812308e2012-02-29 15:58:45 +000019620 int initial_probes = probes_counter;
19621 int initial_misses = misses_counter;
19622 int initial_updates = updates_counter;
19623 CompileRun(kMegamorphicTestProgram);
19624 int probes = probes_counter - initial_probes;
19625 int misses = misses_counter - initial_misses;
19626 int updates = updates_counter - initial_updates;
19627 CHECK_LT(updates, 10);
19628 CHECK_LT(misses, 10);
19629 CHECK_GE(probes, 10000);
19630#endif
19631}
19632
19633
19634TEST(SecondaryStubCache) {
19635 StubCacheHelper(true);
19636}
19637
19638
19639TEST(PrimaryStubCache) {
19640 StubCacheHelper(false);
19641}
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000019642
19643
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000019644TEST(StaticGetters) {
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000019645 LocalContext context;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019646 i::Factory* factory = CcTest::i_isolate()->factory();
19647 v8::Isolate* isolate = CcTest::isolate();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019648 v8::HandleScope scope(isolate);
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000019649 i::Handle<i::Object> undefined_value = factory->undefined_value();
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000019650 CHECK(*v8::Utils::OpenHandle(*v8::Undefined(isolate)) == *undefined_value);
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000019651 i::Handle<i::Object> null_value = factory->null_value();
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000019652 CHECK(*v8::Utils::OpenHandle(*v8::Null(isolate)) == *null_value);
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000019653 i::Handle<i::Object> true_value = factory->true_value();
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000019654 CHECK(*v8::Utils::OpenHandle(*v8::True(isolate)) == *true_value);
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000019655 i::Handle<i::Object> false_value = factory->false_value();
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000019656 CHECK(*v8::Utils::OpenHandle(*v8::False(isolate)) == *false_value);
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000019657}
19658
19659
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019660UNINITIALIZED_TEST(IsolateEmbedderData) {
19661 CcTest::DisableAutomaticDispose();
19662 v8::Isolate* isolate = v8::Isolate::New();
19663 isolate->Enter();
hpayer@chromium.orgc5d49712013-09-11 08:25:48 +000019664 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000019665 CHECK_EQ(NULL, isolate->GetData());
hpayer@chromium.orgc5d49712013-09-11 08:25:48 +000019666 CHECK_EQ(NULL, i_isolate->GetData());
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000019667 static void* data1 = reinterpret_cast<void*>(0xacce55ed);
19668 isolate->SetData(data1);
19669 CHECK_EQ(data1, isolate->GetData());
hpayer@chromium.orgc5d49712013-09-11 08:25:48 +000019670 CHECK_EQ(data1, i_isolate->GetData());
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000019671 static void* data2 = reinterpret_cast<void*>(0xdecea5ed);
hpayer@chromium.orgc5d49712013-09-11 08:25:48 +000019672 i_isolate->SetData(data2);
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000019673 CHECK_EQ(data2, isolate->GetData());
hpayer@chromium.orgc5d49712013-09-11 08:25:48 +000019674 CHECK_EQ(data2, i_isolate->GetData());
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019675 isolate->Exit();
19676 isolate->Dispose();
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000019677}
19678
19679
19680TEST(StringEmpty) {
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000019681 LocalContext context;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019682 i::Factory* factory = CcTest::i_isolate()->factory();
19683 v8::Isolate* isolate = CcTest::isolate();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019684 v8::HandleScope scope(isolate);
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000019685 i::Handle<i::Object> empty_string = factory->empty_string();
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000019686 CHECK(*v8::Utils::OpenHandle(*v8::String::Empty()) == *empty_string);
19687 CHECK(*v8::Utils::OpenHandle(*v8::String::Empty(isolate)) == *empty_string);
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000019688}
mmassi@chromium.org7028c052012-06-13 11:51:58 +000019689
19690
19691static int instance_checked_getter_count = 0;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000019692static void InstanceCheckedGetter(
19693 Local<String> name,
19694 const v8::PropertyCallbackInfo<v8::Value>& info) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +000019695 CHECK_EQ(name, v8_str("foo"));
19696 instance_checked_getter_count++;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000019697 info.GetReturnValue().Set(v8_num(11));
mmassi@chromium.org7028c052012-06-13 11:51:58 +000019698}
19699
19700
19701static int instance_checked_setter_count = 0;
19702static void InstanceCheckedSetter(Local<String> name,
19703 Local<Value> value,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000019704 const v8::PropertyCallbackInfo<void>& info) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +000019705 CHECK_EQ(name, v8_str("foo"));
19706 CHECK_EQ(value, v8_num(23));
19707 instance_checked_setter_count++;
19708}
19709
19710
19711static void CheckInstanceCheckedResult(int getters,
19712 int setters,
19713 bool expects_callbacks,
19714 TryCatch* try_catch) {
19715 if (expects_callbacks) {
19716 CHECK(!try_catch->HasCaught());
19717 CHECK_EQ(getters, instance_checked_getter_count);
19718 CHECK_EQ(setters, instance_checked_setter_count);
19719 } else {
19720 CHECK(try_catch->HasCaught());
19721 CHECK_EQ(0, instance_checked_getter_count);
19722 CHECK_EQ(0, instance_checked_setter_count);
19723 }
19724 try_catch->Reset();
19725}
19726
19727
19728static void CheckInstanceCheckedAccessors(bool expects_callbacks) {
19729 instance_checked_getter_count = 0;
19730 instance_checked_setter_count = 0;
19731 TryCatch try_catch;
19732
19733 // Test path through generic runtime code.
19734 CompileRun("obj.foo");
19735 CheckInstanceCheckedResult(1, 0, expects_callbacks, &try_catch);
19736 CompileRun("obj.foo = 23");
19737 CheckInstanceCheckedResult(1, 1, expects_callbacks, &try_catch);
19738
19739 // Test path through generated LoadIC and StoredIC.
19740 CompileRun("function test_get(o) { o.foo; }"
19741 "test_get(obj);");
19742 CheckInstanceCheckedResult(2, 1, expects_callbacks, &try_catch);
19743 CompileRun("test_get(obj);");
19744 CheckInstanceCheckedResult(3, 1, expects_callbacks, &try_catch);
19745 CompileRun("test_get(obj);");
19746 CheckInstanceCheckedResult(4, 1, expects_callbacks, &try_catch);
19747 CompileRun("function test_set(o) { o.foo = 23; }"
19748 "test_set(obj);");
19749 CheckInstanceCheckedResult(4, 2, expects_callbacks, &try_catch);
19750 CompileRun("test_set(obj);");
19751 CheckInstanceCheckedResult(4, 3, expects_callbacks, &try_catch);
19752 CompileRun("test_set(obj);");
19753 CheckInstanceCheckedResult(4, 4, expects_callbacks, &try_catch);
19754
19755 // Test path through optimized code.
19756 CompileRun("%OptimizeFunctionOnNextCall(test_get);"
19757 "test_get(obj);");
19758 CheckInstanceCheckedResult(5, 4, expects_callbacks, &try_catch);
19759 CompileRun("%OptimizeFunctionOnNextCall(test_set);"
19760 "test_set(obj);");
19761 CheckInstanceCheckedResult(5, 5, expects_callbacks, &try_catch);
19762
19763 // Cleanup so that closures start out fresh in next check.
19764 CompileRun("%DeoptimizeFunction(test_get);"
19765 "%ClearFunctionTypeFeedback(test_get);"
19766 "%DeoptimizeFunction(test_set);"
19767 "%ClearFunctionTypeFeedback(test_set);");
19768}
19769
19770
19771THREADED_TEST(InstanceCheckOnInstanceAccessor) {
19772 v8::internal::FLAG_allow_natives_syntax = true;
mmassi@chromium.org7028c052012-06-13 11:51:58 +000019773 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019774 v8::HandleScope scope(context->GetIsolate());
mmassi@chromium.org7028c052012-06-13 11:51:58 +000019775
19776 Local<FunctionTemplate> templ = FunctionTemplate::New();
19777 Local<ObjectTemplate> inst = templ->InstanceTemplate();
19778 inst->SetAccessor(v8_str("foo"),
19779 InstanceCheckedGetter, InstanceCheckedSetter,
19780 Handle<Value>(),
19781 v8::DEFAULT,
19782 v8::None,
19783 v8::AccessorSignature::New(templ));
19784 context->Global()->Set(v8_str("f"), templ->GetFunction());
19785
19786 printf("Testing positive ...\n");
19787 CompileRun("var obj = new f();");
19788 CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
19789 CheckInstanceCheckedAccessors(true);
19790
19791 printf("Testing negative ...\n");
19792 CompileRun("var obj = {};"
19793 "obj.__proto__ = new f();");
19794 CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
19795 CheckInstanceCheckedAccessors(false);
19796}
19797
19798
19799THREADED_TEST(InstanceCheckOnInstanceAccessorWithInterceptor) {
19800 v8::internal::FLAG_allow_natives_syntax = true;
mmassi@chromium.org7028c052012-06-13 11:51:58 +000019801 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019802 v8::HandleScope scope(context->GetIsolate());
mmassi@chromium.org7028c052012-06-13 11:51:58 +000019803
19804 Local<FunctionTemplate> templ = FunctionTemplate::New();
19805 Local<ObjectTemplate> inst = templ->InstanceTemplate();
19806 AddInterceptor(templ, EmptyInterceptorGetter, EmptyInterceptorSetter);
19807 inst->SetAccessor(v8_str("foo"),
19808 InstanceCheckedGetter, InstanceCheckedSetter,
19809 Handle<Value>(),
19810 v8::DEFAULT,
19811 v8::None,
19812 v8::AccessorSignature::New(templ));
19813 context->Global()->Set(v8_str("f"), templ->GetFunction());
19814
19815 printf("Testing positive ...\n");
19816 CompileRun("var obj = new f();");
19817 CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
19818 CheckInstanceCheckedAccessors(true);
19819
19820 printf("Testing negative ...\n");
19821 CompileRun("var obj = {};"
19822 "obj.__proto__ = new f();");
19823 CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
19824 CheckInstanceCheckedAccessors(false);
19825}
19826
19827
19828THREADED_TEST(InstanceCheckOnPrototypeAccessor) {
19829 v8::internal::FLAG_allow_natives_syntax = true;
mmassi@chromium.org7028c052012-06-13 11:51:58 +000019830 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019831 v8::HandleScope scope(context->GetIsolate());
mmassi@chromium.org7028c052012-06-13 11:51:58 +000019832
19833 Local<FunctionTemplate> templ = FunctionTemplate::New();
19834 Local<ObjectTemplate> proto = templ->PrototypeTemplate();
19835 proto->SetAccessor(v8_str("foo"),
19836 InstanceCheckedGetter, InstanceCheckedSetter,
19837 Handle<Value>(),
19838 v8::DEFAULT,
19839 v8::None,
19840 v8::AccessorSignature::New(templ));
19841 context->Global()->Set(v8_str("f"), templ->GetFunction());
19842
19843 printf("Testing positive ...\n");
19844 CompileRun("var obj = new f();");
19845 CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
19846 CheckInstanceCheckedAccessors(true);
19847
19848 printf("Testing negative ...\n");
19849 CompileRun("var obj = {};"
19850 "obj.__proto__ = new f();");
19851 CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
19852 CheckInstanceCheckedAccessors(false);
19853
19854 printf("Testing positive with modified prototype chain ...\n");
19855 CompileRun("var obj = new f();"
19856 "var pro = {};"
19857 "pro.__proto__ = obj.__proto__;"
19858 "obj.__proto__ = pro;");
19859 CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
19860 CheckInstanceCheckedAccessors(true);
19861}
19862
19863
19864TEST(TryFinallyMessage) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +000019865 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019866 v8::HandleScope scope(context->GetIsolate());
mmassi@chromium.org7028c052012-06-13 11:51:58 +000019867 {
19868 // Test that the original error message is not lost if there is a
19869 // recursive call into Javascript is done in the finally block, e.g. to
19870 // initialize an IC. (crbug.com/129171)
19871 TryCatch try_catch;
19872 const char* trigger_ic =
19873 "try { \n"
19874 " throw new Error('test'); \n"
19875 "} finally { \n"
19876 " var x = 0; \n"
19877 " x++; \n" // Trigger an IC initialization here.
19878 "} \n";
19879 CompileRun(trigger_ic);
19880 CHECK(try_catch.HasCaught());
19881 Local<Message> message = try_catch.Message();
19882 CHECK(!message.IsEmpty());
19883 CHECK_EQ(2, message->GetLineNumber());
19884 }
19885
19886 {
19887 // Test that the original exception message is indeed overwritten if
19888 // a new error is thrown in the finally block.
19889 TryCatch try_catch;
19890 const char* throw_again =
19891 "try { \n"
19892 " throw new Error('test'); \n"
19893 "} finally { \n"
19894 " var x = 0; \n"
19895 " x++; \n"
19896 " throw new Error('again'); \n" // This is the new uncaught error.
19897 "} \n";
19898 CompileRun(throw_again);
19899 CHECK(try_catch.HasCaught());
19900 Local<Message> message = try_catch.Message();
19901 CHECK(!message.IsEmpty());
19902 CHECK_EQ(6, message->GetLineNumber());
19903 }
19904}
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000019905
19906
erik.corry@gmail.com88767242012-08-08 14:43:45 +000019907static void Helper137002(bool do_store,
19908 bool polymorphic,
19909 bool remove_accessor,
19910 bool interceptor) {
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000019911 LocalContext context;
19912 Local<ObjectTemplate> templ = ObjectTemplate::New();
erik.corry@gmail.com88767242012-08-08 14:43:45 +000019913 if (interceptor) {
19914 templ->SetNamedPropertyHandler(FooGetInterceptor, FooSetInterceptor);
19915 } else {
19916 templ->SetAccessor(v8_str("foo"),
19917 GetterWhichReturns42,
19918 SetterWhichSetsYOnThisTo23);
19919 }
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000019920 context->Global()->Set(v8_str("obj"), templ->NewInstance());
19921
19922 // Turn monomorphic on slow object with native accessor, then turn
19923 // polymorphic, finally optimize to create negative lookup and fail.
erik.corry@gmail.com88767242012-08-08 14:43:45 +000019924 CompileRun(do_store ?
19925 "function f(x) { x.foo = void 0; }" :
19926 "function f(x) { return x.foo; }");
19927 CompileRun("obj.y = void 0;");
19928 if (!interceptor) {
19929 CompileRun("%OptimizeObjectForAddingMultipleProperties(obj, 1);");
19930 }
19931 CompileRun("obj.__proto__ = null;"
19932 "f(obj); f(obj); f(obj);");
19933 if (polymorphic) {
19934 CompileRun("f({});");
19935 }
19936 CompileRun("obj.y = void 0;"
19937 "%OptimizeFunctionOnNextCall(f);");
19938 if (remove_accessor) {
19939 CompileRun("delete obj.foo;");
19940 }
19941 CompileRun("var result = f(obj);");
19942 if (do_store) {
19943 CompileRun("result = obj.y;");
19944 }
19945 if (remove_accessor && !interceptor) {
19946 CHECK(context->Global()->Get(v8_str("result"))->IsUndefined());
19947 } else {
19948 CHECK_EQ(do_store ? 23 : 42,
19949 context->Global()->Get(v8_str("result"))->Int32Value());
19950 }
19951}
19952
19953
19954THREADED_TEST(Regress137002a) {
19955 i::FLAG_allow_natives_syntax = true;
19956 i::FLAG_compilation_cache = false;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019957 v8::HandleScope scope(CcTest::isolate());
erik.corry@gmail.com88767242012-08-08 14:43:45 +000019958 for (int i = 0; i < 16; i++) {
19959 Helper137002(i & 8, i & 4, i & 2, i & 1);
19960 }
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000019961}
19962
19963
19964THREADED_TEST(Regress137002b) {
19965 i::FLAG_allow_natives_syntax = true;
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000019966 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019967 v8::HandleScope scope(context->GetIsolate());
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000019968 Local<ObjectTemplate> templ = ObjectTemplate::New();
19969 templ->SetAccessor(v8_str("foo"),
19970 GetterWhichReturns42,
19971 SetterWhichSetsYOnThisTo23);
19972 context->Global()->Set(v8_str("obj"), templ->NewInstance());
19973
19974 // Turn monomorphic on slow object with native accessor, then just
19975 // delete the property and fail.
erik.corry@gmail.com88767242012-08-08 14:43:45 +000019976 CompileRun("function load(x) { return x.foo; }"
19977 "function store(x) { x.foo = void 0; }"
19978 "function keyed_load(x, key) { return x[key]; }"
19979 // Second version of function has a different source (add void 0)
19980 // so that it does not share code with the first version. This
19981 // ensures that the ICs are monomorphic.
19982 "function load2(x) { void 0; return x.foo; }"
19983 "function store2(x) { void 0; x.foo = void 0; }"
19984 "function keyed_load2(x, key) { void 0; return x[key]; }"
19985
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000019986 "obj.y = void 0;"
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000019987 "obj.__proto__ = null;"
erik.corry@gmail.com88767242012-08-08 14:43:45 +000019988 "var subobj = {};"
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000019989 "subobj.y = void 0;"
erik.corry@gmail.com88767242012-08-08 14:43:45 +000019990 "subobj.__proto__ = obj;"
19991 "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
19992
19993 // Make the ICs monomorphic.
19994 "load(obj); load(obj);"
19995 "load2(subobj); load2(subobj);"
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000019996 "store(obj); store(obj);"
19997 "store2(subobj); store2(subobj);"
erik.corry@gmail.com88767242012-08-08 14:43:45 +000019998 "keyed_load(obj, 'foo'); keyed_load(obj, 'foo');"
19999 "keyed_load2(subobj, 'foo'); keyed_load2(subobj, 'foo');"
20000
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000020001 // Actually test the shiny new ICs and better not crash. This
20002 // serves as a regression test for issue 142088 as well.
20003 "load(obj);"
20004 "load2(subobj);"
20005 "store(obj);"
20006 "store2(subobj);"
20007 "keyed_load(obj, 'foo');"
20008 "keyed_load2(subobj, 'foo');"
20009
erik.corry@gmail.com88767242012-08-08 14:43:45 +000020010 // Delete the accessor. It better not be called any more now.
20011 "delete obj.foo;"
20012 "obj.y = void 0;"
20013 "subobj.y = void 0;"
20014
20015 "var load_result = load(obj);"
20016 "var load_result2 = load2(subobj);"
20017 "var keyed_load_result = keyed_load(obj, 'foo');"
20018 "var keyed_load_result2 = keyed_load2(subobj, 'foo');"
20019 "store(obj);"
20020 "store2(subobj);"
20021 "var y_from_obj = obj.y;"
20022 "var y_from_subobj = subobj.y;");
20023 CHECK(context->Global()->Get(v8_str("load_result"))->IsUndefined());
20024 CHECK(context->Global()->Get(v8_str("load_result2"))->IsUndefined());
20025 CHECK(context->Global()->Get(v8_str("keyed_load_result"))->IsUndefined());
20026 CHECK(context->Global()->Get(v8_str("keyed_load_result2"))->IsUndefined());
20027 CHECK(context->Global()->Get(v8_str("y_from_obj"))->IsUndefined());
20028 CHECK(context->Global()->Get(v8_str("y_from_subobj"))->IsUndefined());
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000020029}
verwaest@chromium.org753aee42012-07-17 16:15:42 +000020030
20031
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000020032THREADED_TEST(Regress142088) {
20033 i::FLAG_allow_natives_syntax = true;
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000020034 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020035 v8::HandleScope scope(context->GetIsolate());
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000020036 Local<ObjectTemplate> templ = ObjectTemplate::New();
20037 templ->SetAccessor(v8_str("foo"),
20038 GetterWhichReturns42,
20039 SetterWhichSetsYOnThisTo23);
20040 context->Global()->Set(v8_str("obj"), templ->NewInstance());
20041
20042 CompileRun("function load(x) { return x.foo; }"
20043 "var o = Object.create(obj);"
20044 "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
20045 "load(o); load(o); load(o); load(o);");
20046}
20047
20048
verwaest@chromium.org753aee42012-07-17 16:15:42 +000020049THREADED_TEST(Regress137496) {
20050 i::FLAG_expose_gc = true;
verwaest@chromium.org753aee42012-07-17 16:15:42 +000020051 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020052 v8::HandleScope scope(context->GetIsolate());
verwaest@chromium.org753aee42012-07-17 16:15:42 +000020053
20054 // Compile a try-finally clause where the finally block causes a GC
20055 // while there still is a message pending for external reporting.
20056 TryCatch try_catch;
20057 try_catch.SetVerbose(true);
20058 CompileRun("try { throw new Error(); } finally { gc(); }");
20059 CHECK(try_catch.HasCaught());
20060}
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000020061
20062
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000020063THREADED_TEST(Regress149912) {
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000020064 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020065 v8::HandleScope scope(context->GetIsolate());
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000020066 Handle<FunctionTemplate> templ = FunctionTemplate::New();
20067 AddInterceptor(templ, EmptyInterceptorGetter, EmptyInterceptorSetter);
20068 context->Global()->Set(v8_str("Bug"), templ->GetFunction());
20069 CompileRun("Number.prototype.__proto__ = new Bug; var x = 0; x.foo();");
20070}
20071
20072
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000020073THREADED_TEST(Regress157124) {
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000020074 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020075 v8::HandleScope scope(context->GetIsolate());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000020076 Local<ObjectTemplate> templ = ObjectTemplate::New();
20077 Local<Object> obj = templ->NewInstance();
20078 obj->GetIdentityHash();
20079 obj->DeleteHiddenValue(v8_str("Bug"));
20080}
20081
20082
ulan@chromium.org6e196bf2013-03-13 09:38:22 +000020083THREADED_TEST(Regress2535) {
20084 i::FLAG_harmony_collections = true;
ulan@chromium.org6e196bf2013-03-13 09:38:22 +000020085 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020086 v8::HandleScope scope(context->GetIsolate());
ulan@chromium.org6e196bf2013-03-13 09:38:22 +000020087 Local<Value> set_value = CompileRun("new Set();");
danno@chromium.orgf95d4b92013-06-13 14:40:17 +000020088 Local<Object> set_object(Local<Object>::Cast(set_value));
ulan@chromium.org6e196bf2013-03-13 09:38:22 +000020089 CHECK_EQ(0, set_object->InternalFieldCount());
20090 Local<Value> map_value = CompileRun("new Map();");
danno@chromium.orgf95d4b92013-06-13 14:40:17 +000020091 Local<Object> map_object(Local<Object>::Cast(map_value));
ulan@chromium.org6e196bf2013-03-13 09:38:22 +000020092 CHECK_EQ(0, map_object->InternalFieldCount());
20093}
20094
20095
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000020096THREADED_TEST(Regress2746) {
20097 LocalContext context;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000020098 v8::Isolate* isolate = context->GetIsolate();
20099 v8::HandleScope scope(isolate);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000020100 Local<Object> obj = Object::New();
20101 Local<String> key = String::New("key");
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000020102 obj->SetHiddenValue(key, v8::Undefined(isolate));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000020103 Local<Value> value = obj->GetHiddenValue(key);
20104 CHECK(!value.IsEmpty());
20105 CHECK(value->IsUndefined());
20106}
20107
20108
jkummerow@chromium.org10480472013-07-17 08:22:15 +000020109THREADED_TEST(Regress260106) {
20110 LocalContext context;
20111 v8::HandleScope scope(context->GetIsolate());
20112 Local<FunctionTemplate> templ = FunctionTemplate::New(DummyCallHandler);
20113 CompileRun("for (var i = 0; i < 128; i++) Object.prototype[i] = 0;");
20114 Local<Function> function = templ->GetFunction();
20115 CHECK(!function.IsEmpty());
20116 CHECK(function->IsFunction());
20117}
20118
20119
danno@chromium.org59400602013-08-13 17:09:37 +000020120THREADED_TEST(JSONParseObject) {
20121 LocalContext context;
20122 HandleScope scope(context->GetIsolate());
20123 Local<Value> obj = v8::JSON::Parse(v8_str("{\"x\":42}"));
20124 Handle<Object> global = context->Global();
20125 global->Set(v8_str("obj"), obj);
20126 ExpectString("JSON.stringify(obj)", "{\"x\":42}");
20127}
20128
20129
20130THREADED_TEST(JSONParseNumber) {
20131 LocalContext context;
20132 HandleScope scope(context->GetIsolate());
20133 Local<Value> obj = v8::JSON::Parse(v8_str("42"));
20134 Handle<Object> global = context->Global();
20135 global->Set(v8_str("obj"), obj);
20136 ExpectString("JSON.stringify(obj)", "42");
20137}
20138
20139
verwaest@chromium.org662436e2013-08-28 08:41:27 +000020140#if V8_OS_POSIX
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000020141class ThreadInterruptTest {
20142 public:
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000020143 ThreadInterruptTest() : sem_(0), sem_value_(0) { }
20144 ~ThreadInterruptTest() {}
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000020145
20146 void RunTest() {
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000020147 InterruptThread i_thread(this);
20148 i_thread.Start();
20149
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000020150 sem_.Wait();
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000020151 CHECK_EQ(kExpectedValue, sem_value_);
20152 }
20153
20154 private:
20155 static const int kExpectedValue = 1;
20156
20157 class InterruptThread : public i::Thread {
20158 public:
20159 explicit InterruptThread(ThreadInterruptTest* test)
20160 : Thread("InterruptThread"), test_(test) {}
20161
20162 virtual void Run() {
20163 struct sigaction action;
20164
20165 // Ensure that we'll enter waiting condition
20166 i::OS::Sleep(100);
20167
20168 // Setup signal handler
20169 memset(&action, 0, sizeof(action));
20170 action.sa_handler = SignalHandler;
20171 sigaction(SIGCHLD, &action, NULL);
20172
20173 // Send signal
20174 kill(getpid(), SIGCHLD);
20175
20176 // Ensure that if wait has returned because of error
20177 i::OS::Sleep(100);
20178
20179 // Set value and signal semaphore
20180 test_->sem_value_ = 1;
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000020181 test_->sem_.Signal();
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000020182 }
20183
20184 static void SignalHandler(int signal) {
20185 }
20186
20187 private:
20188 ThreadInterruptTest* test_;
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000020189 };
20190
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000020191 i::Semaphore sem_;
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000020192 volatile int sem_value_;
20193};
20194
20195
20196THREADED_TEST(SemaphoreInterruption) {
20197 ThreadInterruptTest().RunTest();
20198}
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000020199
danno@chromium.org169691d2013-07-15 08:01:13 +000020200
20201static bool NamedAccessAlwaysBlocked(Local<v8::Object> global,
20202 Local<Value> name,
20203 v8::AccessType type,
20204 Local<Value> data) {
20205 i::PrintF("Named access blocked.\n");
20206 return false;
20207}
20208
20209
20210static bool IndexAccessAlwaysBlocked(Local<v8::Object> global,
20211 uint32_t key,
20212 v8::AccessType type,
20213 Local<Value> data) {
20214 i::PrintF("Indexed access blocked.\n");
20215 return false;
20216}
20217
20218
20219void UnreachableCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
20220 CHECK(false);
20221}
20222
20223
20224TEST(JSONStringifyAccessCheck) {
20225 v8::V8::Initialize();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020226 v8::HandleScope scope(CcTest::isolate());
danno@chromium.org169691d2013-07-15 08:01:13 +000020227
20228 // Create an ObjectTemplate for global objects and install access
20229 // check callbacks that will block access.
20230 v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
20231 global_template->SetAccessCheckCallbacks(NamedAccessAlwaysBlocked,
20232 IndexAccessAlwaysBlocked);
20233
20234 // Create a context and set an x property on it's global object.
20235 LocalContext context0(NULL, global_template);
20236 v8::Handle<v8::Object> global0 = context0->Global();
20237 global0->Set(v8_str("x"), v8_num(42));
20238 ExpectString("JSON.stringify(this)", "{\"x\":42}");
20239
20240 for (int i = 0; i < 2; i++) {
20241 if (i == 1) {
20242 // Install a toJSON function on the second run.
20243 v8::Handle<v8::FunctionTemplate> toJSON =
20244 v8::FunctionTemplate::New(UnreachableCallback);
20245
20246 global0->Set(v8_str("toJSON"), toJSON->GetFunction());
20247 }
20248 // Create a context with a different security token so that the
20249 // failed access check callback will be called on each access.
20250 LocalContext context1(NULL, global_template);
20251 context1->Global()->Set(v8_str("other"), global0);
20252
20253 ExpectString("JSON.stringify(other)", "{}");
20254 ExpectString("JSON.stringify({ 'a' : other, 'b' : ['c'] })",
20255 "{\"a\":{},\"b\":[\"c\"]}");
20256 ExpectString("JSON.stringify([other, 'b', 'c'])",
20257 "[{},\"b\",\"c\"]");
20258
20259 v8::Handle<v8::Array> array = v8::Array::New(2);
20260 array->Set(0, v8_str("a"));
20261 array->Set(1, v8_str("b"));
20262 context1->Global()->Set(v8_str("array"), array);
20263 ExpectString("JSON.stringify(array)", "[\"a\",\"b\"]");
20264 array->TurnOnAccessCheck();
20265 ExpectString("JSON.stringify(array)", "[]");
20266 ExpectString("JSON.stringify([array])", "[[]]");
20267 ExpectString("JSON.stringify({'a' : array})", "{\"a\":[]}");
20268 }
20269}
20270
20271
20272bool access_check_fail_thrown = false;
20273bool catch_callback_called = false;
20274
20275
20276// Failed access check callback that performs a GC on each invocation.
20277void FailedAccessCheckThrows(Local<v8::Object> target,
20278 v8::AccessType type,
20279 Local<v8::Value> data) {
20280 access_check_fail_thrown = true;
20281 i::PrintF("Access check failed. Error thrown.\n");
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000020282 CcTest::isolate()->ThrowException(
20283 v8::Exception::Error(v8_str("cross context")));
danno@chromium.org169691d2013-07-15 08:01:13 +000020284}
20285
20286
20287void CatcherCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
20288 for (int i = 0; i < args.Length(); i++) {
20289 i::PrintF("%s\n", *String::Utf8Value(args[i]));
20290 }
20291 catch_callback_called = true;
20292}
20293
20294
20295void HasOwnPropertyCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
20296 args[0]->ToObject()->HasOwnProperty(args[1]->ToString());
20297}
20298
20299
20300void CheckCorrectThrow(const char* script) {
20301 // Test that the script, when wrapped into a try-catch, triggers the catch
20302 // clause due to failed access check throwing an exception.
20303 // The subsequent try-catch should run without any exception.
20304 access_check_fail_thrown = false;
20305 catch_callback_called = false;
20306 i::ScopedVector<char> source(1024);
20307 i::OS::SNPrintF(source, "try { %s; } catch (e) { catcher(e); }", script);
20308 CompileRun(source.start());
20309 CHECK(access_check_fail_thrown);
20310 CHECK(catch_callback_called);
20311
20312 access_check_fail_thrown = false;
20313 catch_callback_called = false;
20314 CompileRun("try { [1, 2, 3].sort(); } catch (e) { catcher(e) };");
20315 CHECK(!access_check_fail_thrown);
20316 CHECK(!catch_callback_called);
20317}
20318
20319
20320TEST(AccessCheckThrows) {
20321 i::FLAG_allow_natives_syntax = true;
20322 v8::V8::Initialize();
20323 v8::V8::SetFailedAccessCheckCallbackFunction(&FailedAccessCheckThrows);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020324 v8::HandleScope scope(CcTest::isolate());
danno@chromium.org169691d2013-07-15 08:01:13 +000020325
20326 // Create an ObjectTemplate for global objects and install access
20327 // check callbacks that will block access.
20328 v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
20329 global_template->SetAccessCheckCallbacks(NamedAccessAlwaysBlocked,
20330 IndexAccessAlwaysBlocked);
20331
20332 // Create a context and set an x property on it's global object.
20333 LocalContext context0(NULL, global_template);
20334 context0->Global()->Set(v8_str("x"), v8_num(42));
20335 v8::Handle<v8::Object> global0 = context0->Global();
20336
20337 // Create a context with a different security token so that the
20338 // failed access check callback will be called on each access.
20339 LocalContext context1(NULL, global_template);
20340 context1->Global()->Set(v8_str("other"), global0);
20341
20342 v8::Handle<v8::FunctionTemplate> catcher_fun =
20343 v8::FunctionTemplate::New(CatcherCallback);
20344 context1->Global()->Set(v8_str("catcher"), catcher_fun->GetFunction());
20345
20346 v8::Handle<v8::FunctionTemplate> has_own_property_fun =
20347 v8::FunctionTemplate::New(HasOwnPropertyCallback);
20348 context1->Global()->Set(v8_str("has_own_property"),
20349 has_own_property_fun->GetFunction());
20350
20351 { v8::TryCatch try_catch;
20352 access_check_fail_thrown = false;
20353 CompileRun("other.x;");
20354 CHECK(access_check_fail_thrown);
20355 CHECK(try_catch.HasCaught());
20356 }
20357
20358 CheckCorrectThrow("other.x");
20359 CheckCorrectThrow("other[1]");
20360 CheckCorrectThrow("JSON.stringify(other)");
20361 CheckCorrectThrow("has_own_property(other, 'x')");
20362 CheckCorrectThrow("%GetProperty(other, 'x')");
20363 CheckCorrectThrow("%SetProperty(other, 'x', 'foo', 1, 0)");
20364 CheckCorrectThrow("%IgnoreAttributesAndSetProperty(other, 'x', 'foo')");
20365 CheckCorrectThrow("%DeleteProperty(other, 'x', 0)");
20366 CheckCorrectThrow("%DeleteProperty(other, '1', 0)");
20367 CheckCorrectThrow("%HasLocalProperty(other, 'x')");
20368 CheckCorrectThrow("%HasProperty(other, 'x')");
20369 CheckCorrectThrow("%HasElement(other, 1)");
20370 CheckCorrectThrow("%IsPropertyEnumerable(other, 'x')");
20371 CheckCorrectThrow("%GetPropertyNames(other)");
20372 CheckCorrectThrow("%GetLocalPropertyNames(other, true)");
20373 CheckCorrectThrow("%DefineOrRedefineAccessorProperty("
20374 "other, 'x', null, null, 1)");
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +000020375
20376 // Reset the failed access check callback so it does not influence
20377 // the other tests.
20378 v8::V8::SetFailedAccessCheckCallbackFunction(NULL);
danno@chromium.org169691d2013-07-15 08:01:13 +000020379}
20380
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000020381
20382THREADED_TEST(Regress256330) {
20383 i::FLAG_allow_natives_syntax = true;
20384 LocalContext context;
20385 v8::HandleScope scope(context->GetIsolate());
20386 Handle<FunctionTemplate> templ = FunctionTemplate::New();
20387 AddInterceptor(templ, EmptyInterceptorGetter, EmptyInterceptorSetter);
20388 context->Global()->Set(v8_str("Bug"), templ->GetFunction());
20389 CompileRun("\"use strict\"; var o = new Bug;"
20390 "function f(o) { o.x = 10; };"
20391 "f(o); f(o); f(o);"
20392 "%OptimizeFunctionOnNextCall(f);"
20393 "f(o);");
20394 ExpectBoolean("%GetOptimizationStatus(f) != 2", true);
20395}
20396
20397
20398THREADED_TEST(CrankshaftInterceptorSetter) {
20399 i::FLAG_allow_natives_syntax = true;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020400 v8::HandleScope scope(CcTest::isolate());
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000020401 Handle<FunctionTemplate> templ = FunctionTemplate::New();
20402 AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
20403 LocalContext env;
20404 env->Global()->Set(v8_str("Obj"), templ->GetFunction());
20405 CompileRun("var obj = new Obj;"
20406 // Initialize fields to avoid transitions later.
20407 "obj.age = 0;"
20408 "obj.accessor_age = 42;"
20409 "function setter(i) { this.accessor_age = i; };"
20410 "function getter() { return this.accessor_age; };"
20411 "function setAge(i) { obj.age = i; };"
20412 "Object.defineProperty(obj, 'age', { get:getter, set:setter });"
20413 "setAge(1);"
20414 "setAge(2);"
20415 "setAge(3);"
20416 "%OptimizeFunctionOnNextCall(setAge);"
20417 "setAge(4);");
20418 // All stores went through the interceptor.
20419 ExpectInt32("obj.interceptor_age", 4);
20420 ExpectInt32("obj.accessor_age", 42);
20421}
20422
20423
20424THREADED_TEST(CrankshaftInterceptorGetter) {
20425 i::FLAG_allow_natives_syntax = true;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020426 v8::HandleScope scope(CcTest::isolate());
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000020427 Handle<FunctionTemplate> templ = FunctionTemplate::New();
20428 AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
20429 LocalContext env;
20430 env->Global()->Set(v8_str("Obj"), templ->GetFunction());
20431 CompileRun("var obj = new Obj;"
20432 // Initialize fields to avoid transitions later.
20433 "obj.age = 1;"
20434 "obj.accessor_age = 42;"
20435 "function getter() { return this.accessor_age; };"
20436 "function getAge() { return obj.interceptor_age; };"
20437 "Object.defineProperty(obj, 'interceptor_age', { get:getter });"
20438 "getAge();"
20439 "getAge();"
20440 "getAge();"
20441 "%OptimizeFunctionOnNextCall(getAge);");
20442 // Access through interceptor.
20443 ExpectInt32("getAge()", 1);
20444}
20445
20446
20447THREADED_TEST(CrankshaftInterceptorFieldRead) {
20448 i::FLAG_allow_natives_syntax = true;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020449 v8::HandleScope scope(CcTest::isolate());
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000020450 Handle<FunctionTemplate> templ = FunctionTemplate::New();
20451 AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
20452 LocalContext env;
20453 env->Global()->Set(v8_str("Obj"), templ->GetFunction());
20454 CompileRun("var obj = new Obj;"
20455 "obj.__proto__.interceptor_age = 42;"
20456 "obj.age = 100;"
20457 "function getAge() { return obj.interceptor_age; };");
20458 ExpectInt32("getAge();", 100);
20459 ExpectInt32("getAge();", 100);
20460 ExpectInt32("getAge();", 100);
20461 CompileRun("%OptimizeFunctionOnNextCall(getAge);");
20462 // Access through interceptor.
20463 ExpectInt32("getAge();", 100);
20464}
20465
20466
20467THREADED_TEST(CrankshaftInterceptorFieldWrite) {
20468 i::FLAG_allow_natives_syntax = true;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020469 v8::HandleScope scope(CcTest::isolate());
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000020470 Handle<FunctionTemplate> templ = FunctionTemplate::New();
20471 AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
20472 LocalContext env;
20473 env->Global()->Set(v8_str("Obj"), templ->GetFunction());
20474 CompileRun("var obj = new Obj;"
20475 "obj.age = 100000;"
20476 "function setAge(i) { obj.age = i };"
20477 "setAge(100);"
20478 "setAge(101);"
20479 "setAge(102);"
20480 "%OptimizeFunctionOnNextCall(setAge);"
20481 "setAge(103);");
20482 ExpectInt32("obj.age", 100000);
20483 ExpectInt32("obj.interceptor_age", 103);
20484}
20485
dslomov@chromium.org639bac02013-09-09 11:58:54 +000020486
verwaest@chromium.org662436e2013-08-28 08:41:27 +000020487#endif // V8_OS_POSIX
dslomov@chromium.org639bac02013-09-09 11:58:54 +000020488
20489
20490static Local<Value> function_new_expected_env;
20491static void FunctionNewCallback(const v8::FunctionCallbackInfo<Value>& info) {
20492 CHECK_EQ(function_new_expected_env, info.Data());
20493 info.GetReturnValue().Set(17);
20494}
20495
20496
20497THREADED_TEST(FunctionNew) {
20498 LocalContext env;
20499 v8::Isolate* isolate = env->GetIsolate();
20500 v8::HandleScope scope(isolate);
20501 Local<Object> data = v8::Object::New();
20502 function_new_expected_env = data;
20503 Local<Function> func = Function::New(isolate, FunctionNewCallback, data);
20504 env->Global()->Set(v8_str("func"), func);
20505 Local<Value> result = CompileRun("func();");
20506 CHECK_EQ(v8::Integer::New(17, isolate), result);
20507 // Verify function not cached
20508 int serial_number =
20509 i::Smi::cast(v8::Utils::OpenHandle(*func)
20510 ->shared()->get_api_func_data()->serial_number())->value();
20511 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
20512 i::Object* elm = i_isolate->native_context()->function_cache()
20513 ->GetElementNoExceptionThrown(i_isolate, serial_number);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020514 CHECK(elm->IsUndefined());
20515 // Verify that each Function::New creates a new function instance
20516 Local<Object> data2 = v8::Object::New();
20517 function_new_expected_env = data2;
20518 Local<Function> func2 = Function::New(isolate, FunctionNewCallback, data2);
20519 CHECK(!func2->IsNull());
20520 CHECK_NE(func, func2);
20521 env->Global()->Set(v8_str("func2"), func2);
20522 Local<Value> result2 = CompileRun("func2();");
20523 CHECK_EQ(v8::Integer::New(17, isolate), result2);
dslomov@chromium.org639bac02013-09-09 11:58:54 +000020524}
20525
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000020526
20527TEST(EscapeableHandleScope) {
20528 HandleScope outer_scope(CcTest::isolate());
20529 LocalContext context;
20530 const int runs = 10;
20531 Local<String> values[runs];
20532 for (int i = 0; i < runs; i++) {
20533 v8::EscapableHandleScope inner_scope(CcTest::isolate());
20534 Local<String> value;
20535 if (i != 0) value = v8_str("escape value");
20536 values[i] = inner_scope.Escape(value);
20537 }
20538 for (int i = 0; i < runs; i++) {
20539 Local<String> expected;
20540 if (i != 0) {
20541 CHECK_EQ(v8_str("escape value"), values[i]);
20542 } else {
20543 CHECK(values[i].IsEmpty());
20544 }
20545 }
20546}