blob: acc47b9c7663d3389004cc5c2212308cd063e493 [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
ager@chromium.org3811b432009-10-28 14:53:37 +000028#include <limits.h>
29
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000030#ifndef WIN32
31#include <signal.h> // kill
32#include <unistd.h> // getpid
33#endif // WIN32
34
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000035#include "v8.h"
36
37#include "api.h"
lrn@chromium.org1c092762011-05-09 09:42:16 +000038#include "isolate.h"
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +000039#include "compilation-cache.h"
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000040#include "execution.h"
verwaest@chromium.org753aee42012-07-17 16:15:42 +000041#include "objects.h"
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000042#include "snapshot.h"
43#include "platform.h"
ager@chromium.org3811b432009-10-28 14:53:37 +000044#include "utils.h"
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000045#include "cctest.h"
ager@chromium.org5b2fbee2010-09-08 06:38:15 +000046#include "parser.h"
erik.corry@gmail.com4a6c3272010-11-18 12:04:40 +000047#include "unicode-inl.h"
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000048
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +000049static const bool kLogThreading = false;
ager@chromium.orgc4c92722009-11-18 14:12:51 +000050
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000051using ::v8::AccessorInfo;
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000052using ::v8::Arguments;
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +000053using ::v8::Context;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000054using ::v8::Extension;
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +000055using ::v8::Function;
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000056using ::v8::FunctionTemplate;
57using ::v8::Handle;
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +000058using ::v8::HandleScope;
59using ::v8::Local;
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000060using ::v8::Message;
61using ::v8::MessageCallback;
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +000062using ::v8::Object;
63using ::v8::ObjectTemplate;
64using ::v8::Persistent;
65using ::v8::Script;
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000066using ::v8::StackTrace;
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +000067using ::v8::String;
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000068using ::v8::TryCatch;
69using ::v8::Undefined;
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +000070using ::v8::V8;
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000071using ::v8::Value;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000072
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000073
kasperl@chromium.orgeac059f2010-01-25 11:02:06 +000074static void ExpectString(const char* code, const char* expected) {
75 Local<Value> result = CompileRun(code);
76 CHECK(result->IsString());
77 String::AsciiValue ascii(result);
78 CHECK_EQ(expected, *ascii);
79}
80
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000081static void ExpectInt32(const char* code, int expected) {
82 Local<Value> result = CompileRun(code);
83 CHECK(result->IsInt32());
84 CHECK_EQ(expected, result->Int32Value());
85}
kasperl@chromium.orgeac059f2010-01-25 11:02:06 +000086
87static void ExpectBoolean(const char* code, bool expected) {
88 Local<Value> result = CompileRun(code);
89 CHECK(result->IsBoolean());
90 CHECK_EQ(expected, result->BooleanValue());
91}
92
93
kmillikin@chromium.org9155e252010-05-26 13:27:57 +000094static void ExpectTrue(const char* code) {
95 ExpectBoolean(code, true);
96}
97
98
ager@chromium.orgea4f62e2010-08-16 16:28:43 +000099static void ExpectFalse(const char* code) {
100 ExpectBoolean(code, false);
101}
102
103
kasperl@chromium.orgeac059f2010-01-25 11:02:06 +0000104static void ExpectObject(const char* code, Local<Value> expected) {
105 Local<Value> result = CompileRun(code);
106 CHECK(result->Equals(expected));
107}
108
109
ager@chromium.orgea4f62e2010-08-16 16:28:43 +0000110static void ExpectUndefined(const char* code) {
111 Local<Value> result = CompileRun(code);
112 CHECK(result->IsUndefined());
113}
114
115
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000116static int signature_callback_count;
117static v8::Handle<Value> IncrementingSignatureCallback(
118 const v8::Arguments& args) {
119 ApiTestFuzzer::Fuzz();
120 signature_callback_count++;
121 v8::Handle<v8::Array> result = v8::Array::New(args.Length());
122 for (int i = 0; i < args.Length(); i++)
123 result->Set(v8::Integer::New(i), args[i]);
124 return result;
125}
126
127
128static v8::Handle<Value> SignatureCallback(const v8::Arguments& args) {
129 ApiTestFuzzer::Fuzz();
130 v8::Handle<v8::Array> result = v8::Array::New(args.Length());
131 for (int i = 0; i < args.Length(); i++) {
132 result->Set(v8::Integer::New(i), args[i]);
133 }
134 return result;
135}
136
137
138THREADED_TEST(Handles) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000139 v8::HandleScope scope(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000140 Local<Context> local_env;
141 {
142 LocalContext env;
143 local_env = env.local();
144 }
145
146 // Local context should still be live.
147 CHECK(!local_env.IsEmpty());
148 local_env->Enter();
149
150 v8::Handle<v8::Primitive> undef = v8::Undefined();
151 CHECK(!undef.IsEmpty());
152 CHECK(undef->IsUndefined());
153
154 const char* c_source = "1 + 2 + 3";
155 Local<String> source = String::New(c_source);
156 Local<Script> script = Script::Compile(source);
157 CHECK_EQ(6, script->Run()->Int32Value());
158
159 local_env->Exit();
160}
161
162
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000163THREADED_TEST(IsolateOfContext) {
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000164 v8::Persistent<Context> env = Context::New();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000165 v8::HandleScope scope(env->GetIsolate());
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000166
167 CHECK(!env->InContext());
168 CHECK(env->GetIsolate() == v8::Isolate::GetCurrent());
169 env->Enter();
170 CHECK(env->InContext());
171 CHECK(env->GetIsolate() == v8::Isolate::GetCurrent());
172 env->Exit();
173 CHECK(!env->InContext());
174 CHECK(env->GetIsolate() == v8::Isolate::GetCurrent());
175
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +0000176 env.Dispose(env->GetIsolate());
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000177}
178
179
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000180THREADED_TEST(ReceiverSignature) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000181 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000182 v8::HandleScope scope(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000183 v8::Handle<v8::FunctionTemplate> fun = v8::FunctionTemplate::New();
184 v8::Handle<v8::Signature> sig = v8::Signature::New(fun);
185 fun->PrototypeTemplate()->Set(
186 v8_str("m"),
187 v8::FunctionTemplate::New(IncrementingSignatureCallback,
188 v8::Handle<Value>(),
189 sig));
190 env->Global()->Set(v8_str("Fun"), fun->GetFunction());
191 signature_callback_count = 0;
192 CompileRun(
193 "var o = new Fun();"
194 "o.m();");
195 CHECK_EQ(1, signature_callback_count);
196 v8::Handle<v8::FunctionTemplate> sub_fun = v8::FunctionTemplate::New();
197 sub_fun->Inherit(fun);
198 env->Global()->Set(v8_str("SubFun"), sub_fun->GetFunction());
199 CompileRun(
200 "var o = new SubFun();"
201 "o.m();");
202 CHECK_EQ(2, signature_callback_count);
203
204 v8::TryCatch try_catch;
205 CompileRun(
206 "var o = { };"
207 "o.m = Fun.prototype.m;"
208 "o.m();");
209 CHECK_EQ(2, signature_callback_count);
210 CHECK(try_catch.HasCaught());
211 try_catch.Reset();
212 v8::Handle<v8::FunctionTemplate> unrel_fun = v8::FunctionTemplate::New();
213 sub_fun->Inherit(fun);
214 env->Global()->Set(v8_str("UnrelFun"), unrel_fun->GetFunction());
215 CompileRun(
216 "var o = new UnrelFun();"
217 "o.m = Fun.prototype.m;"
218 "o.m();");
219 CHECK_EQ(2, signature_callback_count);
220 CHECK(try_catch.HasCaught());
221}
222
223
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000224THREADED_TEST(ArgumentSignature) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000225 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000226 v8::HandleScope scope(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000227 v8::Handle<v8::FunctionTemplate> cons = v8::FunctionTemplate::New();
228 cons->SetClassName(v8_str("Cons"));
229 v8::Handle<v8::Signature> sig =
230 v8::Signature::New(v8::Handle<v8::FunctionTemplate>(), 1, &cons);
231 v8::Handle<v8::FunctionTemplate> fun =
232 v8::FunctionTemplate::New(SignatureCallback, v8::Handle<Value>(), sig);
233 env->Global()->Set(v8_str("Cons"), cons->GetFunction());
234 env->Global()->Set(v8_str("Fun1"), fun->GetFunction());
235
236 v8::Handle<Value> value1 = CompileRun("Fun1(4) == '';");
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000237 CHECK(value1->IsTrue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000238
239 v8::Handle<Value> value2 = CompileRun("Fun1(new Cons()) == '[object Cons]';");
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000240 CHECK(value2->IsTrue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000241
242 v8::Handle<Value> value3 = CompileRun("Fun1() == '';");
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000243 CHECK(value3->IsTrue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000244
245 v8::Handle<v8::FunctionTemplate> cons1 = v8::FunctionTemplate::New();
246 cons1->SetClassName(v8_str("Cons1"));
247 v8::Handle<v8::FunctionTemplate> cons2 = v8::FunctionTemplate::New();
248 cons2->SetClassName(v8_str("Cons2"));
249 v8::Handle<v8::FunctionTemplate> cons3 = v8::FunctionTemplate::New();
250 cons3->SetClassName(v8_str("Cons3"));
251
252 v8::Handle<v8::FunctionTemplate> args[3] = { cons1, cons2, cons3 };
253 v8::Handle<v8::Signature> wsig =
254 v8::Signature::New(v8::Handle<v8::FunctionTemplate>(), 3, args);
255 v8::Handle<v8::FunctionTemplate> fun2 =
256 v8::FunctionTemplate::New(SignatureCallback, v8::Handle<Value>(), wsig);
257
258 env->Global()->Set(v8_str("Cons1"), cons1->GetFunction());
259 env->Global()->Set(v8_str("Cons2"), cons2->GetFunction());
260 env->Global()->Set(v8_str("Cons3"), cons3->GetFunction());
261 env->Global()->Set(v8_str("Fun2"), fun2->GetFunction());
262 v8::Handle<Value> value4 = CompileRun(
263 "Fun2(new Cons1(), new Cons2(), new Cons3()) =="
264 "'[object Cons1],[object Cons2],[object Cons3]'");
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000265 CHECK(value4->IsTrue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000266
267 v8::Handle<Value> value5 = CompileRun(
268 "Fun2(new Cons1(), new Cons2(), 5) == '[object Cons1],[object Cons2],'");
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000269 CHECK(value5->IsTrue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000270
271 v8::Handle<Value> value6 = CompileRun(
272 "Fun2(new Cons3(), new Cons2(), new Cons1()) == ',[object Cons2],'");
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000273 CHECK(value6->IsTrue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000274
275 v8::Handle<Value> value7 = CompileRun(
276 "Fun2(new Cons1(), new Cons2(), new Cons3(), 'd') == "
277 "'[object Cons1],[object Cons2],[object Cons3],d';");
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000278 CHECK(value7->IsTrue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000279
280 v8::Handle<Value> value8 = CompileRun(
281 "Fun2(new Cons1(), new Cons2()) == '[object Cons1],[object Cons2]'");
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000282 CHECK(value8->IsTrue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000283}
284
285
286THREADED_TEST(HulIgennem) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000287 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000288 v8::HandleScope scope(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000289 v8::Handle<v8::Primitive> undef = v8::Undefined();
290 Local<String> undef_str = undef->ToString();
291 char* value = i::NewArray<char>(undef_str->Length() + 1);
292 undef_str->WriteAscii(value);
293 CHECK_EQ(0, strcmp(value, "undefined"));
294 i::DeleteArray(value);
295}
296
297
298THREADED_TEST(Access) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000299 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000300 v8::HandleScope scope(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000301 Local<v8::Object> obj = v8::Object::New();
302 Local<Value> foo_before = obj->Get(v8_str("foo"));
303 CHECK(foo_before->IsUndefined());
304 Local<String> bar_str = v8_str("bar");
305 obj->Set(v8_str("foo"), bar_str);
306 Local<Value> foo_after = obj->Get(v8_str("foo"));
307 CHECK(!foo_after->IsUndefined());
308 CHECK(foo_after->IsString());
309 CHECK_EQ(bar_str, foo_after);
310}
311
312
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000313THREADED_TEST(AccessElement) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000314 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000315 v8::HandleScope scope(env->GetIsolate());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000316 Local<v8::Object> obj = v8::Object::New();
317 Local<Value> before = obj->Get(1);
318 CHECK(before->IsUndefined());
319 Local<String> bar_str = v8_str("bar");
320 obj->Set(1, bar_str);
321 Local<Value> after = obj->Get(1);
322 CHECK(!after->IsUndefined());
323 CHECK(after->IsString());
324 CHECK_EQ(bar_str, after);
325
326 Local<v8::Array> value = CompileRun("[\"a\", \"b\"]").As<v8::Array>();
327 CHECK_EQ(v8_str("a"), value->Get(0));
328 CHECK_EQ(v8_str("b"), value->Get(1));
329}
330
331
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000332THREADED_TEST(Script) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000333 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000334 v8::HandleScope scope(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000335 const char* c_source = "1 + 2 + 3";
336 Local<String> source = String::New(c_source);
337 Local<Script> script = Script::Compile(source);
338 CHECK_EQ(6, script->Run()->Int32Value());
339}
340
341
342static uint16_t* AsciiToTwoByteString(const char* source) {
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000343 int array_length = i::StrLength(source) + 1;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000344 uint16_t* converted = i::NewArray<uint16_t>(array_length);
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000345 for (int i = 0; i < array_length; i++) converted[i] = source[i];
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000346 return converted;
347}
348
349
350class TestResource: public String::ExternalStringResource {
351 public:
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000352 explicit TestResource(uint16_t* data, int* counter = NULL)
353 : data_(data), length_(0), counter_(counter) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000354 while (data[length_]) ++length_;
355 }
356
357 ~TestResource() {
358 i::DeleteArray(data_);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000359 if (counter_ != NULL) ++*counter_;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000360 }
361
362 const uint16_t* data() const {
363 return data_;
364 }
365
366 size_t length() const {
367 return length_;
368 }
369 private:
370 uint16_t* data_;
371 size_t length_;
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000372 int* counter_;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000373};
374
375
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000376class TestAsciiResource: public String::ExternalAsciiStringResource {
377 public:
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000378 explicit TestAsciiResource(const char* data, int* counter = NULL)
379 : data_(data), length_(strlen(data)), counter_(counter) { }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000380
381 ~TestAsciiResource() {
382 i::DeleteArray(data_);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000383 if (counter_ != NULL) ++*counter_;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000384 }
385
386 const char* data() const {
387 return data_;
388 }
389
390 size_t length() const {
391 return length_;
392 }
393 private:
ager@chromium.org5ec48922009-05-05 07:25:34 +0000394 const char* data_;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000395 size_t length_;
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000396 int* counter_;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000397};
398
399
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000400THREADED_TEST(ScriptUsingStringResource) {
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000401 int dispose_count = 0;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000402 const char* c_source = "1 + 2 * 3";
403 uint16_t* two_byte_source = AsciiToTwoByteString(c_source);
404 {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000405 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000406 v8::HandleScope scope(env->GetIsolate());
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000407 TestResource* resource = new TestResource(two_byte_source, &dispose_count);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000408 Local<String> source = String::NewExternal(resource);
409 Local<Script> script = Script::Compile(source);
410 Local<Value> value = script->Run();
411 CHECK(value->IsNumber());
412 CHECK_EQ(7, value->Int32Value());
413 CHECK(source->IsExternal());
414 CHECK_EQ(resource,
415 static_cast<TestResource*>(source->GetExternalStringResource()));
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000416 String::Encoding encoding = String::UNKNOWN_ENCODING;
417 CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
418 source->GetExternalStringResourceBase(&encoding));
419 CHECK_EQ(String::TWO_BYTE_ENCODING, encoding);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000420 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000421 CHECK_EQ(0, dispose_count);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000422 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000423 v8::internal::Isolate::Current()->compilation_cache()->Clear();
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000424 HEAP->CollectAllAvailableGarbage();
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000425 CHECK_EQ(1, dispose_count);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000426}
427
428
429THREADED_TEST(ScriptUsingAsciiStringResource) {
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000430 int dispose_count = 0;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000431 const char* c_source = "1 + 2 * 3";
432 {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000433 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000434 v8::HandleScope scope(env->GetIsolate());
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000435 TestAsciiResource* resource = new TestAsciiResource(i::StrDup(c_source),
436 &dispose_count);
437 Local<String> source = String::NewExternal(resource);
438 CHECK(source->IsExternalAscii());
439 CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
440 source->GetExternalAsciiStringResource());
441 String::Encoding encoding = String::UNKNOWN_ENCODING;
442 CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
443 source->GetExternalStringResourceBase(&encoding));
444 CHECK_EQ(String::ASCII_ENCODING, encoding);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000445 Local<Script> script = Script::Compile(source);
446 Local<Value> value = script->Run();
447 CHECK(value->IsNumber());
448 CHECK_EQ(7, value->Int32Value());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000449 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000450 CHECK_EQ(0, dispose_count);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000451 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000452 i::Isolate::Current()->compilation_cache()->Clear();
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000453 HEAP->CollectAllAvailableGarbage();
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000454 CHECK_EQ(1, dispose_count);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000455}
456
457
ager@chromium.org6f10e412009-02-13 10:11:16 +0000458THREADED_TEST(ScriptMakingExternalString) {
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000459 int dispose_count = 0;
ager@chromium.org6f10e412009-02-13 10:11:16 +0000460 uint16_t* two_byte_source = AsciiToTwoByteString("1 + 2 * 3");
461 {
ager@chromium.org6f10e412009-02-13 10:11:16 +0000462 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000463 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org6f10e412009-02-13 10:11:16 +0000464 Local<String> source = String::New(two_byte_source);
ager@chromium.org5c838252010-02-19 08:53:10 +0000465 // Trigger GCs so that the newly allocated string moves to old gen.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000466 HEAP->CollectGarbage(i::NEW_SPACE); // in survivor space now
467 HEAP->CollectGarbage(i::NEW_SPACE); // in old gen now
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000468 CHECK_EQ(source->IsExternal(), false);
469 CHECK_EQ(source->IsExternalAscii(), false);
470 String::Encoding encoding = String::UNKNOWN_ENCODING;
471 CHECK_EQ(NULL, source->GetExternalStringResourceBase(&encoding));
472 CHECK_EQ(String::ASCII_ENCODING, encoding);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000473 bool success = source->MakeExternal(new TestResource(two_byte_source,
474 &dispose_count));
ager@chromium.org6f10e412009-02-13 10:11:16 +0000475 CHECK(success);
476 Local<Script> script = Script::Compile(source);
477 Local<Value> value = script->Run();
478 CHECK(value->IsNumber());
479 CHECK_EQ(7, value->Int32Value());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000480 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000481 CHECK_EQ(0, dispose_count);
ager@chromium.org6f10e412009-02-13 10:11:16 +0000482 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000483 i::Isolate::Current()->compilation_cache()->Clear();
erik.corry@gmail.combbceb572012-03-09 10:52:05 +0000484 HEAP->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000485 CHECK_EQ(1, dispose_count);
ager@chromium.org6f10e412009-02-13 10:11:16 +0000486}
487
488
489THREADED_TEST(ScriptMakingExternalAsciiString) {
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000490 int dispose_count = 0;
ager@chromium.org6f10e412009-02-13 10:11:16 +0000491 const char* c_source = "1 + 2 * 3";
492 {
ager@chromium.org6f10e412009-02-13 10:11:16 +0000493 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000494 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org6f10e412009-02-13 10:11:16 +0000495 Local<String> source = v8_str(c_source);
ager@chromium.org5c838252010-02-19 08:53:10 +0000496 // Trigger GCs so that the newly allocated string moves to old gen.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000497 HEAP->CollectGarbage(i::NEW_SPACE); // in survivor space now
498 HEAP->CollectGarbage(i::NEW_SPACE); // in old gen now
ager@chromium.org6f10e412009-02-13 10:11:16 +0000499 bool success = source->MakeExternal(
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000500 new TestAsciiResource(i::StrDup(c_source), &dispose_count));
ager@chromium.org6f10e412009-02-13 10:11:16 +0000501 CHECK(success);
502 Local<Script> script = Script::Compile(source);
503 Local<Value> value = script->Run();
504 CHECK(value->IsNumber());
505 CHECK_EQ(7, value->Int32Value());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000506 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000507 CHECK_EQ(0, dispose_count);
ager@chromium.org6f10e412009-02-13 10:11:16 +0000508 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000509 i::Isolate::Current()->compilation_cache()->Clear();
erik.corry@gmail.combbceb572012-03-09 10:52:05 +0000510 HEAP->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000511 CHECK_EQ(1, dispose_count);
ager@chromium.org6f10e412009-02-13 10:11:16 +0000512}
513
514
ager@chromium.org5c838252010-02-19 08:53:10 +0000515TEST(MakingExternalStringConditions) {
ager@chromium.org5c838252010-02-19 08:53:10 +0000516 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000517 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org5c838252010-02-19 08:53:10 +0000518
519 // Free some space in the new space so that we can check freshness.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000520 HEAP->CollectGarbage(i::NEW_SPACE);
521 HEAP->CollectGarbage(i::NEW_SPACE);
ager@chromium.org5c838252010-02-19 08:53:10 +0000522
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000523 uint16_t* two_byte_string = AsciiToTwoByteString("s1");
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000524 Local<String> small_string = String::New(two_byte_string);
525 i::DeleteArray(two_byte_string);
526
ager@chromium.org5c838252010-02-19 08:53:10 +0000527 // We should refuse to externalize newly created small string.
528 CHECK(!small_string->CanMakeExternal());
529 // Trigger GCs so that the newly allocated string moves to old gen.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000530 HEAP->CollectGarbage(i::NEW_SPACE); // in survivor space now
531 HEAP->CollectGarbage(i::NEW_SPACE); // in old gen now
ager@chromium.org5c838252010-02-19 08:53:10 +0000532 // Old space strings should be accepted.
533 CHECK(small_string->CanMakeExternal());
534
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000535 two_byte_string = AsciiToTwoByteString("small string 2");
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000536 small_string = String::New(two_byte_string);
537 i::DeleteArray(two_byte_string);
538
ager@chromium.org5c838252010-02-19 08:53:10 +0000539 // We should refuse externalizing newly created small string.
540 CHECK(!small_string->CanMakeExternal());
541 for (int i = 0; i < 100; i++) {
542 String::Value value(small_string);
543 }
544 // Frequently used strings should be accepted.
545 CHECK(small_string->CanMakeExternal());
546
547 const int buf_size = 10 * 1024;
548 char* buf = i::NewArray<char>(buf_size);
549 memset(buf, 'a', buf_size);
550 buf[buf_size - 1] = '\0';
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000551
552 two_byte_string = AsciiToTwoByteString(buf);
553 Local<String> large_string = String::New(two_byte_string);
ager@chromium.org5c838252010-02-19 08:53:10 +0000554 i::DeleteArray(buf);
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000555 i::DeleteArray(two_byte_string);
ager@chromium.org5c838252010-02-19 08:53:10 +0000556 // Large strings should be immediately accepted.
557 CHECK(large_string->CanMakeExternal());
558}
559
560
561TEST(MakingExternalAsciiStringConditions) {
ager@chromium.org5c838252010-02-19 08:53:10 +0000562 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000563 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org5c838252010-02-19 08:53:10 +0000564
565 // Free some space in the new space so that we can check freshness.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000566 HEAP->CollectGarbage(i::NEW_SPACE);
567 HEAP->CollectGarbage(i::NEW_SPACE);
ager@chromium.org5c838252010-02-19 08:53:10 +0000568
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000569 Local<String> small_string = String::New("s1");
ager@chromium.org5c838252010-02-19 08:53:10 +0000570 // We should refuse to externalize newly created small string.
571 CHECK(!small_string->CanMakeExternal());
572 // Trigger GCs so that the newly allocated string moves to old gen.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000573 HEAP->CollectGarbage(i::NEW_SPACE); // in survivor space now
574 HEAP->CollectGarbage(i::NEW_SPACE); // in old gen now
ager@chromium.org5c838252010-02-19 08:53:10 +0000575 // Old space strings should be accepted.
576 CHECK(small_string->CanMakeExternal());
577
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000578 small_string = String::New("small string 2");
ager@chromium.org5c838252010-02-19 08:53:10 +0000579 // We should refuse externalizing newly created small string.
580 CHECK(!small_string->CanMakeExternal());
581 for (int i = 0; i < 100; i++) {
582 String::Value value(small_string);
583 }
584 // Frequently used strings should be accepted.
585 CHECK(small_string->CanMakeExternal());
586
587 const int buf_size = 10 * 1024;
588 char* buf = i::NewArray<char>(buf_size);
589 memset(buf, 'a', buf_size);
590 buf[buf_size - 1] = '\0';
591 Local<String> large_string = String::New(buf);
592 i::DeleteArray(buf);
593 // Large strings should be immediately accepted.
594 CHECK(large_string->CanMakeExternal());
595}
596
597
ager@chromium.org6f10e412009-02-13 10:11:16 +0000598THREADED_TEST(UsingExternalString) {
ager@chromium.orge2902be2009-06-08 12:21:35 +0000599 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000600 v8::HandleScope scope(v8::Isolate::GetCurrent());
ager@chromium.orge2902be2009-06-08 12:21:35 +0000601 uint16_t* two_byte_string = AsciiToTwoByteString("test string");
602 Local<String> string =
603 String::NewExternal(new TestResource(two_byte_string));
604 i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
605 // Trigger GCs so that the newly allocated string moves to old gen.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000606 HEAP->CollectGarbage(i::NEW_SPACE); // in survivor space now
607 HEAP->CollectGarbage(i::NEW_SPACE); // in old gen now
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000608 i::Handle<i::String> isymbol =
609 FACTORY->InternalizedStringFromString(istring);
610 CHECK(isymbol->IsInternalizedString());
ager@chromium.orge2902be2009-06-08 12:21:35 +0000611 }
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000612 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
613 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org6f10e412009-02-13 10:11:16 +0000614}
615
616
617THREADED_TEST(UsingExternalAsciiString) {
ager@chromium.orge2902be2009-06-08 12:21:35 +0000618 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000619 v8::HandleScope scope(v8::Isolate::GetCurrent());
ager@chromium.orge2902be2009-06-08 12:21:35 +0000620 const char* one_byte_string = "test string";
621 Local<String> string = String::NewExternal(
622 new TestAsciiResource(i::StrDup(one_byte_string)));
623 i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
624 // Trigger GCs so that the newly allocated string moves to old gen.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000625 HEAP->CollectGarbage(i::NEW_SPACE); // in survivor space now
626 HEAP->CollectGarbage(i::NEW_SPACE); // in old gen now
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000627 i::Handle<i::String> isymbol =
628 FACTORY->InternalizedStringFromString(istring);
629 CHECK(isymbol->IsInternalizedString());
ager@chromium.orge2902be2009-06-08 12:21:35 +0000630 }
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000631 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
632 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org6f10e412009-02-13 10:11:16 +0000633}
634
635
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000636THREADED_TEST(ScavengeExternalString) {
svenpanne@chromium.org83130cf2012-11-30 10:13:25 +0000637 i::FLAG_stress_compaction = false;
638 i::FLAG_gc_global = false;
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000639 int dispose_count = 0;
lrn@chromium.orgc34f5802010-04-28 12:53:43 +0000640 bool in_new_space = false;
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000641 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000642 v8::HandleScope scope(v8::Isolate::GetCurrent());
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000643 uint16_t* two_byte_string = AsciiToTwoByteString("test string");
644 Local<String> string =
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000645 String::NewExternal(new TestResource(two_byte_string,
646 &dispose_count));
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000647 i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000648 HEAP->CollectGarbage(i::NEW_SPACE);
649 in_new_space = HEAP->InNewSpace(*istring);
650 CHECK(in_new_space || HEAP->old_data_space()->Contains(*istring));
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000651 CHECK_EQ(0, dispose_count);
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000652 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000653 HEAP->CollectGarbage(in_new_space ? i::NEW_SPACE : i::OLD_DATA_SPACE);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000654 CHECK_EQ(1, dispose_count);
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000655}
656
657
658THREADED_TEST(ScavengeExternalAsciiString) {
svenpanne@chromium.org83130cf2012-11-30 10:13:25 +0000659 i::FLAG_stress_compaction = false;
660 i::FLAG_gc_global = false;
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000661 int dispose_count = 0;
lrn@chromium.orgc34f5802010-04-28 12:53:43 +0000662 bool in_new_space = false;
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000663 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000664 v8::HandleScope scope(v8::Isolate::GetCurrent());
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000665 const char* one_byte_string = "test string";
666 Local<String> string = String::NewExternal(
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000667 new TestAsciiResource(i::StrDup(one_byte_string), &dispose_count));
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000668 i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000669 HEAP->CollectGarbage(i::NEW_SPACE);
670 in_new_space = HEAP->InNewSpace(*istring);
671 CHECK(in_new_space || HEAP->old_data_space()->Contains(*istring));
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000672 CHECK_EQ(0, dispose_count);
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000673 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000674 HEAP->CollectGarbage(in_new_space ? i::NEW_SPACE : i::OLD_DATA_SPACE);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000675 CHECK_EQ(1, dispose_count);
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000676}
677
678
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000679class TestAsciiResourceWithDisposeControl: public TestAsciiResource {
680 public:
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000681 // Only used by non-threaded tests, so it can use static fields.
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000682 static int dispose_calls;
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000683 static int dispose_count;
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000684
685 TestAsciiResourceWithDisposeControl(const char* data, bool dispose)
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000686 : TestAsciiResource(data, &dispose_count),
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000687 dispose_(dispose) { }
688
689 void Dispose() {
690 ++dispose_calls;
691 if (dispose_) delete this;
692 }
693 private:
694 bool dispose_;
695};
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000696
697
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000698int TestAsciiResourceWithDisposeControl::dispose_count = 0;
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000699int TestAsciiResourceWithDisposeControl::dispose_calls = 0;
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000700
701
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000702TEST(ExternalStringWithDisposeHandling) {
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000703 const char* c_source = "1 + 2 * 3";
704
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000705 // Use a stack allocated external string resource allocated object.
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000706 TestAsciiResourceWithDisposeControl::dispose_count = 0;
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000707 TestAsciiResourceWithDisposeControl::dispose_calls = 0;
708 TestAsciiResourceWithDisposeControl res_stack(i::StrDup(c_source), false);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000709 {
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000710 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000711 v8::HandleScope scope(env->GetIsolate());
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000712 Local<String> source = String::NewExternal(&res_stack);
713 Local<Script> script = Script::Compile(source);
714 Local<Value> value = script->Run();
715 CHECK(value->IsNumber());
716 CHECK_EQ(7, value->Int32Value());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000717 HEAP->CollectAllAvailableGarbage();
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000718 CHECK_EQ(0, TestAsciiResourceWithDisposeControl::dispose_count);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000719 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000720 i::Isolate::Current()->compilation_cache()->Clear();
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000721 HEAP->CollectAllAvailableGarbage();
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000722 CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_calls);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000723 CHECK_EQ(0, TestAsciiResourceWithDisposeControl::dispose_count);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000724
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000725 // Use a heap allocated external string resource allocated object.
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000726 TestAsciiResourceWithDisposeControl::dispose_count = 0;
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000727 TestAsciiResourceWithDisposeControl::dispose_calls = 0;
728 TestAsciiResource* res_heap =
729 new TestAsciiResourceWithDisposeControl(i::StrDup(c_source), true);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000730 {
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000731 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000732 v8::HandleScope scope(env->GetIsolate());
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000733 Local<String> source = String::NewExternal(res_heap);
734 Local<Script> script = Script::Compile(source);
735 Local<Value> value = script->Run();
736 CHECK(value->IsNumber());
737 CHECK_EQ(7, value->Int32Value());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000738 HEAP->CollectAllAvailableGarbage();
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000739 CHECK_EQ(0, TestAsciiResourceWithDisposeControl::dispose_count);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000740 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000741 i::Isolate::Current()->compilation_cache()->Clear();
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000742 HEAP->CollectAllAvailableGarbage();
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000743 CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_calls);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000744 CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_count);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000745}
746
747
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000748THREADED_TEST(StringConcat) {
749 {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000750 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000751 v8::HandleScope scope(env->GetIsolate());
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000752 const char* one_byte_string_1 = "function a_times_t";
753 const char* two_byte_string_1 = "wo_plus_b(a, b) {return ";
754 const char* one_byte_extern_1 = "a * 2 + b;} a_times_two_plus_b(4, 8) + ";
755 const char* two_byte_extern_1 = "a_times_two_plus_b(4, 8) + ";
756 const char* one_byte_string_2 = "a_times_two_plus_b(4, 8) + ";
757 const char* two_byte_string_2 = "a_times_two_plus_b(4, 8) + ";
758 const char* two_byte_extern_2 = "a_times_two_plus_b(1, 2);";
759 Local<String> left = v8_str(one_byte_string_1);
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000760
761 uint16_t* two_byte_source = AsciiToTwoByteString(two_byte_string_1);
762 Local<String> right = String::New(two_byte_source);
763 i::DeleteArray(two_byte_source);
764
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000765 Local<String> source = String::Concat(left, right);
766 right = String::NewExternal(
767 new TestAsciiResource(i::StrDup(one_byte_extern_1)));
768 source = String::Concat(source, right);
769 right = String::NewExternal(
770 new TestResource(AsciiToTwoByteString(two_byte_extern_1)));
771 source = String::Concat(source, right);
772 right = v8_str(one_byte_string_2);
773 source = String::Concat(source, right);
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000774
775 two_byte_source = AsciiToTwoByteString(two_byte_string_2);
776 right = String::New(two_byte_source);
777 i::DeleteArray(two_byte_source);
778
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000779 source = String::Concat(source, right);
780 right = String::NewExternal(
781 new TestResource(AsciiToTwoByteString(two_byte_extern_2)));
782 source = String::Concat(source, right);
783 Local<Script> script = Script::Compile(source);
784 Local<Value> value = script->Run();
785 CHECK(value->IsNumber());
786 CHECK_EQ(68, value->Int32Value());
787 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000788 i::Isolate::Current()->compilation_cache()->Clear();
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000789 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
790 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000791}
792
793
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000794THREADED_TEST(GlobalProperties) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000795 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000796 v8::HandleScope scope(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000797 v8::Handle<v8::Object> global = env->Global();
798 global->Set(v8_str("pi"), v8_num(3.1415926));
799 Local<Value> pi = global->Get(v8_str("pi"));
800 CHECK_EQ(3.1415926, pi->NumberValue());
801}
802
803
804static v8::Handle<Value> handle_call(const v8::Arguments& args) {
805 ApiTestFuzzer::Fuzz();
806 return v8_num(102);
807}
808
809
810static v8::Handle<Value> construct_call(const v8::Arguments& args) {
811 ApiTestFuzzer::Fuzz();
812 args.This()->Set(v8_str("x"), v8_num(1));
813 args.This()->Set(v8_str("y"), v8_num(2));
814 return args.This();
815}
816
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000817static v8::Handle<Value> Return239(Local<String> name, const AccessorInfo&) {
818 ApiTestFuzzer::Fuzz();
819 return v8_num(239);
820}
821
822
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000823THREADED_TEST(FunctionTemplate) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000824 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000825 v8::HandleScope scope(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000826 {
827 Local<v8::FunctionTemplate> fun_templ =
828 v8::FunctionTemplate::New(handle_call);
829 Local<Function> fun = fun_templ->GetFunction();
830 env->Global()->Set(v8_str("obj"), fun);
831 Local<Script> script = v8_compile("obj()");
832 CHECK_EQ(102, script->Run()->Int32Value());
833 }
834 // Use SetCallHandler to initialize a function template, should work like the
835 // previous one.
836 {
837 Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
838 fun_templ->SetCallHandler(handle_call);
839 Local<Function> fun = fun_templ->GetFunction();
840 env->Global()->Set(v8_str("obj"), fun);
841 Local<Script> script = v8_compile("obj()");
842 CHECK_EQ(102, script->Run()->Int32Value());
843 }
844 // Test constructor calls.
845 {
846 Local<v8::FunctionTemplate> fun_templ =
847 v8::FunctionTemplate::New(construct_call);
848 fun_templ->SetClassName(v8_str("funky"));
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000849 fun_templ->InstanceTemplate()->SetAccessor(v8_str("m"), Return239);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000850 Local<Function> fun = fun_templ->GetFunction();
851 env->Global()->Set(v8_str("obj"), fun);
852 Local<Script> script = v8_compile("var s = new obj(); s.x");
853 CHECK_EQ(1, script->Run()->Int32Value());
854
855 Local<Value> result = v8_compile("(new obj()).toString()")->Run();
856 CHECK_EQ(v8_str("[object funky]"), result);
ager@chromium.orgb61a0d12010-10-13 08:35:23 +0000857
858 result = v8_compile("(new obj()).m")->Run();
859 CHECK_EQ(239, result->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000860 }
861}
862
863
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000864THREADED_TEST(FunctionTemplateSetLength) {
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000865 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000866 v8::HandleScope scope(env->GetIsolate());
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000867 {
868 Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(
869 handle_call, Handle<v8::Value>(), Handle<v8::Signature>(), 23);
870 Local<Function> fun = fun_templ->GetFunction();
871 env->Global()->Set(v8_str("obj"), fun);
872 Local<Script> script = v8_compile("obj.length");
873 CHECK_EQ(23, script->Run()->Int32Value());
874 }
875 {
876 Local<v8::FunctionTemplate> fun_templ =
877 v8::FunctionTemplate::New(handle_call);
878 fun_templ->SetLength(22);
879 Local<Function> fun = fun_templ->GetFunction();
880 env->Global()->Set(v8_str("obj"), fun);
881 Local<Script> script = v8_compile("obj.length");
882 CHECK_EQ(22, script->Run()->Int32Value());
883 }
884 {
885 // Without setting length it defaults to 0.
886 Local<v8::FunctionTemplate> fun_templ =
887 v8::FunctionTemplate::New(handle_call);
888 Local<Function> fun = fun_templ->GetFunction();
889 env->Global()->Set(v8_str("obj"), fun);
890 Local<Script> script = v8_compile("obj.length");
891 CHECK_EQ(0, script->Run()->Int32Value());
892 }
893}
894
895
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000896static void* expected_ptr;
897static v8::Handle<v8::Value> callback(const v8::Arguments& args) {
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000898 void* ptr = v8::External::Cast(*args.Data())->Value();
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000899 CHECK_EQ(expected_ptr, ptr);
yangguo@chromium.org80c42ed2011-08-31 09:03:56 +0000900 return v8::True();
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000901}
902
903
904static void TestExternalPointerWrapping() {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000905 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000906 v8::HandleScope scope(env->GetIsolate());
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000907
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000908 v8::Handle<v8::Value> data = v8::External::New(expected_ptr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000909
910 v8::Handle<v8::Object> obj = v8::Object::New();
911 obj->Set(v8_str("func"),
912 v8::FunctionTemplate::New(callback, data)->GetFunction());
913 env->Global()->Set(v8_str("obj"), obj);
914
915 CHECK(CompileRun(
916 "function foo() {\n"
917 " for (var i = 0; i < 13; i++) obj.func();\n"
918 "}\n"
919 "foo(), true")->BooleanValue());
920}
921
922
923THREADED_TEST(ExternalWrap) {
924 // Check heap allocated object.
925 int* ptr = new int;
926 expected_ptr = ptr;
927 TestExternalPointerWrapping();
928 delete ptr;
929
930 // Check stack allocated object.
931 int foo;
932 expected_ptr = &foo;
933 TestExternalPointerWrapping();
934
935 // Check not aligned addresses.
936 const int n = 100;
937 char* s = new char[n];
938 for (int i = 0; i < n; i++) {
939 expected_ptr = s + i;
940 TestExternalPointerWrapping();
941 }
942
943 delete[] s;
944
945 // Check several invalid addresses.
946 expected_ptr = reinterpret_cast<void*>(1);
947 TestExternalPointerWrapping();
948
949 expected_ptr = reinterpret_cast<void*>(0xdeadbeef);
950 TestExternalPointerWrapping();
951
952 expected_ptr = reinterpret_cast<void*>(0xdeadbeef + 1);
953 TestExternalPointerWrapping();
954
955#if defined(V8_HOST_ARCH_X64)
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000956 // Check a value with a leading 1 bit in x64 Smi encoding.
957 expected_ptr = reinterpret_cast<void*>(0x400000000);
958 TestExternalPointerWrapping();
959
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000960 expected_ptr = reinterpret_cast<void*>(0xdeadbeefdeadbeef);
961 TestExternalPointerWrapping();
962
963 expected_ptr = reinterpret_cast<void*>(0xdeadbeefdeadbeef + 1);
964 TestExternalPointerWrapping();
965#endif
966}
967
968
sgjesse@chromium.org900d3b72009-08-07 11:24:25 +0000969THREADED_TEST(FindInstanceInPrototypeChain) {
sgjesse@chromium.org900d3b72009-08-07 11:24:25 +0000970 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000971 v8::HandleScope scope(env->GetIsolate());
sgjesse@chromium.org900d3b72009-08-07 11:24:25 +0000972
973 Local<v8::FunctionTemplate> base = v8::FunctionTemplate::New();
974 Local<v8::FunctionTemplate> derived = v8::FunctionTemplate::New();
975 Local<v8::FunctionTemplate> other = v8::FunctionTemplate::New();
976 derived->Inherit(base);
977
978 Local<v8::Function> base_function = base->GetFunction();
979 Local<v8::Function> derived_function = derived->GetFunction();
980 Local<v8::Function> other_function = other->GetFunction();
981
982 Local<v8::Object> base_instance = base_function->NewInstance();
983 Local<v8::Object> derived_instance = derived_function->NewInstance();
984 Local<v8::Object> derived_instance2 = derived_function->NewInstance();
985 Local<v8::Object> other_instance = other_function->NewInstance();
986 derived_instance2->Set(v8_str("__proto__"), derived_instance);
987 other_instance->Set(v8_str("__proto__"), derived_instance2);
988
989 // base_instance is only an instance of base.
990 CHECK_EQ(base_instance,
991 base_instance->FindInstanceInPrototypeChain(base));
992 CHECK(base_instance->FindInstanceInPrototypeChain(derived).IsEmpty());
993 CHECK(base_instance->FindInstanceInPrototypeChain(other).IsEmpty());
994
995 // derived_instance is an instance of base and derived.
996 CHECK_EQ(derived_instance,
997 derived_instance->FindInstanceInPrototypeChain(base));
998 CHECK_EQ(derived_instance,
999 derived_instance->FindInstanceInPrototypeChain(derived));
1000 CHECK(derived_instance->FindInstanceInPrototypeChain(other).IsEmpty());
1001
1002 // other_instance is an instance of other and its immediate
1003 // prototype derived_instance2 is an instance of base and derived.
1004 // Note, derived_instance is an instance of base and derived too,
1005 // but it comes after derived_instance2 in the prototype chain of
1006 // other_instance.
1007 CHECK_EQ(derived_instance2,
1008 other_instance->FindInstanceInPrototypeChain(base));
1009 CHECK_EQ(derived_instance2,
1010 other_instance->FindInstanceInPrototypeChain(derived));
1011 CHECK_EQ(other_instance,
1012 other_instance->FindInstanceInPrototypeChain(other));
1013}
1014
1015
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001016THREADED_TEST(TinyInteger) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001017 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001018 v8::HandleScope scope(env->GetIsolate());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001019 v8::Isolate* isolate = v8::Isolate::GetCurrent();
1020
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001021 int32_t value = 239;
1022 Local<v8::Integer> value_obj = v8::Integer::New(value);
1023 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001024
1025 value_obj = v8::Integer::New(value, isolate);
1026 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001027}
1028
1029
1030THREADED_TEST(BigSmiInteger) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001031 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001032 v8::HandleScope scope(env->GetIsolate());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001033 v8::Isolate* isolate = v8::Isolate::GetCurrent();
1034
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001035 int32_t value = i::Smi::kMaxValue;
1036 // We cannot add one to a Smi::kMaxValue without wrapping.
1037 if (i::kSmiValueSize < 32) {
1038 CHECK(i::Smi::IsValid(value));
1039 CHECK(!i::Smi::IsValid(value + 1));
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001040
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001041 Local<v8::Integer> value_obj = v8::Integer::New(value);
1042 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001043
1044 value_obj = v8::Integer::New(value, isolate);
1045 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001046 }
1047}
1048
1049
1050THREADED_TEST(BigInteger) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001051 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001052 v8::HandleScope scope(env->GetIsolate());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001053 v8::Isolate* isolate = v8::Isolate::GetCurrent();
1054
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001055 // We cannot add one to a Smi::kMaxValue without wrapping.
1056 if (i::kSmiValueSize < 32) {
1057 // The casts allow this to compile, even if Smi::kMaxValue is 2^31-1.
1058 // The code will not be run in that case, due to the "if" guard.
1059 int32_t value =
1060 static_cast<int32_t>(static_cast<uint32_t>(i::Smi::kMaxValue) + 1);
1061 CHECK(value > i::Smi::kMaxValue);
1062 CHECK(!i::Smi::IsValid(value));
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001063
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001064 Local<v8::Integer> value_obj = v8::Integer::New(value);
1065 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001066
1067 value_obj = v8::Integer::New(value, isolate);
1068 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001069 }
1070}
1071
1072
1073THREADED_TEST(TinyUnsignedInteger) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001074 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001075 v8::HandleScope scope(env->GetIsolate());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001076 v8::Isolate* isolate = v8::Isolate::GetCurrent();
1077
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001078 uint32_t value = 239;
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001079
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001080 Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(value);
1081 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001082
1083 value_obj = v8::Integer::NewFromUnsigned(value, isolate);
1084 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001085}
1086
1087
1088THREADED_TEST(BigUnsignedSmiInteger) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001089 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001090 v8::HandleScope scope(env->GetIsolate());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001091 v8::Isolate* isolate = v8::Isolate::GetCurrent();
1092
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001093 uint32_t value = static_cast<uint32_t>(i::Smi::kMaxValue);
1094 CHECK(i::Smi::IsValid(value));
1095 CHECK(!i::Smi::IsValid(value + 1));
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001096
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001097 Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(value);
1098 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001099
1100 value_obj = v8::Integer::NewFromUnsigned(value, isolate);
1101 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001102}
1103
1104
1105THREADED_TEST(BigUnsignedInteger) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001106 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001107 v8::HandleScope scope(env->GetIsolate());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001108 v8::Isolate* isolate = v8::Isolate::GetCurrent();
1109
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001110 uint32_t value = static_cast<uint32_t>(i::Smi::kMaxValue) + 1;
1111 CHECK(value > static_cast<uint32_t>(i::Smi::kMaxValue));
1112 CHECK(!i::Smi::IsValid(value));
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001113
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001114 Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(value);
1115 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001116
1117 value_obj = v8::Integer::NewFromUnsigned(value, isolate);
1118 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001119}
1120
1121
1122THREADED_TEST(OutOfSignedRangeUnsignedInteger) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001123 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001124 v8::HandleScope scope(env->GetIsolate());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001125 v8::Isolate* isolate = v8::Isolate::GetCurrent();
1126
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001127 uint32_t INT32_MAX_AS_UINT = (1U << 31) - 1;
1128 uint32_t value = INT32_MAX_AS_UINT + 1;
1129 CHECK(value > INT32_MAX_AS_UINT); // No overflow.
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001130
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001131 Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(value);
1132 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001133
1134 value_obj = v8::Integer::NewFromUnsigned(value, isolate);
1135 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001136}
1137
1138
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001139THREADED_TEST(IsNativeError) {
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001140 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001141 v8::HandleScope scope(env->GetIsolate());
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001142 v8::Handle<Value> syntax_error = CompileRun(
1143 "var out = 0; try { eval(\"#\"); } catch(x) { out = x; } out; ");
1144 CHECK(syntax_error->IsNativeError());
1145 v8::Handle<Value> not_error = CompileRun("{a:42}");
1146 CHECK(!not_error->IsNativeError());
1147 v8::Handle<Value> not_object = CompileRun("42");
1148 CHECK(!not_object->IsNativeError());
1149}
1150
1151
1152THREADED_TEST(StringObject) {
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001153 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001154 v8::HandleScope scope(env->GetIsolate());
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001155 v8::Handle<Value> boxed_string = CompileRun("new String(\"test\")");
1156 CHECK(boxed_string->IsStringObject());
1157 v8::Handle<Value> unboxed_string = CompileRun("\"test\"");
1158 CHECK(!unboxed_string->IsStringObject());
1159 v8::Handle<Value> boxed_not_string = CompileRun("new Number(42)");
1160 CHECK(!boxed_not_string->IsStringObject());
1161 v8::Handle<Value> not_object = CompileRun("0");
1162 CHECK(!not_object->IsStringObject());
1163 v8::Handle<v8::StringObject> as_boxed = boxed_string.As<v8::StringObject>();
1164 CHECK(!as_boxed.IsEmpty());
1165 Local<v8::String> the_string = as_boxed->StringValue();
1166 CHECK(!the_string.IsEmpty());
1167 ExpectObject("\"test\"", the_string);
1168 v8::Handle<v8::Value> new_boxed_string = v8::StringObject::New(the_string);
1169 CHECK(new_boxed_string->IsStringObject());
1170 as_boxed = new_boxed_string.As<v8::StringObject>();
1171 the_string = as_boxed->StringValue();
1172 CHECK(!the_string.IsEmpty());
1173 ExpectObject("\"test\"", the_string);
1174}
1175
1176
1177THREADED_TEST(NumberObject) {
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001178 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001179 v8::HandleScope scope(env->GetIsolate());
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001180 v8::Handle<Value> boxed_number = CompileRun("new Number(42)");
1181 CHECK(boxed_number->IsNumberObject());
1182 v8::Handle<Value> unboxed_number = CompileRun("42");
1183 CHECK(!unboxed_number->IsNumberObject());
1184 v8::Handle<Value> boxed_not_number = CompileRun("new Boolean(false)");
1185 CHECK(!boxed_not_number->IsNumberObject());
1186 v8::Handle<v8::NumberObject> as_boxed = boxed_number.As<v8::NumberObject>();
1187 CHECK(!as_boxed.IsEmpty());
1188 double the_number = as_boxed->NumberValue();
1189 CHECK_EQ(42.0, the_number);
1190 v8::Handle<v8::Value> new_boxed_number = v8::NumberObject::New(43);
1191 CHECK(new_boxed_number->IsNumberObject());
1192 as_boxed = new_boxed_number.As<v8::NumberObject>();
1193 the_number = as_boxed->NumberValue();
1194 CHECK_EQ(43.0, the_number);
1195}
1196
1197
1198THREADED_TEST(BooleanObject) {
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001199 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001200 v8::HandleScope scope(env->GetIsolate());
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001201 v8::Handle<Value> boxed_boolean = CompileRun("new Boolean(true)");
1202 CHECK(boxed_boolean->IsBooleanObject());
1203 v8::Handle<Value> unboxed_boolean = CompileRun("true");
1204 CHECK(!unboxed_boolean->IsBooleanObject());
1205 v8::Handle<Value> boxed_not_boolean = CompileRun("new Number(42)");
1206 CHECK(!boxed_not_boolean->IsBooleanObject());
1207 v8::Handle<v8::BooleanObject> as_boxed =
1208 boxed_boolean.As<v8::BooleanObject>();
1209 CHECK(!as_boxed.IsEmpty());
1210 bool the_boolean = as_boxed->BooleanValue();
1211 CHECK_EQ(true, the_boolean);
1212 v8::Handle<v8::Value> boxed_true = v8::BooleanObject::New(true);
1213 v8::Handle<v8::Value> boxed_false = v8::BooleanObject::New(false);
1214 CHECK(boxed_true->IsBooleanObject());
1215 CHECK(boxed_false->IsBooleanObject());
1216 as_boxed = boxed_true.As<v8::BooleanObject>();
1217 CHECK_EQ(true, as_boxed->BooleanValue());
1218 as_boxed = boxed_false.As<v8::BooleanObject>();
1219 CHECK_EQ(false, as_boxed->BooleanValue());
1220}
1221
1222
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001223THREADED_TEST(Number) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001224 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001225 v8::HandleScope scope(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001226 double PI = 3.1415926;
1227 Local<v8::Number> pi_obj = v8::Number::New(PI);
1228 CHECK_EQ(PI, pi_obj->NumberValue());
1229}
1230
1231
1232THREADED_TEST(ToNumber) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001233 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001234 v8::HandleScope scope(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001235 Local<String> str = v8_str("3.1415926");
1236 CHECK_EQ(3.1415926, str->NumberValue());
1237 v8::Handle<v8::Boolean> t = v8::True();
1238 CHECK_EQ(1.0, t->NumberValue());
1239 v8::Handle<v8::Boolean> f = v8::False();
1240 CHECK_EQ(0.0, f->NumberValue());
1241}
1242
1243
1244THREADED_TEST(Date) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001245 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001246 v8::HandleScope scope(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001247 double PI = 3.1415926;
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +00001248 Local<Value> date = v8::Date::New(PI);
1249 CHECK_EQ(3.0, date->NumberValue());
1250 date.As<v8::Date>()->Set(v8_str("property"), v8::Integer::New(42));
1251 CHECK_EQ(42, date.As<v8::Date>()->Get(v8_str("property"))->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001252}
1253
1254
1255THREADED_TEST(Boolean) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001256 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001257 v8::HandleScope scope(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001258 v8::Handle<v8::Boolean> t = v8::True();
1259 CHECK(t->Value());
1260 v8::Handle<v8::Boolean> f = v8::False();
1261 CHECK(!f->Value());
1262 v8::Handle<v8::Primitive> u = v8::Undefined();
1263 CHECK(!u->BooleanValue());
1264 v8::Handle<v8::Primitive> n = v8::Null();
1265 CHECK(!n->BooleanValue());
1266 v8::Handle<String> str1 = v8_str("");
1267 CHECK(!str1->BooleanValue());
1268 v8::Handle<String> str2 = v8_str("x");
1269 CHECK(str2->BooleanValue());
1270 CHECK(!v8::Number::New(0)->BooleanValue());
1271 CHECK(v8::Number::New(-1)->BooleanValue());
1272 CHECK(v8::Number::New(1)->BooleanValue());
1273 CHECK(v8::Number::New(42)->BooleanValue());
1274 CHECK(!v8_compile("NaN")->Run()->BooleanValue());
1275}
1276
1277
1278static v8::Handle<Value> DummyCallHandler(const v8::Arguments& args) {
1279 ApiTestFuzzer::Fuzz();
1280 return v8_num(13.4);
1281}
1282
1283
1284static v8::Handle<Value> GetM(Local<String> name, const AccessorInfo&) {
1285 ApiTestFuzzer::Fuzz();
1286 return v8_num(876);
1287}
1288
1289
1290THREADED_TEST(GlobalPrototype) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001291 v8::HandleScope scope(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001292 v8::Handle<v8::FunctionTemplate> func_templ = v8::FunctionTemplate::New();
1293 func_templ->PrototypeTemplate()->Set(
1294 "dummy",
1295 v8::FunctionTemplate::New(DummyCallHandler));
1296 v8::Handle<ObjectTemplate> templ = func_templ->InstanceTemplate();
1297 templ->Set("x", v8_num(200));
1298 templ->SetAccessor(v8_str("m"), GetM);
1299 LocalContext env(0, templ);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001300 v8::Handle<Script> script(v8_compile("dummy()"));
1301 v8::Handle<Value> result(script->Run());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001302 CHECK_EQ(13.4, result->NumberValue());
1303 CHECK_EQ(200, v8_compile("x")->Run()->Int32Value());
1304 CHECK_EQ(876, v8_compile("m")->Run()->Int32Value());
1305}
1306
1307
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001308THREADED_TEST(ObjectTemplate) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001309 v8::HandleScope scope(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001310 Local<ObjectTemplate> templ1 = ObjectTemplate::New();
1311 templ1->Set("x", v8_num(10));
1312 templ1->Set("y", v8_num(13));
1313 LocalContext env;
1314 Local<v8::Object> instance1 = templ1->NewInstance();
1315 env->Global()->Set(v8_str("p"), instance1);
1316 CHECK(v8_compile("(p.x == 10)")->Run()->BooleanValue());
1317 CHECK(v8_compile("(p.y == 13)")->Run()->BooleanValue());
1318 Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New();
1319 fun->PrototypeTemplate()->Set("nirk", v8_num(123));
1320 Local<ObjectTemplate> templ2 = fun->InstanceTemplate();
1321 templ2->Set("a", v8_num(12));
1322 templ2->Set("b", templ1);
1323 Local<v8::Object> instance2 = templ2->NewInstance();
1324 env->Global()->Set(v8_str("q"), instance2);
1325 CHECK(v8_compile("(q.nirk == 123)")->Run()->BooleanValue());
1326 CHECK(v8_compile("(q.a == 12)")->Run()->BooleanValue());
1327 CHECK(v8_compile("(q.b.x == 10)")->Run()->BooleanValue());
1328 CHECK(v8_compile("(q.b.y == 13)")->Run()->BooleanValue());
1329}
1330
1331
1332static v8::Handle<Value> GetFlabby(const v8::Arguments& args) {
1333 ApiTestFuzzer::Fuzz();
1334 return v8_num(17.2);
1335}
1336
1337
1338static v8::Handle<Value> GetKnurd(Local<String> property, const AccessorInfo&) {
1339 ApiTestFuzzer::Fuzz();
1340 return v8_num(15.2);
1341}
1342
1343
1344THREADED_TEST(DescriptorInheritance) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001345 v8::HandleScope scope(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001346 v8::Handle<v8::FunctionTemplate> super = v8::FunctionTemplate::New();
1347 super->PrototypeTemplate()->Set("flabby",
1348 v8::FunctionTemplate::New(GetFlabby));
1349 super->PrototypeTemplate()->Set("PI", v8_num(3.14));
1350
1351 super->InstanceTemplate()->SetAccessor(v8_str("knurd"), GetKnurd);
1352
1353 v8::Handle<v8::FunctionTemplate> base1 = v8::FunctionTemplate::New();
1354 base1->Inherit(super);
1355 base1->PrototypeTemplate()->Set("v1", v8_num(20.1));
1356
1357 v8::Handle<v8::FunctionTemplate> base2 = v8::FunctionTemplate::New();
1358 base2->Inherit(super);
1359 base2->PrototypeTemplate()->Set("v2", v8_num(10.1));
1360
1361 LocalContext env;
1362
1363 env->Global()->Set(v8_str("s"), super->GetFunction());
1364 env->Global()->Set(v8_str("base1"), base1->GetFunction());
1365 env->Global()->Set(v8_str("base2"), base2->GetFunction());
1366
1367 // Checks right __proto__ chain.
1368 CHECK(CompileRun("base1.prototype.__proto__ == s.prototype")->BooleanValue());
1369 CHECK(CompileRun("base2.prototype.__proto__ == s.prototype")->BooleanValue());
1370
1371 CHECK(v8_compile("s.prototype.PI == 3.14")->Run()->BooleanValue());
1372
1373 // Instance accessor should not be visible on function object or its prototype
1374 CHECK(CompileRun("s.knurd == undefined")->BooleanValue());
1375 CHECK(CompileRun("s.prototype.knurd == undefined")->BooleanValue());
1376 CHECK(CompileRun("base1.prototype.knurd == undefined")->BooleanValue());
1377
1378 env->Global()->Set(v8_str("obj"),
1379 base1->GetFunction()->NewInstance());
1380 CHECK_EQ(17.2, v8_compile("obj.flabby()")->Run()->NumberValue());
1381 CHECK(v8_compile("'flabby' in obj")->Run()->BooleanValue());
1382 CHECK_EQ(15.2, v8_compile("obj.knurd")->Run()->NumberValue());
1383 CHECK(v8_compile("'knurd' in obj")->Run()->BooleanValue());
1384 CHECK_EQ(20.1, v8_compile("obj.v1")->Run()->NumberValue());
1385
1386 env->Global()->Set(v8_str("obj2"),
1387 base2->GetFunction()->NewInstance());
1388 CHECK_EQ(17.2, v8_compile("obj2.flabby()")->Run()->NumberValue());
1389 CHECK(v8_compile("'flabby' in obj2")->Run()->BooleanValue());
1390 CHECK_EQ(15.2, v8_compile("obj2.knurd")->Run()->NumberValue());
1391 CHECK(v8_compile("'knurd' in obj2")->Run()->BooleanValue());
1392 CHECK_EQ(10.1, v8_compile("obj2.v2")->Run()->NumberValue());
1393
1394 // base1 and base2 cannot cross reference to each's prototype
1395 CHECK(v8_compile("obj.v2")->Run()->IsUndefined());
1396 CHECK(v8_compile("obj2.v1")->Run()->IsUndefined());
1397}
1398
1399
1400int echo_named_call_count;
1401
1402
1403static v8::Handle<Value> EchoNamedProperty(Local<String> name,
1404 const AccessorInfo& info) {
1405 ApiTestFuzzer::Fuzz();
1406 CHECK_EQ(v8_str("data"), info.Data());
1407 echo_named_call_count++;
1408 return name;
1409}
1410
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001411// Helper functions for Interceptor/Accessor interaction tests
1412
1413Handle<Value> SimpleAccessorGetter(Local<String> name,
1414 const AccessorInfo& info) {
1415 Handle<Object> self = info.This();
1416 return self->Get(String::Concat(v8_str("accessor_"), name));
1417}
1418
1419void SimpleAccessorSetter(Local<String> name, Local<Value> value,
1420 const AccessorInfo& info) {
1421 Handle<Object> self = info.This();
1422 self->Set(String::Concat(v8_str("accessor_"), name), value);
1423}
1424
1425Handle<Value> EmptyInterceptorGetter(Local<String> name,
1426 const AccessorInfo& info) {
1427 return Handle<Value>();
1428}
1429
1430Handle<Value> EmptyInterceptorSetter(Local<String> name,
1431 Local<Value> value,
1432 const AccessorInfo& info) {
1433 return Handle<Value>();
1434}
1435
1436Handle<Value> InterceptorGetter(Local<String> name,
1437 const AccessorInfo& info) {
1438 // Intercept names that start with 'interceptor_'.
1439 String::AsciiValue ascii(name);
1440 char* name_str = *ascii;
1441 char prefix[] = "interceptor_";
1442 int i;
1443 for (i = 0; name_str[i] && prefix[i]; ++i) {
1444 if (name_str[i] != prefix[i]) return Handle<Value>();
1445 }
1446 Handle<Object> self = info.This();
1447 return self->GetHiddenValue(v8_str(name_str + i));
1448}
1449
1450Handle<Value> InterceptorSetter(Local<String> name,
1451 Local<Value> value,
1452 const AccessorInfo& info) {
1453 // Intercept accesses that set certain integer values.
1454 if (value->IsInt32() && value->Int32Value() < 10000) {
1455 Handle<Object> self = info.This();
1456 self->SetHiddenValue(name, value);
1457 return value;
1458 }
1459 return Handle<Value>();
1460}
1461
1462void AddAccessor(Handle<FunctionTemplate> templ,
1463 Handle<String> name,
1464 v8::AccessorGetter getter,
1465 v8::AccessorSetter setter) {
1466 templ->PrototypeTemplate()->SetAccessor(name, getter, setter);
1467}
1468
1469void AddInterceptor(Handle<FunctionTemplate> templ,
1470 v8::NamedPropertyGetter getter,
1471 v8::NamedPropertySetter setter) {
1472 templ->InstanceTemplate()->SetNamedPropertyHandler(getter, setter);
1473}
1474
1475THREADED_TEST(EmptyInterceptorDoesNotShadowAccessors) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001476 v8::HandleScope scope(v8::Isolate::GetCurrent());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001477 Handle<FunctionTemplate> parent = FunctionTemplate::New();
1478 Handle<FunctionTemplate> child = FunctionTemplate::New();
1479 child->Inherit(parent);
1480 AddAccessor(parent, v8_str("age"),
1481 SimpleAccessorGetter, SimpleAccessorSetter);
1482 AddInterceptor(child, EmptyInterceptorGetter, EmptyInterceptorSetter);
1483 LocalContext env;
1484 env->Global()->Set(v8_str("Child"), child->GetFunction());
1485 CompileRun("var child = new Child;"
1486 "child.age = 10;");
1487 ExpectBoolean("child.hasOwnProperty('age')", false);
1488 ExpectInt32("child.age", 10);
1489 ExpectInt32("child.accessor_age", 10);
1490}
1491
1492THREADED_TEST(EmptyInterceptorDoesNotShadowJSAccessors) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001493 v8::HandleScope scope(v8::Isolate::GetCurrent());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001494 Handle<FunctionTemplate> parent = FunctionTemplate::New();
1495 Handle<FunctionTemplate> child = FunctionTemplate::New();
1496 child->Inherit(parent);
1497 AddInterceptor(child, EmptyInterceptorGetter, EmptyInterceptorSetter);
1498 LocalContext env;
1499 env->Global()->Set(v8_str("Child"), child->GetFunction());
1500 CompileRun("var child = new Child;"
1501 "var parent = child.__proto__;"
1502 "Object.defineProperty(parent, 'age', "
1503 " {get: function(){ return this.accessor_age; }, "
1504 " set: function(v){ this.accessor_age = v; }, "
1505 " enumerable: true, configurable: true});"
1506 "child.age = 10;");
1507 ExpectBoolean("child.hasOwnProperty('age')", false);
1508 ExpectInt32("child.age", 10);
1509 ExpectInt32("child.accessor_age", 10);
1510}
1511
1512THREADED_TEST(EmptyInterceptorDoesNotAffectJSProperties) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001513 v8::HandleScope scope(v8::Isolate::GetCurrent());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001514 Handle<FunctionTemplate> parent = FunctionTemplate::New();
1515 Handle<FunctionTemplate> child = FunctionTemplate::New();
1516 child->Inherit(parent);
1517 AddInterceptor(child, EmptyInterceptorGetter, EmptyInterceptorSetter);
1518 LocalContext env;
1519 env->Global()->Set(v8_str("Child"), child->GetFunction());
1520 CompileRun("var child = new Child;"
1521 "var parent = child.__proto__;"
1522 "parent.name = 'Alice';");
1523 ExpectBoolean("child.hasOwnProperty('name')", false);
1524 ExpectString("child.name", "Alice");
1525 CompileRun("child.name = 'Bob';");
1526 ExpectString("child.name", "Bob");
1527 ExpectBoolean("child.hasOwnProperty('name')", true);
1528 ExpectString("parent.name", "Alice");
1529}
1530
1531THREADED_TEST(SwitchFromInterceptorToAccessor) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001532 v8::HandleScope scope(v8::Isolate::GetCurrent());
danno@chromium.orgbf0c8202011-12-27 10:09:42 +00001533 Handle<FunctionTemplate> templ = FunctionTemplate::New();
1534 AddAccessor(templ, v8_str("age"),
1535 SimpleAccessorGetter, SimpleAccessorSetter);
1536 AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
1537 LocalContext env;
1538 env->Global()->Set(v8_str("Obj"), templ->GetFunction());
1539 CompileRun("var obj = new Obj;"
1540 "function setAge(i){ obj.age = i; };"
1541 "for(var i = 0; i <= 10000; i++) setAge(i);");
1542 // All i < 10000 go to the interceptor.
1543 ExpectInt32("obj.interceptor_age", 9999);
1544 // The last i goes to the accessor.
1545 ExpectInt32("obj.accessor_age", 10000);
1546}
1547
1548THREADED_TEST(SwitchFromAccessorToInterceptor) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001549 v8::HandleScope scope(v8::Isolate::GetCurrent());
danno@chromium.orgbf0c8202011-12-27 10:09:42 +00001550 Handle<FunctionTemplate> templ = FunctionTemplate::New();
1551 AddAccessor(templ, v8_str("age"),
1552 SimpleAccessorGetter, SimpleAccessorSetter);
1553 AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
1554 LocalContext env;
1555 env->Global()->Set(v8_str("Obj"), templ->GetFunction());
1556 CompileRun("var obj = new Obj;"
1557 "function setAge(i){ obj.age = i; };"
1558 "for(var i = 20000; i >= 9999; i--) setAge(i);");
1559 // All i >= 10000 go to the accessor.
1560 ExpectInt32("obj.accessor_age", 10000);
1561 // The last i goes to the interceptor.
1562 ExpectInt32("obj.interceptor_age", 9999);
1563}
1564
1565THREADED_TEST(SwitchFromInterceptorToAccessorWithInheritance) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001566 v8::HandleScope scope(v8::Isolate::GetCurrent());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001567 Handle<FunctionTemplate> parent = FunctionTemplate::New();
1568 Handle<FunctionTemplate> child = FunctionTemplate::New();
1569 child->Inherit(parent);
1570 AddAccessor(parent, v8_str("age"),
1571 SimpleAccessorGetter, SimpleAccessorSetter);
1572 AddInterceptor(child, InterceptorGetter, InterceptorSetter);
1573 LocalContext env;
1574 env->Global()->Set(v8_str("Child"), child->GetFunction());
1575 CompileRun("var child = new Child;"
1576 "function setAge(i){ child.age = i; };"
1577 "for(var i = 0; i <= 10000; i++) setAge(i);");
1578 // All i < 10000 go to the interceptor.
1579 ExpectInt32("child.interceptor_age", 9999);
1580 // The last i goes to the accessor.
1581 ExpectInt32("child.accessor_age", 10000);
1582}
1583
danno@chromium.orgbf0c8202011-12-27 10:09:42 +00001584THREADED_TEST(SwitchFromAccessorToInterceptorWithInheritance) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001585 v8::HandleScope scope(v8::Isolate::GetCurrent());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001586 Handle<FunctionTemplate> parent = FunctionTemplate::New();
1587 Handle<FunctionTemplate> child = FunctionTemplate::New();
1588 child->Inherit(parent);
1589 AddAccessor(parent, v8_str("age"),
1590 SimpleAccessorGetter, SimpleAccessorSetter);
1591 AddInterceptor(child, InterceptorGetter, InterceptorSetter);
1592 LocalContext env;
1593 env->Global()->Set(v8_str("Child"), child->GetFunction());
1594 CompileRun("var child = new Child;"
1595 "function setAge(i){ child.age = i; };"
1596 "for(var i = 20000; i >= 9999; i--) setAge(i);");
1597 // All i >= 10000 go to the accessor.
1598 ExpectInt32("child.accessor_age", 10000);
1599 // The last i goes to the interceptor.
1600 ExpectInt32("child.interceptor_age", 9999);
1601}
1602
danno@chromium.orgbf0c8202011-12-27 10:09:42 +00001603THREADED_TEST(SwitchFromInterceptorToJSAccessor) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001604 v8::HandleScope scope(v8::Isolate::GetCurrent());
danno@chromium.orgbf0c8202011-12-27 10:09:42 +00001605 Handle<FunctionTemplate> templ = FunctionTemplate::New();
1606 AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
1607 LocalContext env;
1608 env->Global()->Set(v8_str("Obj"), templ->GetFunction());
1609 CompileRun("var obj = new Obj;"
1610 "function setter(i) { this.accessor_age = i; };"
1611 "function getter() { return this.accessor_age; };"
1612 "function setAge(i) { obj.age = i; };"
1613 "Object.defineProperty(obj, 'age', { get:getter, set:setter });"
1614 "for(var i = 0; i <= 10000; i++) setAge(i);");
1615 // All i < 10000 go to the interceptor.
1616 ExpectInt32("obj.interceptor_age", 9999);
1617 // The last i goes to the JavaScript accessor.
1618 ExpectInt32("obj.accessor_age", 10000);
1619 // The installed JavaScript getter is still intact.
1620 // This last part is a regression test for issue 1651 and relies on the fact
1621 // that both interceptor and accessor are being installed on the same object.
1622 ExpectInt32("obj.age", 10000);
1623 ExpectBoolean("obj.hasOwnProperty('age')", true);
1624 ExpectUndefined("Object.getOwnPropertyDescriptor(obj, 'age').value");
1625}
1626
1627THREADED_TEST(SwitchFromJSAccessorToInterceptor) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001628 v8::HandleScope scope(v8::Isolate::GetCurrent());
danno@chromium.orgbf0c8202011-12-27 10:09:42 +00001629 Handle<FunctionTemplate> templ = FunctionTemplate::New();
1630 AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
1631 LocalContext env;
1632 env->Global()->Set(v8_str("Obj"), templ->GetFunction());
1633 CompileRun("var obj = new Obj;"
1634 "function setter(i) { this.accessor_age = i; };"
1635 "function getter() { return this.accessor_age; };"
1636 "function setAge(i) { obj.age = i; };"
1637 "Object.defineProperty(obj, 'age', { get:getter, set:setter });"
1638 "for(var i = 20000; i >= 9999; i--) setAge(i);");
1639 // All i >= 10000 go to the accessor.
1640 ExpectInt32("obj.accessor_age", 10000);
1641 // The last i goes to the interceptor.
1642 ExpectInt32("obj.interceptor_age", 9999);
1643 // The installed JavaScript getter is still intact.
1644 // This last part is a regression test for issue 1651 and relies on the fact
1645 // that both interceptor and accessor are being installed on the same object.
1646 ExpectInt32("obj.age", 10000);
1647 ExpectBoolean("obj.hasOwnProperty('age')", true);
1648 ExpectUndefined("Object.getOwnPropertyDescriptor(obj, 'age').value");
1649}
1650
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001651THREADED_TEST(SwitchFromInterceptorToProperty) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001652 v8::HandleScope scope(v8::Isolate::GetCurrent());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001653 Handle<FunctionTemplate> parent = FunctionTemplate::New();
1654 Handle<FunctionTemplate> child = FunctionTemplate::New();
1655 child->Inherit(parent);
1656 AddInterceptor(child, InterceptorGetter, InterceptorSetter);
1657 LocalContext env;
1658 env->Global()->Set(v8_str("Child"), child->GetFunction());
1659 CompileRun("var child = new Child;"
1660 "function setAge(i){ child.age = i; };"
1661 "for(var i = 0; i <= 10000; i++) setAge(i);");
1662 // All i < 10000 go to the interceptor.
1663 ExpectInt32("child.interceptor_age", 9999);
1664 // The last i goes to child's own property.
1665 ExpectInt32("child.age", 10000);
1666}
1667
1668THREADED_TEST(SwitchFromPropertyToInterceptor) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001669 v8::HandleScope scope(v8::Isolate::GetCurrent());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001670 Handle<FunctionTemplate> parent = FunctionTemplate::New();
1671 Handle<FunctionTemplate> child = FunctionTemplate::New();
1672 child->Inherit(parent);
1673 AddInterceptor(child, InterceptorGetter, InterceptorSetter);
1674 LocalContext env;
1675 env->Global()->Set(v8_str("Child"), child->GetFunction());
1676 CompileRun("var child = new Child;"
1677 "function setAge(i){ child.age = i; };"
1678 "for(var i = 20000; i >= 9999; i--) setAge(i);");
1679 // All i >= 10000 go to child's own property.
1680 ExpectInt32("child.age", 10000);
1681 // The last i goes to the interceptor.
1682 ExpectInt32("child.interceptor_age", 9999);
1683}
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001684
1685THREADED_TEST(NamedPropertyHandlerGetter) {
1686 echo_named_call_count = 0;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001687 v8::HandleScope scope(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001688 v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
1689 templ->InstanceTemplate()->SetNamedPropertyHandler(EchoNamedProperty,
1690 0, 0, 0, 0,
1691 v8_str("data"));
1692 LocalContext env;
1693 env->Global()->Set(v8_str("obj"),
1694 templ->GetFunction()->NewInstance());
1695 CHECK_EQ(echo_named_call_count, 0);
1696 v8_compile("obj.x")->Run();
1697 CHECK_EQ(echo_named_call_count, 1);
1698 const char* code = "var str = 'oddle'; obj[str] + obj.poddle;";
1699 v8::Handle<Value> str = CompileRun(code);
1700 String::AsciiValue value(str);
1701 CHECK_EQ(*value, "oddlepoddle");
1702 // Check default behavior
1703 CHECK_EQ(v8_compile("obj.flob = 10;")->Run()->Int32Value(), 10);
1704 CHECK(v8_compile("'myProperty' in obj")->Run()->BooleanValue());
1705 CHECK(v8_compile("delete obj.myProperty")->Run()->BooleanValue());
1706}
1707
1708
1709int echo_indexed_call_count = 0;
1710
1711
1712static v8::Handle<Value> EchoIndexedProperty(uint32_t index,
1713 const AccessorInfo& info) {
1714 ApiTestFuzzer::Fuzz();
1715 CHECK_EQ(v8_num(637), info.Data());
1716 echo_indexed_call_count++;
1717 return v8_num(index);
1718}
1719
1720
1721THREADED_TEST(IndexedPropertyHandlerGetter) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001722 v8::HandleScope scope(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001723 v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
1724 templ->InstanceTemplate()->SetIndexedPropertyHandler(EchoIndexedProperty,
1725 0, 0, 0, 0,
1726 v8_num(637));
1727 LocalContext env;
1728 env->Global()->Set(v8_str("obj"),
1729 templ->GetFunction()->NewInstance());
1730 Local<Script> script = v8_compile("obj[900]");
1731 CHECK_EQ(script->Run()->Int32Value(), 900);
1732}
1733
1734
1735v8::Handle<v8::Object> bottom;
1736
1737static v8::Handle<Value> CheckThisIndexedPropertyHandler(
1738 uint32_t index,
1739 const AccessorInfo& info) {
1740 ApiTestFuzzer::Fuzz();
1741 CHECK(info.This()->Equals(bottom));
1742 return v8::Handle<Value>();
1743}
1744
1745static v8::Handle<Value> CheckThisNamedPropertyHandler(
1746 Local<String> name,
1747 const AccessorInfo& info) {
1748 ApiTestFuzzer::Fuzz();
1749 CHECK(info.This()->Equals(bottom));
1750 return v8::Handle<Value>();
1751}
1752
1753
1754v8::Handle<Value> CheckThisIndexedPropertySetter(uint32_t index,
1755 Local<Value> value,
1756 const AccessorInfo& info) {
1757 ApiTestFuzzer::Fuzz();
1758 CHECK(info.This()->Equals(bottom));
1759 return v8::Handle<Value>();
1760}
1761
1762
1763v8::Handle<Value> CheckThisNamedPropertySetter(Local<String> property,
1764 Local<Value> value,
1765 const AccessorInfo& info) {
1766 ApiTestFuzzer::Fuzz();
1767 CHECK(info.This()->Equals(bottom));
1768 return v8::Handle<Value>();
1769}
1770
vegorov@chromium.org26c16f82010-08-11 13:41:03 +00001771v8::Handle<v8::Integer> CheckThisIndexedPropertyQuery(
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001772 uint32_t index,
1773 const AccessorInfo& info) {
1774 ApiTestFuzzer::Fuzz();
1775 CHECK(info.This()->Equals(bottom));
vegorov@chromium.org26c16f82010-08-11 13:41:03 +00001776 return v8::Handle<v8::Integer>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001777}
1778
1779
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001780v8::Handle<v8::Integer> CheckThisNamedPropertyQuery(Local<String> property,
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001781 const AccessorInfo& info) {
1782 ApiTestFuzzer::Fuzz();
1783 CHECK(info.This()->Equals(bottom));
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001784 return v8::Handle<v8::Integer>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001785}
1786
1787
1788v8::Handle<v8::Boolean> CheckThisIndexedPropertyDeleter(
1789 uint32_t index,
1790 const AccessorInfo& info) {
1791 ApiTestFuzzer::Fuzz();
1792 CHECK(info.This()->Equals(bottom));
1793 return v8::Handle<v8::Boolean>();
1794}
1795
1796
1797v8::Handle<v8::Boolean> CheckThisNamedPropertyDeleter(
1798 Local<String> property,
1799 const AccessorInfo& info) {
1800 ApiTestFuzzer::Fuzz();
1801 CHECK(info.This()->Equals(bottom));
1802 return v8::Handle<v8::Boolean>();
1803}
1804
1805
1806v8::Handle<v8::Array> CheckThisIndexedPropertyEnumerator(
1807 const AccessorInfo& info) {
1808 ApiTestFuzzer::Fuzz();
1809 CHECK(info.This()->Equals(bottom));
1810 return v8::Handle<v8::Array>();
1811}
1812
1813
1814v8::Handle<v8::Array> CheckThisNamedPropertyEnumerator(
1815 const AccessorInfo& info) {
1816 ApiTestFuzzer::Fuzz();
1817 CHECK(info.This()->Equals(bottom));
1818 return v8::Handle<v8::Array>();
1819}
1820
1821
1822THREADED_TEST(PropertyHandlerInPrototype) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001823 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001824 v8::HandleScope scope(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001825
1826 // Set up a prototype chain with three interceptors.
1827 v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
1828 templ->InstanceTemplate()->SetIndexedPropertyHandler(
1829 CheckThisIndexedPropertyHandler,
1830 CheckThisIndexedPropertySetter,
1831 CheckThisIndexedPropertyQuery,
1832 CheckThisIndexedPropertyDeleter,
1833 CheckThisIndexedPropertyEnumerator);
1834
1835 templ->InstanceTemplate()->SetNamedPropertyHandler(
1836 CheckThisNamedPropertyHandler,
1837 CheckThisNamedPropertySetter,
1838 CheckThisNamedPropertyQuery,
1839 CheckThisNamedPropertyDeleter,
1840 CheckThisNamedPropertyEnumerator);
1841
1842 bottom = templ->GetFunction()->NewInstance();
1843 Local<v8::Object> top = templ->GetFunction()->NewInstance();
1844 Local<v8::Object> middle = templ->GetFunction()->NewInstance();
1845
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +00001846 bottom->SetPrototype(middle);
1847 middle->SetPrototype(top);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001848 env->Global()->Set(v8_str("obj"), bottom);
1849
1850 // Indexed and named get.
1851 Script::Compile(v8_str("obj[0]"))->Run();
1852 Script::Compile(v8_str("obj.x"))->Run();
1853
1854 // Indexed and named set.
1855 Script::Compile(v8_str("obj[1] = 42"))->Run();
1856 Script::Compile(v8_str("obj.y = 42"))->Run();
1857
1858 // Indexed and named query.
1859 Script::Compile(v8_str("0 in obj"))->Run();
1860 Script::Compile(v8_str("'x' in obj"))->Run();
1861
1862 // Indexed and named deleter.
1863 Script::Compile(v8_str("delete obj[0]"))->Run();
1864 Script::Compile(v8_str("delete obj.x"))->Run();
1865
1866 // Enumerators.
1867 Script::Compile(v8_str("for (var p in obj) ;"))->Run();
1868}
1869
1870
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001871static v8::Handle<Value> PrePropertyHandlerGet(Local<String> key,
1872 const AccessorInfo& info) {
1873 ApiTestFuzzer::Fuzz();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001874 if (v8_str("pre")->Equals(key)) {
1875 return v8_str("PrePropertyHandler: pre");
1876 }
1877 return v8::Handle<String>();
1878}
1879
1880
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001881static v8::Handle<v8::Integer> PrePropertyHandlerQuery(Local<String> key,
1882 const AccessorInfo&) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001883 if (v8_str("pre")->Equals(key)) {
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001884 return v8::Integer::New(v8::None);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001885 }
1886
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001887 return v8::Handle<v8::Integer>(); // do not intercept the call
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001888}
1889
1890
1891THREADED_TEST(PrePropertyHandler) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001892 v8::HandleScope scope(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001893 v8::Handle<v8::FunctionTemplate> desc = v8::FunctionTemplate::New();
1894 desc->InstanceTemplate()->SetNamedPropertyHandler(PrePropertyHandlerGet,
1895 0,
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00001896 PrePropertyHandlerQuery);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001897 LocalContext env(NULL, desc->InstanceTemplate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001898 Script::Compile(v8_str(
1899 "var pre = 'Object: pre'; var on = 'Object: on';"))->Run();
1900 v8::Handle<Value> result_pre = Script::Compile(v8_str("pre"))->Run();
1901 CHECK_EQ(v8_str("PrePropertyHandler: pre"), result_pre);
1902 v8::Handle<Value> result_on = Script::Compile(v8_str("on"))->Run();
1903 CHECK_EQ(v8_str("Object: on"), result_on);
1904 v8::Handle<Value> result_post = Script::Compile(v8_str("post"))->Run();
1905 CHECK(result_post.IsEmpty());
1906}
1907
1908
ager@chromium.org870a0b62008-11-04 11:43:05 +00001909THREADED_TEST(UndefinedIsNotEnumerable) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00001910 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001911 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org870a0b62008-11-04 11:43:05 +00001912 v8::Handle<Value> result = Script::Compile(v8_str(
1913 "this.propertyIsEnumerable(undefined)"))->Run();
1914 CHECK(result->IsFalse());
1915}
1916
1917
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001918v8::Handle<Script> call_recursively_script;
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001919static const int kTargetRecursionDepth = 200; // near maximum
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001920
1921
1922static v8::Handle<Value> CallScriptRecursivelyCall(const v8::Arguments& args) {
1923 ApiTestFuzzer::Fuzz();
1924 int depth = args.This()->Get(v8_str("depth"))->Int32Value();
1925 if (depth == kTargetRecursionDepth) return v8::Undefined();
1926 args.This()->Set(v8_str("depth"), v8::Integer::New(depth + 1));
1927 return call_recursively_script->Run();
1928}
1929
1930
1931static v8::Handle<Value> CallFunctionRecursivelyCall(
1932 const v8::Arguments& args) {
1933 ApiTestFuzzer::Fuzz();
1934 int depth = args.This()->Get(v8_str("depth"))->Int32Value();
1935 if (depth == kTargetRecursionDepth) {
1936 printf("[depth = %d]\n", depth);
1937 return v8::Undefined();
1938 }
1939 args.This()->Set(v8_str("depth"), v8::Integer::New(depth + 1));
1940 v8::Handle<Value> function =
1941 args.This()->Get(v8_str("callFunctionRecursively"));
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00001942 return function.As<Function>()->Call(args.This(), 0, NULL);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001943}
1944
1945
1946THREADED_TEST(DeepCrossLanguageRecursion) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001947 v8::HandleScope scope(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001948 v8::Handle<v8::ObjectTemplate> global = ObjectTemplate::New();
1949 global->Set(v8_str("callScriptRecursively"),
1950 v8::FunctionTemplate::New(CallScriptRecursivelyCall));
1951 global->Set(v8_str("callFunctionRecursively"),
1952 v8::FunctionTemplate::New(CallFunctionRecursivelyCall));
1953 LocalContext env(NULL, global);
1954
1955 env->Global()->Set(v8_str("depth"), v8::Integer::New(0));
1956 call_recursively_script = v8_compile("callScriptRecursively()");
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00001957 call_recursively_script->Run();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001958 call_recursively_script = v8::Handle<Script>();
1959
1960 env->Global()->Set(v8_str("depth"), v8::Integer::New(0));
1961 Script::Compile(v8_str("callFunctionRecursively()"))->Run();
1962}
1963
1964
1965static v8::Handle<Value>
1966 ThrowingPropertyHandlerGet(Local<String> key, const AccessorInfo&) {
1967 ApiTestFuzzer::Fuzz();
1968 return v8::ThrowException(key);
1969}
1970
1971
1972static v8::Handle<Value> ThrowingPropertyHandlerSet(Local<String> key,
1973 Local<Value>,
1974 const AccessorInfo&) {
1975 v8::ThrowException(key);
1976 return v8::Undefined(); // not the same as v8::Handle<v8::Value>()
1977}
1978
1979
1980THREADED_TEST(CallbackExceptionRegression) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001981 v8::HandleScope scope(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001982 v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
1983 obj->SetNamedPropertyHandler(ThrowingPropertyHandlerGet,
1984 ThrowingPropertyHandlerSet);
1985 LocalContext env;
1986 env->Global()->Set(v8_str("obj"), obj->NewInstance());
1987 v8::Handle<Value> otto = Script::Compile(v8_str(
1988 "try { with (obj) { otto; } } catch (e) { e; }"))->Run();
1989 CHECK_EQ(v8_str("otto"), otto);
1990 v8::Handle<Value> netto = Script::Compile(v8_str(
1991 "try { with (obj) { netto = 4; } } catch (e) { e; }"))->Run();
1992 CHECK_EQ(v8_str("netto"), netto);
1993}
1994
1995
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001996THREADED_TEST(FunctionPrototype) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001997 v8::HandleScope scope(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001998 Local<v8::FunctionTemplate> Foo = v8::FunctionTemplate::New();
1999 Foo->PrototypeTemplate()->Set(v8_str("plak"), v8_num(321));
2000 LocalContext env;
2001 env->Global()->Set(v8_str("Foo"), Foo->GetFunction());
2002 Local<Script> script = Script::Compile(v8_str("Foo.prototype.plak"));
2003 CHECK_EQ(script->Run()->Int32Value(), 321);
2004}
2005
2006
2007THREADED_TEST(InternalFields) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002008 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00002009 v8::HandleScope scope(env->GetIsolate());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002010
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002011 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
2012 Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
2013 instance_templ->SetInternalFieldCount(1);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002014 Local<v8::Object> obj = templ->GetFunction()->NewInstance();
2015 CHECK_EQ(1, obj->InternalFieldCount());
2016 CHECK(obj->GetInternalField(0)->IsUndefined());
2017 obj->SetInternalField(0, v8_num(17));
2018 CHECK_EQ(17, obj->GetInternalField(0)->Int32Value());
2019}
2020
2021
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002022THREADED_TEST(GlobalObjectInternalFields) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00002023 v8::HandleScope scope(v8::Isolate::GetCurrent());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002024 Local<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
2025 global_template->SetInternalFieldCount(1);
2026 LocalContext env(NULL, global_template);
2027 v8::Handle<v8::Object> global_proxy = env->Global();
2028 v8::Handle<v8::Object> global = global_proxy->GetPrototype().As<v8::Object>();
2029 CHECK_EQ(1, global->InternalFieldCount());
2030 CHECK(global->GetInternalField(0)->IsUndefined());
2031 global->SetInternalField(0, v8_num(17));
2032 CHECK_EQ(17, global->GetInternalField(0)->Int32Value());
2033}
2034
2035
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002036static void CheckAlignedPointerInInternalField(Handle<v8::Object> obj,
2037 void* value) {
2038 CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(value) & 0x1));
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00002039 obj->SetAlignedPointerInInternalField(0, value);
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002040 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00002041 CHECK_EQ(value, obj->GetAlignedPointerFromInternalField(0));
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002042}
2043
2044
2045THREADED_TEST(InternalFieldsAlignedPointers) {
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002046 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00002047 v8::HandleScope scope(env->GetIsolate());
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002048
2049 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
2050 Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
2051 instance_templ->SetInternalFieldCount(1);
2052 Local<v8::Object> obj = templ->GetFunction()->NewInstance();
2053 CHECK_EQ(1, obj->InternalFieldCount());
2054
2055 CheckAlignedPointerInInternalField(obj, NULL);
2056
2057 int* heap_allocated = new int[100];
2058 CheckAlignedPointerInInternalField(obj, heap_allocated);
2059 delete[] heap_allocated;
2060
2061 int stack_allocated[100];
2062 CheckAlignedPointerInInternalField(obj, stack_allocated);
2063
2064 void* huge = reinterpret_cast<void*>(~static_cast<uintptr_t>(1));
2065 CheckAlignedPointerInInternalField(obj, huge);
2066}
2067
2068
2069static void CheckAlignedPointerInEmbedderData(LocalContext* env,
2070 int index,
2071 void* value) {
2072 CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(value) & 0x1));
2073 (*env)->SetAlignedPointerInEmbedderData(index, value);
2074 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
2075 CHECK_EQ(value, (*env)->GetAlignedPointerFromEmbedderData(index));
2076}
2077
2078
2079static void* AlignedTestPointer(int i) {
2080 return reinterpret_cast<void*>(i * 1234);
2081}
2082
2083
2084THREADED_TEST(EmbedderDataAlignedPointers) {
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002085 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00002086 v8::HandleScope scope(env->GetIsolate());
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002087
2088 CheckAlignedPointerInEmbedderData(&env, 0, NULL);
2089
2090 int* heap_allocated = new int[100];
2091 CheckAlignedPointerInEmbedderData(&env, 1, heap_allocated);
2092 delete[] heap_allocated;
2093
2094 int stack_allocated[100];
2095 CheckAlignedPointerInEmbedderData(&env, 2, stack_allocated);
2096
2097 void* huge = reinterpret_cast<void*>(~static_cast<uintptr_t>(1));
2098 CheckAlignedPointerInEmbedderData(&env, 3, huge);
2099
2100 // Test growing of the embedder data's backing store.
2101 for (int i = 0; i < 100; i++) {
2102 env->SetAlignedPointerInEmbedderData(i, AlignedTestPointer(i));
2103 }
2104 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
2105 for (int i = 0; i < 100; i++) {
2106 CHECK_EQ(AlignedTestPointer(i), env->GetAlignedPointerFromEmbedderData(i));
2107 }
2108}
2109
2110
2111static void CheckEmbedderData(LocalContext* env,
2112 int index,
2113 v8::Handle<Value> data) {
2114 (*env)->SetEmbedderData(index, data);
2115 CHECK((*env)->GetEmbedderData(index)->StrictEquals(data));
2116}
2117
2118THREADED_TEST(EmbedderData) {
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002119 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00002120 v8::HandleScope scope(env->GetIsolate());
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002121
2122 CheckEmbedderData(&env, 3, v8::String::New("The quick brown fox jumps"));
2123 CheckEmbedderData(&env, 2, v8::String::New("over the lazy dog."));
2124 CheckEmbedderData(&env, 1, v8::Number::New(1.2345));
2125 CheckEmbedderData(&env, 0, v8::Boolean::New(true));
2126}
2127
2128
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002129THREADED_TEST(IdentityHash) {
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002130 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00002131 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002132
2133 // Ensure that the test starts with an fresh heap to test whether the hash
2134 // code is based on the address.
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002135 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002136 Local<v8::Object> obj = v8::Object::New();
2137 int hash = obj->GetIdentityHash();
2138 int hash1 = obj->GetIdentityHash();
2139 CHECK_EQ(hash, hash1);
2140 int hash2 = v8::Object::New()->GetIdentityHash();
2141 // Since the identity hash is essentially a random number two consecutive
2142 // objects should not be assigned the same hash code. If the test below fails
2143 // the random number generator should be evaluated.
2144 CHECK_NE(hash, hash2);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002145 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002146 int hash3 = v8::Object::New()->GetIdentityHash();
2147 // Make sure that the identity hash is not based on the initial address of
2148 // the object alone. If the test below fails the random number generator
2149 // should be evaluated.
2150 CHECK_NE(hash, hash3);
2151 int hash4 = obj->GetIdentityHash();
2152 CHECK_EQ(hash, hash4);
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002153
2154 // Check identity hashes behaviour in the presence of JS accessors.
2155 // Put a getter for 'v8::IdentityHash' on the Object's prototype:
2156 {
2157 CompileRun("Object.prototype['v8::IdentityHash'] = 42;\n");
2158 Local<v8::Object> o1 = v8::Object::New();
2159 Local<v8::Object> o2 = v8::Object::New();
2160 CHECK_NE(o1->GetIdentityHash(), o2->GetIdentityHash());
2161 }
2162 {
2163 CompileRun(
2164 "function cnst() { return 42; };\n"
2165 "Object.prototype.__defineGetter__('v8::IdentityHash', cnst);\n");
2166 Local<v8::Object> o1 = v8::Object::New();
2167 Local<v8::Object> o2 = v8::Object::New();
2168 CHECK_NE(o1->GetIdentityHash(), o2->GetIdentityHash());
2169 }
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002170}
2171
2172
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002173THREADED_TEST(SymbolProperties) {
2174 i::FLAG_harmony_symbols = true;
2175
2176 LocalContext env;
2177 v8::Isolate* isolate = env->GetIsolate();
2178 v8::HandleScope scope(isolate);
2179
2180 v8::Local<v8::Object> obj = v8::Object::New();
2181 v8::Local<v8::Symbol> sym1 = v8::Symbol::New(isolate);
2182 v8::Local<v8::Symbol> sym2 = v8::Symbol::New(isolate, "my-symbol");
2183
2184 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
2185
2186 // Check basic symbol functionality.
2187 CHECK(sym1->IsSymbol());
2188 CHECK(sym2->IsSymbol());
2189 CHECK(!obj->IsSymbol());
2190
2191 CHECK(sym1->Equals(sym1));
2192 CHECK(sym2->Equals(sym2));
2193 CHECK(!sym1->Equals(sym2));
2194 CHECK(!sym2->Equals(sym1));
2195 CHECK(sym1->StrictEquals(sym1));
2196 CHECK(sym2->StrictEquals(sym2));
2197 CHECK(!sym1->StrictEquals(sym2));
2198 CHECK(!sym2->StrictEquals(sym1));
2199
2200 CHECK(sym2->Name()->Equals(v8::String::New("my-symbol")));
2201
2202 v8::Local<v8::Value> sym_val = sym2;
2203 CHECK(sym_val->IsSymbol());
2204 CHECK(sym_val->Equals(sym2));
2205 CHECK(sym_val->StrictEquals(sym2));
2206 CHECK(v8::Symbol::Cast(*sym_val)->Equals(sym2));
2207
2208 v8::Local<v8::Value> sym_obj = v8::SymbolObject::New(isolate, sym2);
2209 CHECK(sym_obj->IsSymbolObject());
2210 CHECK(!sym2->IsSymbolObject());
2211 CHECK(!obj->IsSymbolObject());
2212 CHECK(sym_obj->Equals(sym2));
2213 CHECK(!sym_obj->StrictEquals(sym2));
2214 CHECK(v8::SymbolObject::Cast(*sym_obj)->Equals(sym_obj));
2215 CHECK(v8::SymbolObject::Cast(*sym_obj)->SymbolValue()->Equals(sym2));
2216
2217 // Make sure delete of a non-existent symbol property works.
2218 CHECK(obj->Delete(sym1));
2219 CHECK(!obj->Has(sym1));
2220
2221 CHECK(obj->Set(sym1, v8::Integer::New(1503)));
2222 CHECK(obj->Has(sym1));
2223 CHECK_EQ(1503, obj->Get(sym1)->Int32Value());
2224 CHECK(obj->Set(sym1, v8::Integer::New(2002)));
2225 CHECK(obj->Has(sym1));
2226 CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
2227 CHECK_EQ(v8::None, obj->GetPropertyAttributes(sym1));
2228
2229 CHECK_EQ(0, obj->GetOwnPropertyNames()->Length());
2230 int num_props = obj->GetPropertyNames()->Length();
2231 CHECK(obj->Set(v8::String::New("bla"), v8::Integer::New(20)));
2232 CHECK_EQ(1, obj->GetOwnPropertyNames()->Length());
2233 CHECK_EQ(num_props + 1, obj->GetPropertyNames()->Length());
2234
2235 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
2236
2237 // Add another property and delete it afterwards to force the object in
2238 // slow case.
2239 CHECK(obj->Set(sym2, v8::Integer::New(2008)));
2240 CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
2241 CHECK_EQ(2008, obj->Get(sym2)->Int32Value());
2242 CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
2243 CHECK_EQ(1, obj->GetOwnPropertyNames()->Length());
2244
2245 CHECK(obj->Has(sym1));
2246 CHECK(obj->Has(sym2));
2247 CHECK(obj->Delete(sym2));
2248 CHECK(obj->Has(sym1));
2249 CHECK(!obj->Has(sym2));
2250 CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
2251 CHECK_EQ(1, obj->GetOwnPropertyNames()->Length());
2252}
2253
2254
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002255THREADED_TEST(HiddenProperties) {
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002256 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00002257 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002258
2259 v8::Local<v8::Object> obj = v8::Object::New();
2260 v8::Local<v8::String> key = v8_str("api-test::hidden-key");
2261 v8::Local<v8::String> empty = v8_str("");
2262 v8::Local<v8::String> prop_name = v8_str("prop_name");
2263
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002264 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002265
kasperl@chromium.orgacae3782009-04-11 09:17:08 +00002266 // Make sure delete of a non-existent hidden value works
2267 CHECK(obj->DeleteHiddenValue(key));
2268
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002269 CHECK(obj->SetHiddenValue(key, v8::Integer::New(1503)));
2270 CHECK_EQ(1503, obj->GetHiddenValue(key)->Int32Value());
2271 CHECK(obj->SetHiddenValue(key, v8::Integer::New(2002)));
2272 CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
2273
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002274 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002275
2276 // Make sure we do not find the hidden property.
2277 CHECK(!obj->Has(empty));
2278 CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
2279 CHECK(obj->Get(empty)->IsUndefined());
2280 CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
2281 CHECK(obj->Set(empty, v8::Integer::New(2003)));
2282 CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
2283 CHECK_EQ(2003, obj->Get(empty)->Int32Value());
2284
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002285 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002286
2287 // Add another property and delete it afterwards to force the object in
2288 // slow case.
2289 CHECK(obj->Set(prop_name, v8::Integer::New(2008)));
2290 CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
2291 CHECK_EQ(2008, obj->Get(prop_name)->Int32Value());
2292 CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
2293 CHECK(obj->Delete(prop_name));
2294 CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
2295
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002296 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002297
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00002298 CHECK(obj->SetHiddenValue(key, Handle<Value>()));
2299 CHECK(obj->GetHiddenValue(key).IsEmpty());
2300
2301 CHECK(obj->SetHiddenValue(key, v8::Integer::New(2002)));
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002302 CHECK(obj->DeleteHiddenValue(key));
2303 CHECK(obj->GetHiddenValue(key).IsEmpty());
2304}
2305
2306
ricow@chromium.org9fe9cdf2011-09-27 08:04:16 +00002307THREADED_TEST(Regress97784) {
2308 // Regression test for crbug.com/97784
2309 // Messing with the Object.prototype should not have effect on
2310 // hidden properties.
ricow@chromium.org9fe9cdf2011-09-27 08:04:16 +00002311 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00002312 v8::HandleScope scope(env->GetIsolate());
ricow@chromium.org9fe9cdf2011-09-27 08:04:16 +00002313
2314 v8::Local<v8::Object> obj = v8::Object::New();
2315 v8::Local<v8::String> key = v8_str("hidden");
2316
2317 CompileRun(
2318 "set_called = false;"
2319 "Object.defineProperty("
2320 " Object.prototype,"
2321 " 'hidden',"
2322 " {get: function() { return 45; },"
2323 " set: function() { set_called = true; }})");
2324
2325 CHECK(obj->GetHiddenValue(key).IsEmpty());
2326 // Make sure that the getter and setter from Object.prototype is not invoked.
2327 // If it did we would have full access to the hidden properties in
2328 // the accessor.
2329 CHECK(obj->SetHiddenValue(key, v8::Integer::New(42)));
2330 ExpectFalse("set_called");
2331 CHECK_EQ(42, obj->GetHiddenValue(key)->Int32Value());
2332}
2333
2334
ager@chromium.orgc4c92722009-11-18 14:12:51 +00002335static bool interceptor_for_hidden_properties_called;
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002336static v8::Handle<Value> InterceptorForHiddenProperties(
2337 Local<String> name, const AccessorInfo& info) {
ager@chromium.orgc4c92722009-11-18 14:12:51 +00002338 interceptor_for_hidden_properties_called = true;
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002339 return v8::Handle<Value>();
2340}
2341
2342
2343THREADED_TEST(HiddenPropertiesWithInterceptors) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002344 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00002345 v8::HandleScope scope(context->GetIsolate());
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002346
ager@chromium.orgc4c92722009-11-18 14:12:51 +00002347 interceptor_for_hidden_properties_called = false;
2348
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002349 v8::Local<v8::String> key = v8_str("api-test::hidden-key");
2350
2351 // Associate an interceptor with an object and start setting hidden values.
2352 Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
2353 Local<v8::ObjectTemplate> instance_templ = fun_templ->InstanceTemplate();
2354 instance_templ->SetNamedPropertyHandler(InterceptorForHiddenProperties);
2355 Local<v8::Function> function = fun_templ->GetFunction();
2356 Local<v8::Object> obj = function->NewInstance();
2357 CHECK(obj->SetHiddenValue(key, v8::Integer::New(2302)));
2358 CHECK_EQ(2302, obj->GetHiddenValue(key)->Int32Value());
ager@chromium.orgc4c92722009-11-18 14:12:51 +00002359 CHECK(!interceptor_for_hidden_properties_called);
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00002360}
2361
2362
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002363THREADED_TEST(External) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00002364 v8::HandleScope scope(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002365 int x = 3;
2366 Local<v8::External> ext = v8::External::New(&x);
2367 LocalContext env;
2368 env->Global()->Set(v8_str("ext"), ext);
2369 Local<Value> reext_obj = Script::Compile(v8_str("this.ext"))->Run();
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002370 v8::Handle<v8::External> reext = reext_obj.As<v8::External>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002371 int* ptr = static_cast<int*>(reext->Value());
2372 CHECK_EQ(x, 3);
2373 *ptr = 10;
2374 CHECK_EQ(x, 10);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00002375
2376 // Make sure unaligned pointers are wrapped properly.
2377 char* data = i::StrDup("0123456789");
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00002378 Local<v8::Value> zero = v8::External::New(&data[0]);
2379 Local<v8::Value> one = v8::External::New(&data[1]);
2380 Local<v8::Value> two = v8::External::New(&data[2]);
2381 Local<v8::Value> three = v8::External::New(&data[3]);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00002382
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00002383 char* char_ptr = reinterpret_cast<char*>(v8::External::Cast(*zero)->Value());
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00002384 CHECK_EQ('0', *char_ptr);
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00002385 char_ptr = reinterpret_cast<char*>(v8::External::Cast(*one)->Value());
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00002386 CHECK_EQ('1', *char_ptr);
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00002387 char_ptr = reinterpret_cast<char*>(v8::External::Cast(*two)->Value());
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00002388 CHECK_EQ('2', *char_ptr);
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00002389 char_ptr = reinterpret_cast<char*>(v8::External::Cast(*three)->Value());
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00002390 CHECK_EQ('3', *char_ptr);
2391 i::DeleteArray(data);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002392}
2393
2394
2395THREADED_TEST(GlobalHandle) {
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00002396 v8::Isolate* isolate = v8::Isolate::GetCurrent();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002397 v8::Persistent<String> global;
2398 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00002399 v8::HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002400 Local<String> str = v8_str("str");
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00002401 global = v8::Persistent<String>::New(isolate, str);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002402 }
2403 CHECK_EQ(global->Length(), 3);
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00002404 global.Dispose(isolate);
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00002405
2406 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00002407 v8::HandleScope scope(isolate);
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00002408 Local<String> str = v8_str("str");
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00002409 global = v8::Persistent<String>::New(isolate, str);
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00002410 }
2411 CHECK_EQ(global->Length(), 3);
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00002412 global.Dispose(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002413}
2414
2415
mstarzinger@chromium.org32280cf2012-12-06 17:32:37 +00002416THREADED_TEST(LocalHandle) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00002417 v8::HandleScope scope(v8::Isolate::GetCurrent());
mstarzinger@chromium.org32280cf2012-12-06 17:32:37 +00002418 v8::Local<String> local = v8::Local<String>::New(v8_str("str"));
2419 CHECK_EQ(local->Length(), 3);
2420
2421 local = v8::Local<String>::New(v8::Isolate::GetCurrent(), v8_str("str"));
2422 CHECK_EQ(local->Length(), 3);
2423}
2424
2425
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002426class WeakCallCounter {
2427 public:
2428 explicit WeakCallCounter(int id) : id_(id), number_of_weak_calls_(0) { }
2429 int id() { return id_; }
2430 void increment() { number_of_weak_calls_++; }
2431 int NumberOfWeakCalls() { return number_of_weak_calls_; }
2432 private:
2433 int id_;
2434 int number_of_weak_calls_;
2435};
2436
2437
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00002438static void WeakPointerCallback(v8::Isolate* isolate,
2439 Persistent<Value> handle,
2440 void* id) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002441 WeakCallCounter* counter = reinterpret_cast<WeakCallCounter*>(id);
2442 CHECK_EQ(1234, counter->id());
2443 counter->increment();
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00002444 handle.Dispose(isolate);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00002445}
2446
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002447
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00002448THREADED_TEST(ApiObjectGroups) {
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00002449 LocalContext env;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00002450 v8::Isolate* iso = env->GetIsolate();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00002451 HandleScope scope(iso);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00002452
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00002453 Persistent<Object> g1s1;
2454 Persistent<Object> g1s2;
2455 Persistent<Object> g1c1;
2456 Persistent<Object> g2s1;
2457 Persistent<Object> g2s2;
2458 Persistent<Object> g2c1;
2459
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002460 WeakCallCounter counter(1234);
2461
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00002462 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00002463 HandleScope scope(iso);
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00002464 g1s1 = Persistent<Object>::New(iso, Object::New());
2465 g1s2 = Persistent<Object>::New(iso, Object::New());
2466 g1c1 = Persistent<Object>::New(iso, Object::New());
2467 g1s1.MakeWeak(iso, reinterpret_cast<void*>(&counter), &WeakPointerCallback);
2468 g1s2.MakeWeak(iso, reinterpret_cast<void*>(&counter), &WeakPointerCallback);
2469 g1c1.MakeWeak(iso, reinterpret_cast<void*>(&counter), &WeakPointerCallback);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00002470
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00002471 g2s1 = Persistent<Object>::New(iso, Object::New());
2472 g2s2 = Persistent<Object>::New(iso, Object::New());
2473 g2c1 = Persistent<Object>::New(iso, Object::New());
2474 g2s1.MakeWeak(iso, reinterpret_cast<void*>(&counter), &WeakPointerCallback);
2475 g2s2.MakeWeak(iso, reinterpret_cast<void*>(&counter), &WeakPointerCallback);
2476 g2c1.MakeWeak(iso, reinterpret_cast<void*>(&counter), &WeakPointerCallback);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00002477 }
2478
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00002479 Persistent<Object> root = Persistent<Object>::New(iso, g1s1); // make a root.
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00002480
2481 // Connect group 1 and 2, make a cycle.
2482 CHECK(g1s2->Set(0, g2s2));
2483 CHECK(g2s1->Set(0, g1s1));
2484
2485 {
2486 Persistent<Value> g1_objects[] = { g1s1, g1s2 };
2487 Persistent<Value> g1_children[] = { g1c1 };
2488 Persistent<Value> g2_objects[] = { g2s1, g2s2 };
2489 Persistent<Value> g2_children[] = { g2c1 };
2490 V8::AddObjectGroup(g1_objects, 2);
2491 V8::AddImplicitReferences(g1s1, g1_children, 1);
2492 V8::AddObjectGroup(g2_objects, 2);
2493 V8::AddImplicitReferences(g2s2, g2_children, 1);
2494 }
erik.corry@gmail.combbceb572012-03-09 10:52:05 +00002495 // Do a single full GC, ensure incremental marking is stopped.
2496 HEAP->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00002497
2498 // All object should be alive.
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002499 CHECK_EQ(0, counter.NumberOfWeakCalls());
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00002500
2501 // Weaken the root.
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00002502 root.MakeWeak(iso, reinterpret_cast<void*>(&counter), &WeakPointerCallback);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00002503 // But make children strong roots---all the objects (except for children)
2504 // should be collectable now.
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00002505 g1c1.ClearWeak(iso);
2506 g2c1.ClearWeak(iso);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00002507
2508 // Groups are deleted, rebuild groups.
2509 {
2510 Persistent<Value> g1_objects[] = { g1s1, g1s2 };
2511 Persistent<Value> g1_children[] = { g1c1 };
2512 Persistent<Value> g2_objects[] = { g2s1, g2s2 };
2513 Persistent<Value> g2_children[] = { g2c1 };
2514 V8::AddObjectGroup(g1_objects, 2);
2515 V8::AddImplicitReferences(g1s1, g1_children, 1);
2516 V8::AddObjectGroup(g2_objects, 2);
2517 V8::AddImplicitReferences(g2s2, g2_children, 1);
2518 }
2519
erik.corry@gmail.combbceb572012-03-09 10:52:05 +00002520 HEAP->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00002521
2522 // All objects should be gone. 5 global handles in total.
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002523 CHECK_EQ(5, counter.NumberOfWeakCalls());
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00002524
2525 // And now make children weak again and collect them.
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00002526 g1c1.MakeWeak(iso, reinterpret_cast<void*>(&counter), &WeakPointerCallback);
2527 g2c1.MakeWeak(iso, reinterpret_cast<void*>(&counter), &WeakPointerCallback);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00002528
erik.corry@gmail.combbceb572012-03-09 10:52:05 +00002529 HEAP->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002530 CHECK_EQ(7, counter.NumberOfWeakCalls());
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00002531}
2532
2533
2534THREADED_TEST(ApiObjectGroupsCycle) {
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00002535 LocalContext env;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00002536 v8::Isolate* iso = env->GetIsolate();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00002537 HandleScope scope(iso);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00002538
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002539 WeakCallCounter counter(1234);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00002540
2541 Persistent<Object> g1s1;
2542 Persistent<Object> g1s2;
2543 Persistent<Object> g2s1;
2544 Persistent<Object> g2s2;
2545 Persistent<Object> g3s1;
2546 Persistent<Object> g3s2;
mstarzinger@chromium.org32280cf2012-12-06 17:32:37 +00002547 Persistent<Object> g4s1;
2548 Persistent<Object> g4s2;
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00002549
2550 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00002551 HandleScope scope(iso);
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00002552 g1s1 = Persistent<Object>::New(iso, Object::New());
2553 g1s2 = Persistent<Object>::New(iso, Object::New());
2554 g1s1.MakeWeak(iso, reinterpret_cast<void*>(&counter), &WeakPointerCallback);
2555 g1s2.MakeWeak(iso, reinterpret_cast<void*>(&counter), &WeakPointerCallback);
2556 CHECK(g1s1.IsWeak(iso));
2557 CHECK(g1s2.IsWeak(iso));
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00002558
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00002559 g2s1 = Persistent<Object>::New(iso, Object::New());
2560 g2s2 = Persistent<Object>::New(iso, Object::New());
2561 g2s1.MakeWeak(iso, reinterpret_cast<void*>(&counter), &WeakPointerCallback);
2562 g2s2.MakeWeak(iso, reinterpret_cast<void*>(&counter), &WeakPointerCallback);
2563 CHECK(g2s1.IsWeak(iso));
2564 CHECK(g2s2.IsWeak(iso));
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00002565
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00002566 g3s1 = Persistent<Object>::New(iso, Object::New());
2567 g3s2 = Persistent<Object>::New(iso, Object::New());
2568 g3s1.MakeWeak(iso, reinterpret_cast<void*>(&counter), &WeakPointerCallback);
2569 g3s2.MakeWeak(iso, reinterpret_cast<void*>(&counter), &WeakPointerCallback);
2570 CHECK(g3s1.IsWeak(iso));
2571 CHECK(g3s2.IsWeak(iso));
mstarzinger@chromium.org32280cf2012-12-06 17:32:37 +00002572
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00002573 g4s1 = Persistent<Object>::New(iso, Object::New());
2574 g4s2 = Persistent<Object>::New(iso, Object::New());
2575 g4s1.MakeWeak(iso, reinterpret_cast<void*>(&counter), &WeakPointerCallback);
2576 g4s2.MakeWeak(iso, reinterpret_cast<void*>(&counter), &WeakPointerCallback);
2577 CHECK(g4s1.IsWeak(iso));
2578 CHECK(g4s2.IsWeak(iso));
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00002579 }
2580
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00002581 Persistent<Object> root = Persistent<Object>::New(iso, g1s1); // make a root.
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00002582
2583 // Connect groups. We're building the following cycle:
2584 // G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other
2585 // groups.
2586 {
2587 Persistent<Value> g1_objects[] = { g1s1, g1s2 };
2588 Persistent<Value> g1_children[] = { g2s1 };
2589 Persistent<Value> g2_objects[] = { g2s1, g2s2 };
2590 Persistent<Value> g2_children[] = { g3s1 };
2591 Persistent<Value> g3_objects[] = { g3s1, g3s2 };
mstarzinger@chromium.org32280cf2012-12-06 17:32:37 +00002592 Persistent<Value> g3_children[] = { g4s1 };
2593 Persistent<Value> g4_objects[] = { g4s1, g4s2 };
2594 Persistent<Value> g4_children[] = { g1s1 };
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00002595 V8::AddObjectGroup(g1_objects, 2);
2596 V8::AddImplicitReferences(g1s1, g1_children, 1);
2597 V8::AddObjectGroup(g2_objects, 2);
2598 V8::AddImplicitReferences(g2s1, g2_children, 1);
2599 V8::AddObjectGroup(g3_objects, 2);
2600 V8::AddImplicitReferences(g3s1, g3_children, 1);
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00002601 V8::AddObjectGroup(iso, g4_objects, 2);
mstarzinger@chromium.org32280cf2012-12-06 17:32:37 +00002602 V8::AddImplicitReferences(g4s1, g4_children, 1);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00002603 }
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002604 // Do a single full GC
erik.corry@gmail.combbceb572012-03-09 10:52:05 +00002605 HEAP->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00002606
2607 // All object should be alive.
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002608 CHECK_EQ(0, counter.NumberOfWeakCalls());
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00002609
2610 // Weaken the root.
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00002611 root.MakeWeak(iso, reinterpret_cast<void*>(&counter), &WeakPointerCallback);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00002612
2613 // Groups are deleted, rebuild groups.
2614 {
2615 Persistent<Value> g1_objects[] = { g1s1, g1s2 };
2616 Persistent<Value> g1_children[] = { g2s1 };
2617 Persistent<Value> g2_objects[] = { g2s1, g2s2 };
2618 Persistent<Value> g2_children[] = { g3s1 };
2619 Persistent<Value> g3_objects[] = { g3s1, g3s2 };
mstarzinger@chromium.org32280cf2012-12-06 17:32:37 +00002620 Persistent<Value> g3_children[] = { g4s1 };
2621 Persistent<Value> g4_objects[] = { g4s1, g4s2 };
2622 Persistent<Value> g4_children[] = { g1s1 };
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00002623 V8::AddObjectGroup(g1_objects, 2);
2624 V8::AddImplicitReferences(g1s1, g1_children, 1);
2625 V8::AddObjectGroup(g2_objects, 2);
2626 V8::AddImplicitReferences(g2s1, g2_children, 1);
2627 V8::AddObjectGroup(g3_objects, 2);
2628 V8::AddImplicitReferences(g3s1, g3_children, 1);
mstarzinger@chromium.org32280cf2012-12-06 17:32:37 +00002629 V8::AddObjectGroup(g4_objects, 2);
2630 V8::AddImplicitReferences(g4s1, g4_children, 1);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00002631 }
2632
erik.corry@gmail.combbceb572012-03-09 10:52:05 +00002633 HEAP->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00002634
mstarzinger@chromium.org32280cf2012-12-06 17:32:37 +00002635 // All objects should be gone. 9 global handles in total.
2636 CHECK_EQ(9, counter.NumberOfWeakCalls());
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00002637}
2638
2639
mvstanton@chromium.orge4ac3ef2012-11-12 14:53:34 +00002640// TODO(mstarzinger): This should be a THREADED_TEST but causes failures
2641// on the buildbots, so was made non-threaded for the time being.
2642TEST(ApiObjectGroupsCycleForScavenger) {
svenpanne@chromium.org83130cf2012-11-30 10:13:25 +00002643 i::FLAG_stress_compaction = false;
2644 i::FLAG_gc_global = false;
mvstanton@chromium.orge4ac3ef2012-11-12 14:53:34 +00002645 LocalContext env;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00002646 v8::Isolate* iso = env->GetIsolate();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00002647 HandleScope scope(iso);
mvstanton@chromium.orge4ac3ef2012-11-12 14:53:34 +00002648
2649 WeakCallCounter counter(1234);
2650
2651 Persistent<Object> g1s1;
2652 Persistent<Object> g1s2;
2653 Persistent<Object> g2s1;
2654 Persistent<Object> g2s2;
2655 Persistent<Object> g3s1;
2656 Persistent<Object> g3s2;
2657
2658 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00002659 HandleScope scope(iso);
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00002660 g1s1 = Persistent<Object>::New(iso, Object::New());
2661 g1s2 = Persistent<Object>::New(iso, Object::New());
2662 g1s1.MakeWeak(iso, reinterpret_cast<void*>(&counter), &WeakPointerCallback);
2663 g1s2.MakeWeak(iso, reinterpret_cast<void*>(&counter), &WeakPointerCallback);
mvstanton@chromium.orge4ac3ef2012-11-12 14:53:34 +00002664
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00002665 g2s1 = Persistent<Object>::New(iso, Object::New());
2666 g2s2 = Persistent<Object>::New(iso, Object::New());
2667 g2s1.MakeWeak(iso, reinterpret_cast<void*>(&counter), &WeakPointerCallback);
2668 g2s2.MakeWeak(iso, reinterpret_cast<void*>(&counter), &WeakPointerCallback);
mvstanton@chromium.orge4ac3ef2012-11-12 14:53:34 +00002669
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00002670 g3s1 = Persistent<Object>::New(iso, Object::New());
2671 g3s2 = Persistent<Object>::New(iso, Object::New());
2672 g3s1.MakeWeak(iso, reinterpret_cast<void*>(&counter), &WeakPointerCallback);
2673 g3s2.MakeWeak(iso, reinterpret_cast<void*>(&counter), &WeakPointerCallback);
mvstanton@chromium.orge4ac3ef2012-11-12 14:53:34 +00002674 }
2675
2676 // Make a root.
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00002677 Persistent<Object> root = Persistent<Object>::New(iso, g1s1);
2678 root.MarkPartiallyDependent(iso);
mvstanton@chromium.orge4ac3ef2012-11-12 14:53:34 +00002679
2680 // Connect groups. We're building the following cycle:
2681 // G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other
2682 // groups.
2683 {
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00002684 g1s1.MarkPartiallyDependent(iso);
2685 g1s2.MarkPartiallyDependent(iso);
2686 g2s1.MarkPartiallyDependent(iso);
2687 g2s2.MarkPartiallyDependent(iso);
2688 g3s1.MarkPartiallyDependent(iso);
2689 g3s2.MarkPartiallyDependent(iso);
mvstanton@chromium.orge4ac3ef2012-11-12 14:53:34 +00002690 Persistent<Value> g1_objects[] = { g1s1, g1s2 };
2691 Persistent<Value> g2_objects[] = { g2s1, g2s2 };
2692 Persistent<Value> g3_objects[] = { g3s1, g3s2 };
2693 V8::AddObjectGroup(g1_objects, 2);
2694 g1s1->Set(v8_str("x"), g2s1);
2695 V8::AddObjectGroup(g2_objects, 2);
2696 g2s1->Set(v8_str("x"), g3s1);
2697 V8::AddObjectGroup(g3_objects, 2);
2698 g3s1->Set(v8_str("x"), g1s1);
2699 }
2700
2701 HEAP->CollectGarbage(i::NEW_SPACE);
2702
2703 // All objects should be alive.
2704 CHECK_EQ(0, counter.NumberOfWeakCalls());
2705
2706 // Weaken the root.
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00002707 root.MakeWeak(iso, reinterpret_cast<void*>(&counter), &WeakPointerCallback);
2708 root.MarkPartiallyDependent(iso);
mvstanton@chromium.orge4ac3ef2012-11-12 14:53:34 +00002709
2710 v8::Isolate* isolate = v8::Isolate::GetCurrent();
2711 // Groups are deleted, rebuild groups.
2712 {
2713 g1s1.MarkPartiallyDependent(isolate);
2714 g1s2.MarkPartiallyDependent(isolate);
2715 g2s1.MarkPartiallyDependent(isolate);
2716 g2s2.MarkPartiallyDependent(isolate);
2717 g3s1.MarkPartiallyDependent(isolate);
2718 g3s2.MarkPartiallyDependent(isolate);
2719 Persistent<Value> g1_objects[] = { g1s1, g1s2 };
2720 Persistent<Value> g2_objects[] = { g2s1, g2s2 };
2721 Persistent<Value> g3_objects[] = { g3s1, g3s2 };
2722 V8::AddObjectGroup(g1_objects, 2);
2723 g1s1->Set(v8_str("x"), g2s1);
2724 V8::AddObjectGroup(g2_objects, 2);
2725 g2s1->Set(v8_str("x"), g3s1);
2726 V8::AddObjectGroup(g3_objects, 2);
2727 g3s1->Set(v8_str("x"), g1s1);
2728 }
2729
2730 HEAP->CollectGarbage(i::NEW_SPACE);
2731
2732 // All objects should be gone. 7 global handles in total.
2733 CHECK_EQ(7, counter.NumberOfWeakCalls());
2734}
2735
2736
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002737THREADED_TEST(ScriptException) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002738 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00002739 v8::HandleScope scope(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002740 Local<Script> script = Script::Compile(v8_str("throw 'panama!';"));
2741 v8::TryCatch try_catch;
2742 Local<Value> result = script->Run();
2743 CHECK(result.IsEmpty());
2744 CHECK(try_catch.HasCaught());
2745 String::AsciiValue exception_value(try_catch.Exception());
2746 CHECK_EQ(*exception_value, "panama!");
2747}
2748
2749
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002750TEST(TryCatchCustomException) {
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002751 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00002752 v8::HandleScope scope(env->GetIsolate());
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002753 v8::TryCatch try_catch;
2754 CompileRun("function CustomError() { this.a = 'b'; }"
2755 "(function f() { throw new CustomError(); })();");
2756 CHECK(try_catch.HasCaught());
2757 CHECK(try_catch.Exception()->ToObject()->
2758 Get(v8_str("a"))->Equals(v8_str("b")));
2759}
2760
2761
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002762bool message_received;
2763
2764
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00002765static void check_message_0(v8::Handle<v8::Message> message,
2766 v8::Handle<Value> data) {
hpayer@chromium.org8432c912013-02-28 15:55:26 +00002767 CHECK_EQ(5.76, data->NumberValue());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002768 CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002769 CHECK_EQ(7.56, message->GetScriptData()->NumberValue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002770 message_received = true;
2771}
2772
2773
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00002774THREADED_TEST(MessageHandler0) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002775 message_received = false;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00002776 v8::HandleScope scope(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002777 CHECK(!message_received);
hpayer@chromium.org8432c912013-02-28 15:55:26 +00002778 v8::V8::AddMessageListener(check_message_0, v8_num(5.76));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002779 LocalContext context;
2780 v8::ScriptOrigin origin =
2781 v8::ScriptOrigin(v8_str("6.75"));
ager@chromium.org65dad4b2009-04-23 08:48:43 +00002782 v8::Handle<v8::Script> script = Script::Compile(v8_str("throw 'error'"),
2783 &origin);
2784 script->SetData(v8_str("7.56"));
2785 script->Run();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002786 CHECK(message_received);
2787 // clear out the message listener
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00002788 v8::V8::RemoveMessageListeners(check_message_0);
2789}
2790
2791
2792static void check_message_1(v8::Handle<v8::Message> message,
2793 v8::Handle<Value> data) {
2794 CHECK(data->IsNumber());
2795 CHECK_EQ(1337, data->Int32Value());
2796 message_received = true;
2797}
2798
2799
2800TEST(MessageHandler1) {
2801 message_received = false;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00002802 v8::HandleScope scope(v8::Isolate::GetCurrent());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00002803 CHECK(!message_received);
2804 v8::V8::AddMessageListener(check_message_1);
2805 LocalContext context;
2806 CompileRun("throw 1337;");
2807 CHECK(message_received);
2808 // clear out the message listener
2809 v8::V8::RemoveMessageListeners(check_message_1);
2810}
2811
2812
2813static void check_message_2(v8::Handle<v8::Message> message,
2814 v8::Handle<Value> data) {
2815 LocalContext context;
2816 CHECK(data->IsObject());
2817 v8::Local<v8::Value> hidden_property =
2818 v8::Object::Cast(*data)->GetHiddenValue(v8_str("hidden key"));
2819 CHECK(v8_str("hidden value")->Equals(hidden_property));
2820 message_received = true;
2821}
2822
2823
2824TEST(MessageHandler2) {
2825 message_received = false;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00002826 v8::HandleScope scope(v8::Isolate::GetCurrent());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00002827 CHECK(!message_received);
2828 v8::V8::AddMessageListener(check_message_2);
2829 LocalContext context;
2830 v8::Local<v8::Value> error = v8::Exception::Error(v8_str("custom error"));
2831 v8::Object::Cast(*error)->SetHiddenValue(v8_str("hidden key"),
2832 v8_str("hidden value"));
2833 context->Global()->Set(v8_str("error"), error);
2834 CompileRun("throw error;");
2835 CHECK(message_received);
2836 // clear out the message listener
2837 v8::V8::RemoveMessageListeners(check_message_2);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002838}
2839
2840
2841THREADED_TEST(GetSetProperty) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002842 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00002843 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002844 context->Global()->Set(v8_str("foo"), v8_num(14));
2845 context->Global()->Set(v8_str("12"), v8_num(92));
2846 context->Global()->Set(v8::Integer::New(16), v8_num(32));
2847 context->Global()->Set(v8_num(13), v8_num(56));
2848 Local<Value> foo = Script::Compile(v8_str("this.foo"))->Run();
2849 CHECK_EQ(14, foo->Int32Value());
2850 Local<Value> twelve = Script::Compile(v8_str("this[12]"))->Run();
2851 CHECK_EQ(92, twelve->Int32Value());
2852 Local<Value> sixteen = Script::Compile(v8_str("this[16]"))->Run();
2853 CHECK_EQ(32, sixteen->Int32Value());
2854 Local<Value> thirteen = Script::Compile(v8_str("this[13]"))->Run();
2855 CHECK_EQ(56, thirteen->Int32Value());
2856 CHECK_EQ(92, context->Global()->Get(v8::Integer::New(12))->Int32Value());
2857 CHECK_EQ(92, context->Global()->Get(v8_str("12"))->Int32Value());
2858 CHECK_EQ(92, context->Global()->Get(v8_num(12))->Int32Value());
2859 CHECK_EQ(32, context->Global()->Get(v8::Integer::New(16))->Int32Value());
2860 CHECK_EQ(32, context->Global()->Get(v8_str("16"))->Int32Value());
2861 CHECK_EQ(32, context->Global()->Get(v8_num(16))->Int32Value());
2862 CHECK_EQ(56, context->Global()->Get(v8::Integer::New(13))->Int32Value());
2863 CHECK_EQ(56, context->Global()->Get(v8_str("13"))->Int32Value());
2864 CHECK_EQ(56, context->Global()->Get(v8_num(13))->Int32Value());
2865}
2866
2867
2868THREADED_TEST(PropertyAttributes) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002869 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00002870 v8::HandleScope scope(context->GetIsolate());
rossberg@chromium.org717967f2011-07-20 13:44:42 +00002871 // none
2872 Local<String> prop = v8_str("none");
2873 context->Global()->Set(prop, v8_num(7));
2874 CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(prop));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002875 // read-only
rossberg@chromium.org717967f2011-07-20 13:44:42 +00002876 prop = v8_str("read_only");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002877 context->Global()->Set(prop, v8_num(7), v8::ReadOnly);
2878 CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
rossberg@chromium.org717967f2011-07-20 13:44:42 +00002879 CHECK_EQ(v8::ReadOnly, context->Global()->GetPropertyAttributes(prop));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002880 Script::Compile(v8_str("read_only = 9"))->Run();
2881 CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
2882 context->Global()->Set(prop, v8_num(10));
2883 CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
2884 // dont-delete
2885 prop = v8_str("dont_delete");
2886 context->Global()->Set(prop, v8_num(13), v8::DontDelete);
2887 CHECK_EQ(13, context->Global()->Get(prop)->Int32Value());
2888 Script::Compile(v8_str("delete dont_delete"))->Run();
2889 CHECK_EQ(13, context->Global()->Get(prop)->Int32Value());
rossberg@chromium.org717967f2011-07-20 13:44:42 +00002890 CHECK_EQ(v8::DontDelete, context->Global()->GetPropertyAttributes(prop));
2891 // dont-enum
2892 prop = v8_str("dont_enum");
2893 context->Global()->Set(prop, v8_num(28), v8::DontEnum);
2894 CHECK_EQ(v8::DontEnum, context->Global()->GetPropertyAttributes(prop));
2895 // absent
2896 prop = v8_str("absent");
2897 CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(prop));
2898 Local<Value> fake_prop = v8_num(1);
2899 CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(fake_prop));
2900 // exception
2901 TryCatch try_catch;
2902 Local<Value> exception =
2903 CompileRun("({ toString: function() { throw 'exception';} })");
2904 CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(exception));
2905 CHECK(try_catch.HasCaught());
2906 String::AsciiValue exception_value(try_catch.Exception());
2907 CHECK_EQ("exception", *exception_value);
2908 try_catch.Reset();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002909}
2910
2911
2912THREADED_TEST(Array) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002913 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00002914 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002915 Local<v8::Array> array = v8::Array::New();
2916 CHECK_EQ(0, array->Length());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002917 CHECK(array->Get(0)->IsUndefined());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002918 CHECK(!array->Has(0));
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002919 CHECK(array->Get(100)->IsUndefined());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002920 CHECK(!array->Has(100));
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002921 array->Set(2, v8_num(7));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002922 CHECK_EQ(3, array->Length());
2923 CHECK(!array->Has(0));
2924 CHECK(!array->Has(1));
2925 CHECK(array->Has(2));
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002926 CHECK_EQ(7, array->Get(2)->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002927 Local<Value> obj = Script::Compile(v8_str("[1, 2, 3]"))->Run();
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002928 Local<v8::Array> arr = obj.As<v8::Array>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002929 CHECK_EQ(3, arr->Length());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002930 CHECK_EQ(1, arr->Get(0)->Int32Value());
2931 CHECK_EQ(2, arr->Get(1)->Int32Value());
2932 CHECK_EQ(3, arr->Get(2)->Int32Value());
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00002933 array = v8::Array::New(27);
2934 CHECK_EQ(27, array->Length());
2935 array = v8::Array::New(-27);
2936 CHECK_EQ(0, array->Length());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002937}
2938
2939
2940v8::Handle<Value> HandleF(const v8::Arguments& args) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00002941 v8::HandleScope scope(args.GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002942 ApiTestFuzzer::Fuzz();
2943 Local<v8::Array> result = v8::Array::New(args.Length());
2944 for (int i = 0; i < args.Length(); i++)
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002945 result->Set(i, args[i]);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002946 return scope.Close(result);
2947}
2948
2949
2950THREADED_TEST(Vector) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00002951 v8::HandleScope scope(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002952 Local<ObjectTemplate> global = ObjectTemplate::New();
2953 global->Set(v8_str("f"), v8::FunctionTemplate::New(HandleF));
2954 LocalContext context(0, global);
2955
2956 const char* fun = "f()";
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002957 Local<v8::Array> a0 = CompileRun(fun).As<v8::Array>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002958 CHECK_EQ(0, a0->Length());
2959
2960 const char* fun2 = "f(11)";
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002961 Local<v8::Array> a1 = CompileRun(fun2).As<v8::Array>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002962 CHECK_EQ(1, a1->Length());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002963 CHECK_EQ(11, a1->Get(0)->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002964
2965 const char* fun3 = "f(12, 13)";
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002966 Local<v8::Array> a2 = CompileRun(fun3).As<v8::Array>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002967 CHECK_EQ(2, a2->Length());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002968 CHECK_EQ(12, a2->Get(0)->Int32Value());
2969 CHECK_EQ(13, a2->Get(1)->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002970
2971 const char* fun4 = "f(14, 15, 16)";
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002972 Local<v8::Array> a3 = CompileRun(fun4).As<v8::Array>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002973 CHECK_EQ(3, a3->Length());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002974 CHECK_EQ(14, a3->Get(0)->Int32Value());
2975 CHECK_EQ(15, a3->Get(1)->Int32Value());
2976 CHECK_EQ(16, a3->Get(2)->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002977
2978 const char* fun5 = "f(17, 18, 19, 20)";
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002979 Local<v8::Array> a4 = CompileRun(fun5).As<v8::Array>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002980 CHECK_EQ(4, a4->Length());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002981 CHECK_EQ(17, a4->Get(0)->Int32Value());
2982 CHECK_EQ(18, a4->Get(1)->Int32Value());
2983 CHECK_EQ(19, a4->Get(2)->Int32Value());
2984 CHECK_EQ(20, a4->Get(3)->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002985}
2986
2987
2988THREADED_TEST(FunctionCall) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002989 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00002990 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002991 CompileRun(
2992 "function Foo() {"
2993 " var result = [];"
2994 " for (var i = 0; i < arguments.length; i++) {"
2995 " result.push(arguments[i]);"
2996 " }"
2997 " return result;"
2998 "}");
2999 Local<Function> Foo =
3000 Local<Function>::Cast(context->Global()->Get(v8_str("Foo")));
3001
3002 v8::Handle<Value>* args0 = NULL;
3003 Local<v8::Array> a0 = Local<v8::Array>::Cast(Foo->Call(Foo, 0, args0));
3004 CHECK_EQ(0, a0->Length());
3005
3006 v8::Handle<Value> args1[] = { v8_num(1.1) };
3007 Local<v8::Array> a1 = Local<v8::Array>::Cast(Foo->Call(Foo, 1, args1));
3008 CHECK_EQ(1, a1->Length());
3009 CHECK_EQ(1.1, a1->Get(v8::Integer::New(0))->NumberValue());
3010
3011 v8::Handle<Value> args2[] = { v8_num(2.2),
3012 v8_num(3.3) };
3013 Local<v8::Array> a2 = Local<v8::Array>::Cast(Foo->Call(Foo, 2, args2));
3014 CHECK_EQ(2, a2->Length());
3015 CHECK_EQ(2.2, a2->Get(v8::Integer::New(0))->NumberValue());
3016 CHECK_EQ(3.3, a2->Get(v8::Integer::New(1))->NumberValue());
3017
3018 v8::Handle<Value> args3[] = { v8_num(4.4),
3019 v8_num(5.5),
3020 v8_num(6.6) };
3021 Local<v8::Array> a3 = Local<v8::Array>::Cast(Foo->Call(Foo, 3, args3));
3022 CHECK_EQ(3, a3->Length());
3023 CHECK_EQ(4.4, a3->Get(v8::Integer::New(0))->NumberValue());
3024 CHECK_EQ(5.5, a3->Get(v8::Integer::New(1))->NumberValue());
3025 CHECK_EQ(6.6, a3->Get(v8::Integer::New(2))->NumberValue());
3026
3027 v8::Handle<Value> args4[] = { v8_num(7.7),
3028 v8_num(8.8),
3029 v8_num(9.9),
3030 v8_num(10.11) };
3031 Local<v8::Array> a4 = Local<v8::Array>::Cast(Foo->Call(Foo, 4, args4));
3032 CHECK_EQ(4, a4->Length());
3033 CHECK_EQ(7.7, a4->Get(v8::Integer::New(0))->NumberValue());
3034 CHECK_EQ(8.8, a4->Get(v8::Integer::New(1))->NumberValue());
3035 CHECK_EQ(9.9, a4->Get(v8::Integer::New(2))->NumberValue());
3036 CHECK_EQ(10.11, a4->Get(v8::Integer::New(3))->NumberValue());
3037}
3038
3039
3040static const char* js_code_causing_out_of_memory =
3041 "var a = new Array(); while(true) a.push(a);";
3042
3043
3044// These tests run for a long time and prevent us from running tests
3045// that come after them so they cannot run in parallel.
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00003046TEST(OutOfMemory) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003047 // It's not possible to read a snapshot into a heap with different dimensions.
lrn@chromium.org32d961d2010-06-30 09:09:34 +00003048 if (i::Snapshot::IsEnabled()) return;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003049 // Set heap limits.
3050 static const int K = 1024;
3051 v8::ResourceConstraints constraints;
3052 constraints.set_max_young_space_size(256 * K);
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00003053 constraints.set_max_old_space_size(4 * K * K);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003054 v8::SetResourceConstraints(&constraints);
3055
3056 // Execute a script that causes out of memory.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003057 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003058 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003059 v8::V8::IgnoreOutOfMemoryException();
3060 Local<Script> script =
3061 Script::Compile(String::New(js_code_causing_out_of_memory));
3062 Local<Value> result = script->Run();
3063
3064 // Check for out of memory state.
3065 CHECK(result.IsEmpty());
3066 CHECK(context->HasOutOfMemoryException());
3067}
3068
3069
3070v8::Handle<Value> ProvokeOutOfMemory(const v8::Arguments& args) {
3071 ApiTestFuzzer::Fuzz();
3072
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003073 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003074 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003075 Local<Script> script =
3076 Script::Compile(String::New(js_code_causing_out_of_memory));
3077 Local<Value> result = script->Run();
3078
3079 // Check for out of memory state.
3080 CHECK(result.IsEmpty());
3081 CHECK(context->HasOutOfMemoryException());
3082
3083 return result;
3084}
3085
3086
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00003087TEST(OutOfMemoryNested) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003088 // It's not possible to read a snapshot into a heap with different dimensions.
lrn@chromium.org32d961d2010-06-30 09:09:34 +00003089 if (i::Snapshot::IsEnabled()) return;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003090 // Set heap limits.
3091 static const int K = 1024;
3092 v8::ResourceConstraints constraints;
3093 constraints.set_max_young_space_size(256 * K);
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00003094 constraints.set_max_old_space_size(4 * K * K);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003095 v8::SetResourceConstraints(&constraints);
3096
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003097 v8::HandleScope scope(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003098 Local<ObjectTemplate> templ = ObjectTemplate::New();
3099 templ->Set(v8_str("ProvokeOutOfMemory"),
3100 v8::FunctionTemplate::New(ProvokeOutOfMemory));
3101 LocalContext context(0, templ);
3102 v8::V8::IgnoreOutOfMemoryException();
3103 Local<Value> result = CompileRun(
3104 "var thrown = false;"
3105 "try {"
3106 " ProvokeOutOfMemory();"
3107 "} catch (e) {"
3108 " thrown = true;"
3109 "}");
3110 // Check for out of memory state.
3111 CHECK(result.IsEmpty());
3112 CHECK(context->HasOutOfMemoryException());
3113}
3114
3115
3116TEST(HugeConsStringOutOfMemory) {
3117 // It's not possible to read a snapshot into a heap with different dimensions.
lrn@chromium.org32d961d2010-06-30 09:09:34 +00003118 if (i::Snapshot::IsEnabled()) return;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003119 // Set heap limits.
3120 static const int K = 1024;
3121 v8::ResourceConstraints constraints;
3122 constraints.set_max_young_space_size(256 * K);
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +00003123 constraints.set_max_old_space_size(3 * K * K);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003124 v8::SetResourceConstraints(&constraints);
3125
3126 // Execute a script that causes out of memory.
3127 v8::V8::IgnoreOutOfMemoryException();
3128
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00003129 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003130 v8::HandleScope scope(context->GetIsolate());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00003131
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003132 // Build huge string. This should fail with out of memory exception.
3133 Local<Value> result = CompileRun(
3134 "var str = Array.prototype.join.call({length: 513}, \"A\").toUpperCase();"
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00003135 "for (var i = 0; i < 22; i++) { str = str + str; }");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003136
3137 // Check for out of memory state.
3138 CHECK(result.IsEmpty());
3139 CHECK(context->HasOutOfMemoryException());
3140}
3141
3142
3143THREADED_TEST(ConstructCall) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003144 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003145 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003146 CompileRun(
3147 "function Foo() {"
3148 " var result = [];"
3149 " for (var i = 0; i < arguments.length; i++) {"
3150 " result.push(arguments[i]);"
3151 " }"
3152 " return result;"
3153 "}");
3154 Local<Function> Foo =
3155 Local<Function>::Cast(context->Global()->Get(v8_str("Foo")));
3156
3157 v8::Handle<Value>* args0 = NULL;
3158 Local<v8::Array> a0 = Local<v8::Array>::Cast(Foo->NewInstance(0, args0));
3159 CHECK_EQ(0, a0->Length());
3160
3161 v8::Handle<Value> args1[] = { v8_num(1.1) };
3162 Local<v8::Array> a1 = Local<v8::Array>::Cast(Foo->NewInstance(1, args1));
3163 CHECK_EQ(1, a1->Length());
3164 CHECK_EQ(1.1, a1->Get(v8::Integer::New(0))->NumberValue());
3165
3166 v8::Handle<Value> args2[] = { v8_num(2.2),
3167 v8_num(3.3) };
3168 Local<v8::Array> a2 = Local<v8::Array>::Cast(Foo->NewInstance(2, args2));
3169 CHECK_EQ(2, a2->Length());
3170 CHECK_EQ(2.2, a2->Get(v8::Integer::New(0))->NumberValue());
3171 CHECK_EQ(3.3, a2->Get(v8::Integer::New(1))->NumberValue());
3172
3173 v8::Handle<Value> args3[] = { v8_num(4.4),
3174 v8_num(5.5),
3175 v8_num(6.6) };
3176 Local<v8::Array> a3 = Local<v8::Array>::Cast(Foo->NewInstance(3, args3));
3177 CHECK_EQ(3, a3->Length());
3178 CHECK_EQ(4.4, a3->Get(v8::Integer::New(0))->NumberValue());
3179 CHECK_EQ(5.5, a3->Get(v8::Integer::New(1))->NumberValue());
3180 CHECK_EQ(6.6, a3->Get(v8::Integer::New(2))->NumberValue());
3181
3182 v8::Handle<Value> args4[] = { v8_num(7.7),
3183 v8_num(8.8),
3184 v8_num(9.9),
3185 v8_num(10.11) };
3186 Local<v8::Array> a4 = Local<v8::Array>::Cast(Foo->NewInstance(4, args4));
3187 CHECK_EQ(4, a4->Length());
3188 CHECK_EQ(7.7, a4->Get(v8::Integer::New(0))->NumberValue());
3189 CHECK_EQ(8.8, a4->Get(v8::Integer::New(1))->NumberValue());
3190 CHECK_EQ(9.9, a4->Get(v8::Integer::New(2))->NumberValue());
3191 CHECK_EQ(10.11, a4->Get(v8::Integer::New(3))->NumberValue());
3192}
3193
3194
3195static void CheckUncle(v8::TryCatch* try_catch) {
3196 CHECK(try_catch->HasCaught());
3197 String::AsciiValue str_value(try_catch->Exception());
3198 CHECK_EQ(*str_value, "uncle?");
3199 try_catch->Reset();
3200}
3201
3202
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00003203THREADED_TEST(ConversionNumber) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00003204 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003205 v8::HandleScope scope(env->GetIsolate());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00003206 // Very large number.
3207 CompileRun("var obj = Math.pow(2,32) * 1237;");
3208 Local<Value> obj = env->Global()->Get(v8_str("obj"));
3209 CHECK_EQ(5312874545152.0, obj->ToNumber()->Value());
3210 CHECK_EQ(0, obj->ToInt32()->Value());
3211 CHECK(0u == obj->ToUint32()->Value()); // NOLINT - no CHECK_EQ for unsigned.
3212 // Large number.
3213 CompileRun("var obj = -1234567890123;");
3214 obj = env->Global()->Get(v8_str("obj"));
3215 CHECK_EQ(-1234567890123.0, obj->ToNumber()->Value());
3216 CHECK_EQ(-1912276171, obj->ToInt32()->Value());
3217 CHECK(2382691125u == obj->ToUint32()->Value()); // NOLINT
3218 // Small positive integer.
3219 CompileRun("var obj = 42;");
3220 obj = env->Global()->Get(v8_str("obj"));
3221 CHECK_EQ(42.0, obj->ToNumber()->Value());
3222 CHECK_EQ(42, obj->ToInt32()->Value());
3223 CHECK(42u == obj->ToUint32()->Value()); // NOLINT
3224 // Negative integer.
3225 CompileRun("var obj = -37;");
3226 obj = env->Global()->Get(v8_str("obj"));
3227 CHECK_EQ(-37.0, obj->ToNumber()->Value());
3228 CHECK_EQ(-37, obj->ToInt32()->Value());
3229 CHECK(4294967259u == obj->ToUint32()->Value()); // NOLINT
3230 // Positive non-int32 integer.
3231 CompileRun("var obj = 0x81234567;");
3232 obj = env->Global()->Get(v8_str("obj"));
3233 CHECK_EQ(2166572391.0, obj->ToNumber()->Value());
3234 CHECK_EQ(-2128394905, obj->ToInt32()->Value());
3235 CHECK(2166572391u == obj->ToUint32()->Value()); // NOLINT
3236 // Fraction.
3237 CompileRun("var obj = 42.3;");
3238 obj = env->Global()->Get(v8_str("obj"));
3239 CHECK_EQ(42.3, obj->ToNumber()->Value());
3240 CHECK_EQ(42, obj->ToInt32()->Value());
3241 CHECK(42u == obj->ToUint32()->Value()); // NOLINT
3242 // Large negative fraction.
3243 CompileRun("var obj = -5726623061.75;");
3244 obj = env->Global()->Get(v8_str("obj"));
3245 CHECK_EQ(-5726623061.75, obj->ToNumber()->Value());
3246 CHECK_EQ(-1431655765, obj->ToInt32()->Value());
3247 CHECK(2863311531u == obj->ToUint32()->Value()); // NOLINT
3248}
3249
3250
3251THREADED_TEST(isNumberType) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00003252 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003253 v8::HandleScope scope(env->GetIsolate());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00003254 // Very large number.
3255 CompileRun("var obj = Math.pow(2,32) * 1237;");
3256 Local<Value> obj = env->Global()->Get(v8_str("obj"));
3257 CHECK(!obj->IsInt32());
3258 CHECK(!obj->IsUint32());
3259 // Large negative number.
3260 CompileRun("var obj = -1234567890123;");
3261 obj = env->Global()->Get(v8_str("obj"));
3262 CHECK(!obj->IsInt32());
3263 CHECK(!obj->IsUint32());
3264 // Small positive integer.
3265 CompileRun("var obj = 42;");
3266 obj = env->Global()->Get(v8_str("obj"));
3267 CHECK(obj->IsInt32());
3268 CHECK(obj->IsUint32());
3269 // Negative integer.
3270 CompileRun("var obj = -37;");
3271 obj = env->Global()->Get(v8_str("obj"));
3272 CHECK(obj->IsInt32());
3273 CHECK(!obj->IsUint32());
3274 // Positive non-int32 integer.
3275 CompileRun("var obj = 0x81234567;");
3276 obj = env->Global()->Get(v8_str("obj"));
3277 CHECK(!obj->IsInt32());
3278 CHECK(obj->IsUint32());
3279 // Fraction.
3280 CompileRun("var obj = 42.3;");
3281 obj = env->Global()->Get(v8_str("obj"));
3282 CHECK(!obj->IsInt32());
3283 CHECK(!obj->IsUint32());
3284 // Large negative fraction.
3285 CompileRun("var obj = -5726623061.75;");
3286 obj = env->Global()->Get(v8_str("obj"));
3287 CHECK(!obj->IsInt32());
3288 CHECK(!obj->IsUint32());
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00003289 // Positive zero
3290 CompileRun("var obj = 0.0;");
3291 obj = env->Global()->Get(v8_str("obj"));
3292 CHECK(obj->IsInt32());
3293 CHECK(obj->IsUint32());
3294 // Positive zero
3295 CompileRun("var obj = -0.0;");
3296 obj = env->Global()->Get(v8_str("obj"));
3297 CHECK(!obj->IsInt32());
3298 CHECK(!obj->IsUint32());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00003299}
3300
3301
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003302THREADED_TEST(ConversionException) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003303 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003304 v8::HandleScope scope(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003305 CompileRun(
3306 "function TestClass() { };"
3307 "TestClass.prototype.toString = function () { throw 'uncle?'; };"
3308 "var obj = new TestClass();");
3309 Local<Value> obj = env->Global()->Get(v8_str("obj"));
3310
3311 v8::TryCatch try_catch;
3312
3313 Local<Value> to_string_result = obj->ToString();
3314 CHECK(to_string_result.IsEmpty());
3315 CheckUncle(&try_catch);
3316
3317 Local<Value> to_number_result = obj->ToNumber();
3318 CHECK(to_number_result.IsEmpty());
3319 CheckUncle(&try_catch);
3320
3321 Local<Value> to_integer_result = obj->ToInteger();
3322 CHECK(to_integer_result.IsEmpty());
3323 CheckUncle(&try_catch);
3324
3325 Local<Value> to_uint32_result = obj->ToUint32();
3326 CHECK(to_uint32_result.IsEmpty());
3327 CheckUncle(&try_catch);
3328
3329 Local<Value> to_int32_result = obj->ToInt32();
3330 CHECK(to_int32_result.IsEmpty());
3331 CheckUncle(&try_catch);
3332
3333 Local<Value> to_object_result = v8::Undefined()->ToObject();
3334 CHECK(to_object_result.IsEmpty());
3335 CHECK(try_catch.HasCaught());
3336 try_catch.Reset();
3337
3338 int32_t int32_value = obj->Int32Value();
3339 CHECK_EQ(0, int32_value);
3340 CheckUncle(&try_catch);
3341
3342 uint32_t uint32_value = obj->Uint32Value();
3343 CHECK_EQ(0, uint32_value);
3344 CheckUncle(&try_catch);
3345
3346 double number_value = obj->NumberValue();
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00003347 CHECK_NE(0, isnan(number_value));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003348 CheckUncle(&try_catch);
3349
3350 int64_t integer_value = obj->IntegerValue();
3351 CHECK_EQ(0.0, static_cast<double>(integer_value));
3352 CheckUncle(&try_catch);
3353}
3354
3355
3356v8::Handle<Value> ThrowFromC(const v8::Arguments& args) {
3357 ApiTestFuzzer::Fuzz();
3358 return v8::ThrowException(v8_str("konto"));
3359}
3360
3361
ager@chromium.org8bb60582008-12-11 12:02:20 +00003362v8::Handle<Value> CCatcher(const v8::Arguments& args) {
yangguo@chromium.org80c42ed2011-08-31 09:03:56 +00003363 if (args.Length() < 1) return v8::False();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003364 v8::HandleScope scope(args.GetIsolate());
ager@chromium.org8bb60582008-12-11 12:02:20 +00003365 v8::TryCatch try_catch;
ager@chromium.org71daaf62009-04-01 07:22:49 +00003366 Local<Value> result = v8::Script::Compile(args[0]->ToString())->Run();
3367 CHECK(!try_catch.HasCaught() || result.IsEmpty());
ager@chromium.org8bb60582008-12-11 12:02:20 +00003368 return v8::Boolean::New(try_catch.HasCaught());
3369}
3370
3371
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003372THREADED_TEST(APICatch) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003373 v8::HandleScope scope(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003374 Local<ObjectTemplate> templ = ObjectTemplate::New();
3375 templ->Set(v8_str("ThrowFromC"),
3376 v8::FunctionTemplate::New(ThrowFromC));
3377 LocalContext context(0, templ);
3378 CompileRun(
3379 "var thrown = false;"
3380 "try {"
3381 " ThrowFromC();"
3382 "} catch (e) {"
3383 " thrown = true;"
3384 "}");
3385 Local<Value> thrown = context->Global()->Get(v8_str("thrown"));
3386 CHECK(thrown->BooleanValue());
3387}
3388
3389
ager@chromium.org8bb60582008-12-11 12:02:20 +00003390THREADED_TEST(APIThrowTryCatch) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003391 v8::HandleScope scope(v8::Isolate::GetCurrent());
ager@chromium.org8bb60582008-12-11 12:02:20 +00003392 Local<ObjectTemplate> templ = ObjectTemplate::New();
3393 templ->Set(v8_str("ThrowFromC"),
3394 v8::FunctionTemplate::New(ThrowFromC));
3395 LocalContext context(0, templ);
3396 v8::TryCatch try_catch;
3397 CompileRun("ThrowFromC();");
3398 CHECK(try_catch.HasCaught());
3399}
3400
3401
3402// Test that a try-finally block doesn't shadow a try-catch block
3403// when setting up an external handler.
ager@chromium.org71daaf62009-04-01 07:22:49 +00003404//
3405// BUG(271): Some of the exception propagation does not work on the
3406// ARM simulator because the simulator separates the C++ stack and the
3407// JS stack. This test therefore fails on the simulator. The test is
3408// not threaded to allow the threading tests to run on the simulator.
3409TEST(TryCatchInTryFinally) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003410 v8::HandleScope scope(v8::Isolate::GetCurrent());
ager@chromium.org8bb60582008-12-11 12:02:20 +00003411 Local<ObjectTemplate> templ = ObjectTemplate::New();
3412 templ->Set(v8_str("CCatcher"),
3413 v8::FunctionTemplate::New(CCatcher));
3414 LocalContext context(0, templ);
3415 Local<Value> result = CompileRun("try {"
3416 " try {"
3417 " CCatcher('throw 7;');"
3418 " } finally {"
3419 " }"
3420 "} catch (e) {"
3421 "}");
3422 CHECK(result->IsTrue());
3423}
3424
3425
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00003426static void check_reference_error_message(
3427 v8::Handle<v8::Message> message,
3428 v8::Handle<v8::Value> data) {
3429 const char* reference_error = "Uncaught ReferenceError: asdf is not defined";
3430 CHECK(message->Get()->Equals(v8_str(reference_error)));
3431}
3432
3433
kmillikin@chromium.org31b12772011-02-02 16:08:26 +00003434static v8::Handle<Value> Fail(const v8::Arguments& args) {
3435 ApiTestFuzzer::Fuzz();
3436 CHECK(false);
3437 return v8::Undefined();
3438}
3439
3440
3441// Test that overwritten methods are not invoked on uncaught exception
3442// formatting. However, they are invoked when performing normal error
3443// string conversions.
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00003444TEST(APIThrowMessageOverwrittenToString) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003445 v8::HandleScope scope(v8::Isolate::GetCurrent());
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00003446 v8::V8::AddMessageListener(check_reference_error_message);
kmillikin@chromium.org31b12772011-02-02 16:08:26 +00003447 Local<ObjectTemplate> templ = ObjectTemplate::New();
3448 templ->Set(v8_str("fail"), v8::FunctionTemplate::New(Fail));
3449 LocalContext context(NULL, templ);
3450 CompileRun("asdf;");
3451 CompileRun("var limit = {};"
3452 "limit.valueOf = fail;"
3453 "Error.stackTraceLimit = limit;");
3454 CompileRun("asdf");
3455 CompileRun("Array.prototype.pop = fail;");
3456 CompileRun("Object.prototype.hasOwnProperty = fail;");
3457 CompileRun("Object.prototype.toString = function f() { return 'Yikes'; }");
whesse@chromium.org7a392b32011-01-31 11:30:36 +00003458 CompileRun("Number.prototype.toString = function f() { return 'Yikes'; }");
3459 CompileRun("String.prototype.toString = function f() { return 'Yikes'; }");
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00003460 CompileRun("ReferenceError.prototype.toString ="
3461 " function() { return 'Whoops' }");
3462 CompileRun("asdf;");
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00003463 CompileRun("ReferenceError.prototype.constructor.name = void 0;");
3464 CompileRun("asdf;");
3465 CompileRun("ReferenceError.prototype.constructor = void 0;");
3466 CompileRun("asdf;");
ager@chromium.org0ee099b2011-01-25 14:06:47 +00003467 CompileRun("ReferenceError.prototype.__proto__ = new Object();");
3468 CompileRun("asdf;");
3469 CompileRun("ReferenceError.prototype = new Object();");
3470 CompileRun("asdf;");
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00003471 v8::Handle<Value> string = CompileRun("try { asdf; } catch(e) { e + ''; }");
3472 CHECK(string->Equals(v8_str("Whoops")));
ager@chromium.org378b34e2011-01-28 08:04:38 +00003473 CompileRun("ReferenceError.prototype.constructor = new Object();"
3474 "ReferenceError.prototype.constructor.name = 1;"
3475 "Number.prototype.toString = function() { return 'Whoops'; };"
3476 "ReferenceError.prototype.toString = Object.prototype.toString;");
3477 CompileRun("asdf;");
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00003478 v8::V8::RemoveMessageListeners(check_reference_error_message);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00003479}
3480
3481
yangguo@chromium.org304cc332012-07-24 07:59:48 +00003482static void check_custom_error_message(
3483 v8::Handle<v8::Message> message,
3484 v8::Handle<v8::Value> data) {
3485 const char* uncaught_error = "Uncaught MyError toString";
3486 CHECK(message->Get()->Equals(v8_str(uncaught_error)));
3487}
3488
3489
3490TEST(CustomErrorToString) {
yangguo@chromium.org304cc332012-07-24 07:59:48 +00003491 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003492 v8::HandleScope scope(context->GetIsolate());
3493 v8::V8::AddMessageListener(check_custom_error_message);
yangguo@chromium.org304cc332012-07-24 07:59:48 +00003494 CompileRun(
3495 "function MyError(name, message) { "
3496 " this.name = name; "
3497 " this.message = message; "
3498 "} "
3499 "MyError.prototype = Object.create(Error.prototype); "
3500 "MyError.prototype.toString = function() { "
3501 " return 'MyError toString'; "
3502 "}; "
3503 "throw new MyError('my name', 'my message'); ");
3504 v8::V8::RemoveMessageListeners(check_custom_error_message);
3505}
3506
3507
ager@chromium.org8bb60582008-12-11 12:02:20 +00003508static void receive_message(v8::Handle<v8::Message> message,
3509 v8::Handle<v8::Value> data) {
ager@chromium.org71daaf62009-04-01 07:22:49 +00003510 message->Get();
ager@chromium.org8bb60582008-12-11 12:02:20 +00003511 message_received = true;
3512}
3513
3514
3515TEST(APIThrowMessage) {
3516 message_received = false;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003517 v8::HandleScope scope(v8::Isolate::GetCurrent());
ager@chromium.org8bb60582008-12-11 12:02:20 +00003518 v8::V8::AddMessageListener(receive_message);
3519 Local<ObjectTemplate> templ = ObjectTemplate::New();
3520 templ->Set(v8_str("ThrowFromC"),
3521 v8::FunctionTemplate::New(ThrowFromC));
3522 LocalContext context(0, templ);
3523 CompileRun("ThrowFromC();");
3524 CHECK(message_received);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00003525 v8::V8::RemoveMessageListeners(receive_message);
ager@chromium.org8bb60582008-12-11 12:02:20 +00003526}
3527
3528
3529TEST(APIThrowMessageAndVerboseTryCatch) {
3530 message_received = false;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003531 v8::HandleScope scope(v8::Isolate::GetCurrent());
ager@chromium.org8bb60582008-12-11 12:02:20 +00003532 v8::V8::AddMessageListener(receive_message);
3533 Local<ObjectTemplate> templ = ObjectTemplate::New();
3534 templ->Set(v8_str("ThrowFromC"),
3535 v8::FunctionTemplate::New(ThrowFromC));
3536 LocalContext context(0, templ);
3537 v8::TryCatch try_catch;
3538 try_catch.SetVerbose(true);
ager@chromium.org71daaf62009-04-01 07:22:49 +00003539 Local<Value> result = CompileRun("ThrowFromC();");
ager@chromium.org8bb60582008-12-11 12:02:20 +00003540 CHECK(try_catch.HasCaught());
ager@chromium.org71daaf62009-04-01 07:22:49 +00003541 CHECK(result.IsEmpty());
ager@chromium.org8bb60582008-12-11 12:02:20 +00003542 CHECK(message_received);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00003543 v8::V8::RemoveMessageListeners(receive_message);
ager@chromium.org8bb60582008-12-11 12:02:20 +00003544}
3545
3546
karlklose@chromium.org44bc7082011-04-11 12:33:05 +00003547TEST(APIStackOverflowAndVerboseTryCatch) {
3548 message_received = false;
karlklose@chromium.org44bc7082011-04-11 12:33:05 +00003549 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003550 v8::HandleScope scope(context->GetIsolate());
3551 v8::V8::AddMessageListener(receive_message);
karlklose@chromium.org44bc7082011-04-11 12:33:05 +00003552 v8::TryCatch try_catch;
3553 try_catch.SetVerbose(true);
3554 Local<Value> result = CompileRun("function foo() { foo(); } foo();");
3555 CHECK(try_catch.HasCaught());
3556 CHECK(result.IsEmpty());
3557 CHECK(message_received);
3558 v8::V8::RemoveMessageListeners(receive_message);
3559}
3560
3561
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003562THREADED_TEST(ExternalScriptException) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003563 v8::HandleScope scope(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003564 Local<ObjectTemplate> templ = ObjectTemplate::New();
3565 templ->Set(v8_str("ThrowFromC"),
3566 v8::FunctionTemplate::New(ThrowFromC));
3567 LocalContext context(0, templ);
3568
3569 v8::TryCatch try_catch;
3570 Local<Script> script
3571 = Script::Compile(v8_str("ThrowFromC(); throw 'panama';"));
3572 Local<Value> result = script->Run();
3573 CHECK(result.IsEmpty());
3574 CHECK(try_catch.HasCaught());
3575 String::AsciiValue exception_value(try_catch.Exception());
3576 CHECK_EQ("konto", *exception_value);
3577}
3578
3579
3580
3581v8::Handle<Value> CThrowCountDown(const v8::Arguments& args) {
3582 ApiTestFuzzer::Fuzz();
3583 CHECK_EQ(4, args.Length());
3584 int count = args[0]->Int32Value();
3585 int cInterval = args[2]->Int32Value();
3586 if (count == 0) {
3587 return v8::ThrowException(v8_str("FromC"));
3588 } else {
3589 Local<v8::Object> global = Context::GetCurrent()->Global();
3590 Local<Value> fun = global->Get(v8_str("JSThrowCountDown"));
3591 v8::Handle<Value> argv[] = { v8_num(count - 1),
3592 args[1],
3593 args[2],
3594 args[3] };
3595 if (count % cInterval == 0) {
3596 v8::TryCatch try_catch;
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00003597 Local<Value> result = fun.As<Function>()->Call(global, 4, argv);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003598 int expected = args[3]->Int32Value();
3599 if (try_catch.HasCaught()) {
3600 CHECK_EQ(expected, count);
ager@chromium.org71daaf62009-04-01 07:22:49 +00003601 CHECK(result.IsEmpty());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00003602 CHECK(!i::Isolate::Current()->has_scheduled_exception());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003603 } else {
3604 CHECK_NE(expected, count);
3605 }
3606 return result;
3607 } else {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00003608 return fun.As<Function>()->Call(global, 4, argv);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003609 }
3610 }
3611}
3612
3613
3614v8::Handle<Value> JSCheck(const v8::Arguments& args) {
3615 ApiTestFuzzer::Fuzz();
3616 CHECK_EQ(3, args.Length());
3617 bool equality = args[0]->BooleanValue();
3618 int count = args[1]->Int32Value();
3619 int expected = args[2]->Int32Value();
3620 if (equality) {
3621 CHECK_EQ(count, expected);
3622 } else {
3623 CHECK_NE(count, expected);
3624 }
3625 return v8::Undefined();
3626}
3627
3628
ager@chromium.org8bb60582008-12-11 12:02:20 +00003629THREADED_TEST(EvalInTryFinally) {
ager@chromium.org8bb60582008-12-11 12:02:20 +00003630 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003631 v8::HandleScope scope(context->GetIsolate());
ager@chromium.org8bb60582008-12-11 12:02:20 +00003632 v8::TryCatch try_catch;
3633 CompileRun("(function() {"
3634 " try {"
3635 " eval('asldkf (*&^&*^');"
3636 " } finally {"
3637 " return;"
3638 " }"
3639 "})()");
3640 CHECK(!try_catch.HasCaught());
3641}
3642
3643
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003644// This test works by making a stack of alternating JavaScript and C
3645// activations. These activations set up exception handlers with regular
3646// intervals, one interval for C activations and another for JavaScript
3647// activations. When enough activations have been created an exception is
3648// thrown and we check that the right activation catches the exception and that
3649// no other activations do. The right activation is always the topmost one with
3650// a handler, regardless of whether it is in JavaScript or C.
3651//
3652// The notation used to describe a test case looks like this:
3653//
3654// *JS[4] *C[3] @JS[2] C[1] JS[0]
3655//
3656// Each entry is an activation, either JS or C. The index is the count at that
3657// level. Stars identify activations with exception handlers, the @ identifies
3658// the exception handler that should catch the exception.
ager@chromium.org71daaf62009-04-01 07:22:49 +00003659//
3660// BUG(271): Some of the exception propagation does not work on the
3661// ARM simulator because the simulator separates the C++ stack and the
3662// JS stack. This test therefore fails on the simulator. The test is
3663// not threaded to allow the threading tests to run on the simulator.
3664TEST(ExceptionOrder) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003665 v8::HandleScope scope(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003666 Local<ObjectTemplate> templ = ObjectTemplate::New();
3667 templ->Set(v8_str("check"), v8::FunctionTemplate::New(JSCheck));
3668 templ->Set(v8_str("CThrowCountDown"),
3669 v8::FunctionTemplate::New(CThrowCountDown));
3670 LocalContext context(0, templ);
3671 CompileRun(
3672 "function JSThrowCountDown(count, jsInterval, cInterval, expected) {"
3673 " if (count == 0) throw 'FromJS';"
3674 " if (count % jsInterval == 0) {"
3675 " try {"
3676 " var value = CThrowCountDown(count - 1,"
3677 " jsInterval,"
3678 " cInterval,"
3679 " expected);"
3680 " check(false, count, expected);"
3681 " return value;"
3682 " } catch (e) {"
3683 " check(true, count, expected);"
3684 " }"
3685 " } else {"
3686 " return CThrowCountDown(count - 1, jsInterval, cInterval, expected);"
3687 " }"
3688 "}");
3689 Local<Function> fun =
3690 Local<Function>::Cast(context->Global()->Get(v8_str("JSThrowCountDown")));
3691
3692 const int argc = 4;
3693 // count jsInterval cInterval expected
3694
3695 // *JS[4] *C[3] @JS[2] C[1] JS[0]
3696 v8::Handle<Value> a0[argc] = { v8_num(4), v8_num(2), v8_num(3), v8_num(2) };
3697 fun->Call(fun, argc, a0);
3698
3699 // JS[5] *C[4] JS[3] @C[2] JS[1] C[0]
3700 v8::Handle<Value> a1[argc] = { v8_num(5), v8_num(6), v8_num(1), v8_num(2) };
3701 fun->Call(fun, argc, a1);
3702
3703 // JS[6] @C[5] JS[4] C[3] JS[2] C[1] JS[0]
3704 v8::Handle<Value> a2[argc] = { v8_num(6), v8_num(7), v8_num(5), v8_num(5) };
3705 fun->Call(fun, argc, a2);
3706
3707 // @JS[6] C[5] JS[4] C[3] JS[2] C[1] JS[0]
3708 v8::Handle<Value> a3[argc] = { v8_num(6), v8_num(6), v8_num(7), v8_num(6) };
3709 fun->Call(fun, argc, a3);
3710
3711 // JS[6] *C[5] @JS[4] C[3] JS[2] C[1] JS[0]
3712 v8::Handle<Value> a4[argc] = { v8_num(6), v8_num(4), v8_num(5), v8_num(4) };
3713 fun->Call(fun, argc, a4);
3714
3715 // JS[6] C[5] *JS[4] @C[3] JS[2] C[1] JS[0]
3716 v8::Handle<Value> a5[argc] = { v8_num(6), v8_num(4), v8_num(3), v8_num(3) };
3717 fun->Call(fun, argc, a5);
3718}
3719
3720
3721v8::Handle<Value> ThrowValue(const v8::Arguments& args) {
3722 ApiTestFuzzer::Fuzz();
3723 CHECK_EQ(1, args.Length());
3724 return v8::ThrowException(args[0]);
3725}
3726
3727
3728THREADED_TEST(ThrowValues) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003729 v8::HandleScope scope(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003730 Local<ObjectTemplate> templ = ObjectTemplate::New();
3731 templ->Set(v8_str("Throw"), v8::FunctionTemplate::New(ThrowValue));
3732 LocalContext context(0, templ);
3733 v8::Handle<v8::Array> result = v8::Handle<v8::Array>::Cast(CompileRun(
3734 "function Run(obj) {"
3735 " try {"
3736 " Throw(obj);"
3737 " } catch (e) {"
3738 " return e;"
3739 " }"
3740 " return 'no exception';"
3741 "}"
3742 "[Run('str'), Run(1), Run(0), Run(null), Run(void 0)];"));
3743 CHECK_EQ(5, result->Length());
3744 CHECK(result->Get(v8::Integer::New(0))->IsString());
3745 CHECK(result->Get(v8::Integer::New(1))->IsNumber());
3746 CHECK_EQ(1, result->Get(v8::Integer::New(1))->Int32Value());
3747 CHECK(result->Get(v8::Integer::New(2))->IsNumber());
3748 CHECK_EQ(0, result->Get(v8::Integer::New(2))->Int32Value());
3749 CHECK(result->Get(v8::Integer::New(3))->IsNull());
3750 CHECK(result->Get(v8::Integer::New(4))->IsUndefined());
3751}
3752
3753
3754THREADED_TEST(CatchZero) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003755 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003756 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003757 v8::TryCatch try_catch;
3758 CHECK(!try_catch.HasCaught());
3759 Script::Compile(v8_str("throw 10"))->Run();
3760 CHECK(try_catch.HasCaught());
3761 CHECK_EQ(10, try_catch.Exception()->Int32Value());
3762 try_catch.Reset();
3763 CHECK(!try_catch.HasCaught());
3764 Script::Compile(v8_str("throw 0"))->Run();
3765 CHECK(try_catch.HasCaught());
3766 CHECK_EQ(0, try_catch.Exception()->Int32Value());
3767}
3768
3769
3770THREADED_TEST(CatchExceptionFromWith) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003771 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003772 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003773 v8::TryCatch try_catch;
3774 CHECK(!try_catch.HasCaught());
3775 Script::Compile(v8_str("var o = {}; with (o) { throw 42; }"))->Run();
3776 CHECK(try_catch.HasCaught());
3777}
3778
3779
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00003780THREADED_TEST(TryCatchAndFinallyHidingException) {
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00003781 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003782 v8::HandleScope scope(context->GetIsolate());
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00003783 v8::TryCatch try_catch;
3784 CHECK(!try_catch.HasCaught());
3785 CompileRun("function f(k) { try { this[k]; } finally { return 0; } };");
3786 CompileRun("f({toString: function() { throw 42; }});");
3787 CHECK(!try_catch.HasCaught());
3788}
3789
3790
3791v8::Handle<v8::Value> WithTryCatch(const v8::Arguments& args) {
3792 v8::TryCatch try_catch;
3793 return v8::Undefined();
3794}
3795
3796
3797THREADED_TEST(TryCatchAndFinally) {
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00003798 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003799 v8::HandleScope scope(context->GetIsolate());
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00003800 context->Global()->Set(
3801 v8_str("native_with_try_catch"),
3802 v8::FunctionTemplate::New(WithTryCatch)->GetFunction());
3803 v8::TryCatch try_catch;
3804 CHECK(!try_catch.HasCaught());
3805 CompileRun(
3806 "try {\n"
3807 " throw new Error('a');\n"
3808 "} finally {\n"
3809 " native_with_try_catch();\n"
3810 "}\n");
3811 CHECK(try_catch.HasCaught());
3812}
3813
3814
mmassi@chromium.org49a44672012-12-04 13:52:03 +00003815static void TryCatchNestedHelper(int depth) {
3816 if (depth > 0) {
3817 v8::TryCatch try_catch;
3818 try_catch.SetVerbose(true);
3819 TryCatchNestedHelper(depth - 1);
3820 CHECK(try_catch.HasCaught());
3821 try_catch.ReThrow();
3822 } else {
3823 v8::ThrowException(v8_str("back"));
3824 }
3825}
3826
3827
3828TEST(TryCatchNested) {
3829 v8::V8::Initialize();
mmassi@chromium.org49a44672012-12-04 13:52:03 +00003830 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003831 v8::HandleScope scope(context->GetIsolate());
mmassi@chromium.org49a44672012-12-04 13:52:03 +00003832 v8::TryCatch try_catch;
3833 TryCatchNestedHelper(5);
3834 CHECK(try_catch.HasCaught());
3835 CHECK_EQ(0, strcmp(*v8::String::Utf8Value(try_catch.Exception()), "back"));
3836}
3837
3838
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003839THREADED_TEST(Equality) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003840 LocalContext context;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00003841 v8::Isolate* isolate = context->GetIsolate();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003842 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003843 // Check that equality works at all before relying on CHECK_EQ
3844 CHECK(v8_str("a")->Equals(v8_str("a")));
3845 CHECK(!v8_str("a")->Equals(v8_str("b")));
3846
3847 CHECK_EQ(v8_str("a"), v8_str("a"));
3848 CHECK_NE(v8_str("a"), v8_str("b"));
3849 CHECK_EQ(v8_num(1), v8_num(1));
3850 CHECK_EQ(v8_num(1.00), v8_num(1));
3851 CHECK_NE(v8_num(1), v8_num(2));
3852
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00003853 // Assume String is not internalized.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003854 CHECK(v8_str("a")->StrictEquals(v8_str("a")));
3855 CHECK(!v8_str("a")->StrictEquals(v8_str("b")));
3856 CHECK(!v8_str("5")->StrictEquals(v8_num(5)));
3857 CHECK(v8_num(1)->StrictEquals(v8_num(1)));
3858 CHECK(!v8_num(1)->StrictEquals(v8_num(2)));
3859 CHECK(v8_num(0)->StrictEquals(v8_num(-0)));
3860 Local<Value> not_a_number = v8_num(i::OS::nan_value());
3861 CHECK(!not_a_number->StrictEquals(not_a_number));
3862 CHECK(v8::False()->StrictEquals(v8::False()));
3863 CHECK(!v8::False()->StrictEquals(v8::Undefined()));
3864
3865 v8::Handle<v8::Object> obj = v8::Object::New();
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00003866 v8::Persistent<v8::Object> alias =
3867 v8::Persistent<v8::Object>::New(isolate, obj);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003868 CHECK(alias->StrictEquals(obj));
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00003869 alias.Dispose(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003870}
3871
3872
3873THREADED_TEST(MultiRun) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003874 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003875 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003876 Local<Script> script = Script::Compile(v8_str("x"));
3877 for (int i = 0; i < 10; i++)
3878 script->Run();
3879}
3880
3881
3882static v8::Handle<Value> GetXValue(Local<String> name,
3883 const AccessorInfo& info) {
3884 ApiTestFuzzer::Fuzz();
3885 CHECK_EQ(info.Data(), v8_str("donut"));
3886 CHECK_EQ(name, v8_str("x"));
3887 return name;
3888}
3889
3890
3891THREADED_TEST(SimplePropertyRead) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003892 LocalContext context;
3893 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003894 Local<ObjectTemplate> templ = ObjectTemplate::New();
3895 templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003896 context->Global()->Set(v8_str("obj"), templ->NewInstance());
3897 Local<Script> script = Script::Compile(v8_str("obj.x"));
3898 for (int i = 0; i < 10; i++) {
3899 Local<Value> result = script->Run();
3900 CHECK_EQ(result, v8_str("x"));
3901 }
3902}
3903
ager@chromium.org5c838252010-02-19 08:53:10 +00003904THREADED_TEST(DefinePropertyOnAPIAccessor) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003905 LocalContext context;
3906 v8::HandleScope scope(context->GetIsolate());
ager@chromium.org5c838252010-02-19 08:53:10 +00003907 Local<ObjectTemplate> templ = ObjectTemplate::New();
3908 templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
ager@chromium.org5c838252010-02-19 08:53:10 +00003909 context->Global()->Set(v8_str("obj"), templ->NewInstance());
3910
3911 // Uses getOwnPropertyDescriptor to check the configurable status
3912 Local<Script> script_desc
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00003913 = Script::Compile(v8_str("var prop = Object.getOwnPropertyDescriptor( "
ager@chromium.org5c838252010-02-19 08:53:10 +00003914 "obj, 'x');"
3915 "prop.configurable;"));
3916 Local<Value> result = script_desc->Run();
3917 CHECK_EQ(result->BooleanValue(), true);
3918
3919 // Redefine get - but still configurable
3920 Local<Script> script_define
3921 = Script::Compile(v8_str("var desc = { get: function(){return 42; },"
3922 " configurable: true };"
3923 "Object.defineProperty(obj, 'x', desc);"
3924 "obj.x"));
3925 result = script_define->Run();
3926 CHECK_EQ(result, v8_num(42));
3927
3928 // Check that the accessor is still configurable
3929 result = script_desc->Run();
3930 CHECK_EQ(result->BooleanValue(), true);
3931
3932 // Redefine to a non-configurable
3933 script_define
3934 = Script::Compile(v8_str("var desc = { get: function(){return 43; },"
3935 " configurable: false };"
3936 "Object.defineProperty(obj, 'x', desc);"
3937 "obj.x"));
3938 result = script_define->Run();
3939 CHECK_EQ(result, v8_num(43));
3940 result = script_desc->Run();
3941 CHECK_EQ(result->BooleanValue(), false);
3942
3943 // Make sure that it is not possible to redefine again
3944 v8::TryCatch try_catch;
3945 result = script_define->Run();
3946 CHECK(try_catch.HasCaught());
3947 String::AsciiValue exception_value(try_catch.Exception());
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00003948 CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x");
ager@chromium.org5c838252010-02-19 08:53:10 +00003949}
3950
3951THREADED_TEST(DefinePropertyOnDefineGetterSetter) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003952 v8::HandleScope scope(v8::Isolate::GetCurrent());
ager@chromium.org5c838252010-02-19 08:53:10 +00003953 Local<ObjectTemplate> templ = ObjectTemplate::New();
3954 templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
3955 LocalContext context;
3956 context->Global()->Set(v8_str("obj"), templ->NewInstance());
3957
3958 Local<Script> script_desc = Script::Compile(v8_str("var prop ="
3959 "Object.getOwnPropertyDescriptor( "
3960 "obj, 'x');"
3961 "prop.configurable;"));
3962 Local<Value> result = script_desc->Run();
3963 CHECK_EQ(result->BooleanValue(), true);
3964
3965 Local<Script> script_define =
3966 Script::Compile(v8_str("var desc = {get: function(){return 42; },"
3967 " configurable: true };"
3968 "Object.defineProperty(obj, 'x', desc);"
3969 "obj.x"));
3970 result = script_define->Run();
3971 CHECK_EQ(result, v8_num(42));
3972
3973
3974 result = script_desc->Run();
3975 CHECK_EQ(result->BooleanValue(), true);
3976
3977
3978 script_define =
3979 Script::Compile(v8_str("var desc = {get: function(){return 43; },"
3980 " configurable: false };"
3981 "Object.defineProperty(obj, 'x', desc);"
3982 "obj.x"));
3983 result = script_define->Run();
3984 CHECK_EQ(result, v8_num(43));
3985 result = script_desc->Run();
3986
3987 CHECK_EQ(result->BooleanValue(), false);
3988
3989 v8::TryCatch try_catch;
3990 result = script_define->Run();
3991 CHECK(try_catch.HasCaught());
3992 String::AsciiValue exception_value(try_catch.Exception());
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00003993 CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x");
ager@chromium.org5c838252010-02-19 08:53:10 +00003994}
3995
3996
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00003997static v8::Handle<v8::Object> GetGlobalProperty(LocalContext* context,
3998 char const* name) {
3999 return v8::Handle<v8::Object>::Cast((*context)->Global()->Get(v8_str(name)));
4000}
ager@chromium.org5c838252010-02-19 08:53:10 +00004001
4002
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00004003THREADED_TEST(DefineAPIAccessorOnObject) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004004 v8::HandleScope scope(v8::Isolate::GetCurrent());
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00004005 Local<ObjectTemplate> templ = ObjectTemplate::New();
4006 LocalContext context;
4007
4008 context->Global()->Set(v8_str("obj1"), templ->NewInstance());
4009 CompileRun("var obj2 = {};");
4010
4011 CHECK(CompileRun("obj1.x")->IsUndefined());
4012 CHECK(CompileRun("obj2.x")->IsUndefined());
4013
4014 CHECK(GetGlobalProperty(&context, "obj1")->
4015 SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
4016
4017 ExpectString("obj1.x", "x");
4018 CHECK(CompileRun("obj2.x")->IsUndefined());
4019
4020 CHECK(GetGlobalProperty(&context, "obj2")->
4021 SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
4022
4023 ExpectString("obj1.x", "x");
4024 ExpectString("obj2.x", "x");
4025
4026 ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
4027 ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
4028
4029 CompileRun("Object.defineProperty(obj1, 'x',"
4030 "{ get: function() { return 'y'; }, configurable: true })");
4031
4032 ExpectString("obj1.x", "y");
4033 ExpectString("obj2.x", "x");
4034
4035 CompileRun("Object.defineProperty(obj2, 'x',"
4036 "{ get: function() { return 'y'; }, configurable: true })");
4037
4038 ExpectString("obj1.x", "y");
4039 ExpectString("obj2.x", "y");
4040
4041 ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
4042 ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
4043
4044 CHECK(GetGlobalProperty(&context, "obj1")->
4045 SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
4046 CHECK(GetGlobalProperty(&context, "obj2")->
4047 SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
4048
4049 ExpectString("obj1.x", "x");
4050 ExpectString("obj2.x", "x");
4051
4052 ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
4053 ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
4054
4055 // Define getters/setters, but now make them not configurable.
4056 CompileRun("Object.defineProperty(obj1, 'x',"
4057 "{ get: function() { return 'z'; }, configurable: false })");
4058 CompileRun("Object.defineProperty(obj2, 'x',"
4059 "{ get: function() { return 'z'; }, configurable: false })");
4060
4061 ExpectTrue("!Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
4062 ExpectTrue("!Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
4063
4064 ExpectString("obj1.x", "z");
4065 ExpectString("obj2.x", "z");
4066
4067 CHECK(!GetGlobalProperty(&context, "obj1")->
4068 SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
4069 CHECK(!GetGlobalProperty(&context, "obj2")->
4070 SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
4071
4072 ExpectString("obj1.x", "z");
4073 ExpectString("obj2.x", "z");
4074}
4075
4076
4077THREADED_TEST(DontDeleteAPIAccessorsCannotBeOverriden) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004078 v8::HandleScope scope(v8::Isolate::GetCurrent());
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00004079 Local<ObjectTemplate> templ = ObjectTemplate::New();
4080 LocalContext context;
4081
4082 context->Global()->Set(v8_str("obj1"), templ->NewInstance());
4083 CompileRun("var obj2 = {};");
4084
4085 CHECK(GetGlobalProperty(&context, "obj1")->SetAccessor(
4086 v8_str("x"),
4087 GetXValue, NULL,
4088 v8_str("donut"), v8::DEFAULT, v8::DontDelete));
4089 CHECK(GetGlobalProperty(&context, "obj2")->SetAccessor(
4090 v8_str("x"),
4091 GetXValue, NULL,
4092 v8_str("donut"), v8::DEFAULT, v8::DontDelete));
4093
4094 ExpectString("obj1.x", "x");
4095 ExpectString("obj2.x", "x");
4096
4097 ExpectTrue("!Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
4098 ExpectTrue("!Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
4099
4100 CHECK(!GetGlobalProperty(&context, "obj1")->
4101 SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
4102 CHECK(!GetGlobalProperty(&context, "obj2")->
4103 SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
4104
4105 {
4106 v8::TryCatch try_catch;
4107 CompileRun("Object.defineProperty(obj1, 'x',"
4108 "{get: function() { return 'func'; }})");
4109 CHECK(try_catch.HasCaught());
4110 String::AsciiValue exception_value(try_catch.Exception());
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00004111 CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x");
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00004112 }
4113 {
4114 v8::TryCatch try_catch;
4115 CompileRun("Object.defineProperty(obj2, 'x',"
4116 "{get: function() { return 'func'; }})");
4117 CHECK(try_catch.HasCaught());
4118 String::AsciiValue exception_value(try_catch.Exception());
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00004119 CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x");
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00004120 }
4121}
4122
4123
4124static v8::Handle<Value> Get239Value(Local<String> name,
4125 const AccessorInfo& info) {
4126 ApiTestFuzzer::Fuzz();
4127 CHECK_EQ(info.Data(), v8_str("donut"));
4128 CHECK_EQ(name, v8_str("239"));
4129 return name;
4130}
4131
4132
4133THREADED_TEST(ElementAPIAccessor) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004134 v8::HandleScope scope(v8::Isolate::GetCurrent());
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00004135 Local<ObjectTemplate> templ = ObjectTemplate::New();
4136 LocalContext context;
4137
4138 context->Global()->Set(v8_str("obj1"), templ->NewInstance());
4139 CompileRun("var obj2 = {};");
4140
4141 CHECK(GetGlobalProperty(&context, "obj1")->SetAccessor(
4142 v8_str("239"),
4143 Get239Value, NULL,
4144 v8_str("donut")));
4145 CHECK(GetGlobalProperty(&context, "obj2")->SetAccessor(
4146 v8_str("239"),
4147 Get239Value, NULL,
4148 v8_str("donut")));
4149
4150 ExpectString("obj1[239]", "239");
4151 ExpectString("obj2[239]", "239");
4152 ExpectString("obj1['239']", "239");
4153 ExpectString("obj2['239']", "239");
4154}
4155
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004156
4157v8::Persistent<Value> xValue;
4158
4159
4160static void SetXValue(Local<String> name,
4161 Local<Value> value,
4162 const AccessorInfo& info) {
4163 CHECK_EQ(value, v8_num(4));
4164 CHECK_EQ(info.Data(), v8_str("donut"));
4165 CHECK_EQ(name, v8_str("x"));
4166 CHECK(xValue.IsEmpty());
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00004167 xValue = v8::Persistent<Value>::New(info.GetIsolate(), value);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004168}
4169
4170
4171THREADED_TEST(SimplePropertyWrite) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004172 v8::HandleScope scope(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004173 Local<ObjectTemplate> templ = ObjectTemplate::New();
4174 templ->SetAccessor(v8_str("x"), GetXValue, SetXValue, v8_str("donut"));
4175 LocalContext context;
4176 context->Global()->Set(v8_str("obj"), templ->NewInstance());
4177 Local<Script> script = Script::Compile(v8_str("obj.x = 4"));
4178 for (int i = 0; i < 10; i++) {
4179 CHECK(xValue.IsEmpty());
4180 script->Run();
4181 CHECK_EQ(v8_num(4), xValue);
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00004182 xValue.Dispose(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004183 xValue = v8::Persistent<Value>();
4184 }
4185}
4186
4187
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00004188THREADED_TEST(SetterOnly) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004189 v8::HandleScope scope(v8::Isolate::GetCurrent());
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00004190 Local<ObjectTemplate> templ = ObjectTemplate::New();
4191 templ->SetAccessor(v8_str("x"), NULL, SetXValue, v8_str("donut"));
4192 LocalContext context;
4193 context->Global()->Set(v8_str("obj"), templ->NewInstance());
4194 Local<Script> script = Script::Compile(v8_str("obj.x = 4; obj.x"));
4195 for (int i = 0; i < 10; i++) {
4196 CHECK(xValue.IsEmpty());
4197 script->Run();
4198 CHECK_EQ(v8_num(4), xValue);
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00004199 xValue.Dispose(context->GetIsolate());
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00004200 xValue = v8::Persistent<Value>();
4201 }
4202}
4203
4204
4205THREADED_TEST(NoAccessors) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004206 v8::HandleScope scope(v8::Isolate::GetCurrent());
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00004207 Local<ObjectTemplate> templ = ObjectTemplate::New();
4208 templ->SetAccessor(v8_str("x"), NULL, NULL, v8_str("donut"));
4209 LocalContext context;
4210 context->Global()->Set(v8_str("obj"), templ->NewInstance());
4211 Local<Script> script = Script::Compile(v8_str("obj.x = 4; obj.x"));
4212 for (int i = 0; i < 10; i++) {
4213 script->Run();
4214 }
4215}
4216
4217
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004218static v8::Handle<Value> XPropertyGetter(Local<String> property,
4219 const AccessorInfo& info) {
4220 ApiTestFuzzer::Fuzz();
4221 CHECK(info.Data()->IsUndefined());
4222 return property;
4223}
4224
4225
ager@chromium.orgeadaf222009-06-16 09:43:10 +00004226THREADED_TEST(NamedInterceptorPropertyRead) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004227 v8::HandleScope scope(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004228 Local<ObjectTemplate> templ = ObjectTemplate::New();
4229 templ->SetNamedPropertyHandler(XPropertyGetter);
4230 LocalContext context;
4231 context->Global()->Set(v8_str("obj"), templ->NewInstance());
4232 Local<Script> script = Script::Compile(v8_str("obj.x"));
4233 for (int i = 0; i < 10; i++) {
4234 Local<Value> result = script->Run();
4235 CHECK_EQ(result, v8_str("x"));
4236 }
4237}
4238
ager@chromium.orgeadaf222009-06-16 09:43:10 +00004239
ager@chromium.orgb26c50a2010-03-26 09:27:16 +00004240THREADED_TEST(NamedInterceptorDictionaryIC) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004241 v8::HandleScope scope(v8::Isolate::GetCurrent());
ager@chromium.orgb26c50a2010-03-26 09:27:16 +00004242 Local<ObjectTemplate> templ = ObjectTemplate::New();
4243 templ->SetNamedPropertyHandler(XPropertyGetter);
4244 LocalContext context;
4245 // Create an object with a named interceptor.
4246 context->Global()->Set(v8_str("interceptor_obj"), templ->NewInstance());
4247 Local<Script> script = Script::Compile(v8_str("interceptor_obj.x"));
4248 for (int i = 0; i < 10; i++) {
4249 Local<Value> result = script->Run();
4250 CHECK_EQ(result, v8_str("x"));
4251 }
4252 // Create a slow case object and a function accessing a property in
4253 // that slow case object (with dictionary probing in generated
4254 // code). Then force object with a named interceptor into slow-case,
4255 // pass it to the function, and check that the interceptor is called
4256 // instead of accessing the local property.
4257 Local<Value> result =
4258 CompileRun("function get_x(o) { return o.x; };"
4259 "var obj = { x : 42, y : 0 };"
4260 "delete obj.y;"
4261 "for (var i = 0; i < 10; i++) get_x(obj);"
4262 "interceptor_obj.x = 42;"
4263 "interceptor_obj.y = 10;"
4264 "delete interceptor_obj.y;"
4265 "get_x(interceptor_obj)");
4266 CHECK_EQ(result, v8_str("x"));
4267}
4268
4269
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00004270THREADED_TEST(NamedInterceptorDictionaryICMultipleContext) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004271 v8::HandleScope scope(v8::Isolate::GetCurrent());
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00004272
4273 v8::Persistent<Context> context1 = Context::New();
4274
4275 context1->Enter();
4276 Local<ObjectTemplate> templ = ObjectTemplate::New();
4277 templ->SetNamedPropertyHandler(XPropertyGetter);
4278 // Create an object with a named interceptor.
4279 v8::Local<v8::Object> object = templ->NewInstance();
4280 context1->Global()->Set(v8_str("interceptor_obj"), object);
4281
4282 // Force the object into the slow case.
4283 CompileRun("interceptor_obj.y = 0;"
4284 "delete interceptor_obj.y;");
4285 context1->Exit();
4286
4287 {
4288 // Introduce the object into a different context.
4289 // Repeat named loads to exercise ICs.
4290 LocalContext context2;
4291 context2->Global()->Set(v8_str("interceptor_obj"), object);
4292 Local<Value> result =
4293 CompileRun("function get_x(o) { return o.x; }"
4294 "interceptor_obj.x = 42;"
4295 "for (var i=0; i != 10; i++) {"
4296 " get_x(interceptor_obj);"
4297 "}"
4298 "get_x(interceptor_obj)");
4299 // Check that the interceptor was actually invoked.
4300 CHECK_EQ(result, v8_str("x"));
4301 }
4302
4303 // Return to the original context and force some object to the slow case
4304 // to cause the NormalizedMapCache to verify.
4305 context1->Enter();
4306 CompileRun("var obj = { x : 0 }; delete obj.x;");
4307 context1->Exit();
4308
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00004309 context1.Dispose(context1->GetIsolate());
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00004310}
4311
4312
ager@chromium.org5c838252010-02-19 08:53:10 +00004313static v8::Handle<Value> SetXOnPrototypeGetter(Local<String> property,
4314 const AccessorInfo& info) {
4315 // Set x on the prototype object and do not handle the get request.
4316 v8::Handle<v8::Value> proto = info.Holder()->GetPrototype();
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004317 proto.As<v8::Object>()->Set(v8_str("x"), v8::Integer::New(23));
ager@chromium.org5c838252010-02-19 08:53:10 +00004318 return v8::Handle<Value>();
4319}
4320
4321
4322// This is a regression test for http://crbug.com/20104. Map
4323// transitions should not interfere with post interceptor lookup.
4324THREADED_TEST(NamedInterceptorMapTransitionRead) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004325 v8::HandleScope scope(v8::Isolate::GetCurrent());
ager@chromium.org5c838252010-02-19 08:53:10 +00004326 Local<v8::FunctionTemplate> function_template = v8::FunctionTemplate::New();
4327 Local<v8::ObjectTemplate> instance_template
4328 = function_template->InstanceTemplate();
4329 instance_template->SetNamedPropertyHandler(SetXOnPrototypeGetter);
4330 LocalContext context;
4331 context->Global()->Set(v8_str("F"), function_template->GetFunction());
4332 // Create an instance of F and introduce a map transition for x.
4333 CompileRun("var o = new F(); o.x = 23;");
4334 // Create an instance of F and invoke the getter. The result should be 23.
4335 Local<Value> result = CompileRun("o = new F(); o.x");
4336 CHECK_EQ(result->Int32Value(), 23);
4337}
4338
4339
ager@chromium.orgeadaf222009-06-16 09:43:10 +00004340static v8::Handle<Value> IndexedPropertyGetter(uint32_t index,
4341 const AccessorInfo& info) {
4342 ApiTestFuzzer::Fuzz();
4343 if (index == 37) {
4344 return v8::Handle<Value>(v8_num(625));
4345 }
4346 return v8::Handle<Value>();
4347}
4348
4349
4350static v8::Handle<Value> IndexedPropertySetter(uint32_t index,
4351 Local<Value> value,
4352 const AccessorInfo& info) {
4353 ApiTestFuzzer::Fuzz();
4354 if (index == 39) {
4355 return value;
4356 }
4357 return v8::Handle<Value>();
4358}
4359
4360
4361THREADED_TEST(IndexedInterceptorWithIndexedAccessor) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004362 v8::HandleScope scope(v8::Isolate::GetCurrent());
ager@chromium.orgeadaf222009-06-16 09:43:10 +00004363 Local<ObjectTemplate> templ = ObjectTemplate::New();
4364 templ->SetIndexedPropertyHandler(IndexedPropertyGetter,
4365 IndexedPropertySetter);
4366 LocalContext context;
4367 context->Global()->Set(v8_str("obj"), templ->NewInstance());
4368 Local<Script> getter_script = Script::Compile(v8_str(
4369 "obj.__defineGetter__(\"3\", function(){return 5;});obj[3];"));
4370 Local<Script> setter_script = Script::Compile(v8_str(
4371 "obj.__defineSetter__(\"17\", function(val){this.foo = val;});"
4372 "obj[17] = 23;"
4373 "obj.foo;"));
4374 Local<Script> interceptor_setter_script = Script::Compile(v8_str(
4375 "obj.__defineSetter__(\"39\", function(val){this.foo = \"hit\";});"
4376 "obj[39] = 47;"
4377 "obj.foo;")); // This setter should not run, due to the interceptor.
4378 Local<Script> interceptor_getter_script = Script::Compile(v8_str(
4379 "obj[37];"));
4380 Local<Value> result = getter_script->Run();
4381 CHECK_EQ(v8_num(5), result);
4382 result = setter_script->Run();
4383 CHECK_EQ(v8_num(23), result);
4384 result = interceptor_setter_script->Run();
4385 CHECK_EQ(v8_num(23), result);
4386 result = interceptor_getter_script->Run();
4387 CHECK_EQ(v8_num(625), result);
4388}
4389
4390
ricow@chromium.org9fa09672011-07-25 11:05:35 +00004391static v8::Handle<Value> UnboxedDoubleIndexedPropertyGetter(
4392 uint32_t index,
4393 const AccessorInfo& info) {
4394 ApiTestFuzzer::Fuzz();
4395 if (index < 25) {
4396 return v8::Handle<Value>(v8_num(index));
4397 }
4398 return v8::Handle<Value>();
4399}
4400
4401
4402static v8::Handle<Value> UnboxedDoubleIndexedPropertySetter(
4403 uint32_t index,
4404 Local<Value> value,
4405 const AccessorInfo& info) {
4406 ApiTestFuzzer::Fuzz();
4407 if (index < 25) {
4408 return v8::Handle<Value>(v8_num(index));
4409 }
4410 return v8::Handle<Value>();
4411}
4412
4413
4414Handle<v8::Array> UnboxedDoubleIndexedPropertyEnumerator(
4415 const AccessorInfo& info) {
4416 // Force the list of returned keys to be stored in a FastDoubleArray.
4417 Local<Script> indexed_property_names_script = Script::Compile(v8_str(
4418 "keys = new Array(); keys[125000] = 1;"
4419 "for(i = 0; i < 80000; i++) { keys[i] = i; };"
4420 "keys.length = 25; keys;"));
4421 Local<Value> result = indexed_property_names_script->Run();
4422 return Local<v8::Array>(::v8::Array::Cast(*result));
4423}
4424
4425
4426// Make sure that the the interceptor code in the runtime properly handles
4427// merging property name lists for double-array-backed arrays.
4428THREADED_TEST(IndexedInterceptorUnboxedDoubleWithIndexedAccessor) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004429 v8::HandleScope scope(v8::Isolate::GetCurrent());
ricow@chromium.org9fa09672011-07-25 11:05:35 +00004430 Local<ObjectTemplate> templ = ObjectTemplate::New();
4431 templ->SetIndexedPropertyHandler(UnboxedDoubleIndexedPropertyGetter,
4432 UnboxedDoubleIndexedPropertySetter,
4433 0,
4434 0,
4435 UnboxedDoubleIndexedPropertyEnumerator);
4436 LocalContext context;
4437 context->Global()->Set(v8_str("obj"), templ->NewInstance());
4438 // When obj is created, force it to be Stored in a FastDoubleArray.
4439 Local<Script> create_unboxed_double_script = Script::Compile(v8_str(
4440 "obj[125000] = 1; for(i = 0; i < 80000; i+=2) { obj[i] = i; } "
4441 "key_count = 0; "
4442 "for (x in obj) {key_count++;};"
4443 "obj;"));
4444 Local<Value> result = create_unboxed_double_script->Run();
4445 CHECK(result->ToObject()->HasRealIndexedProperty(2000));
4446 Local<Script> key_count_check = Script::Compile(v8_str(
4447 "key_count;"));
4448 result = key_count_check->Run();
4449 CHECK_EQ(v8_num(40013), result);
4450}
4451
4452
rossberg@chromium.org28a37082011-08-22 11:03:23 +00004453Handle<v8::Array> NonStrictArgsIndexedPropertyEnumerator(
4454 const AccessorInfo& info) {
4455 // Force the list of returned keys to be stored in a Arguments object.
4456 Local<Script> indexed_property_names_script = Script::Compile(v8_str(
4457 "function f(w,x) {"
4458 " return arguments;"
4459 "}"
4460 "keys = f(0, 1, 2, 3);"
4461 "keys;"));
4462 Local<Value> result = indexed_property_names_script->Run();
4463 return Local<v8::Array>(static_cast<v8::Array*>(::v8::Object::Cast(*result)));
4464}
4465
4466
4467static v8::Handle<Value> NonStrictIndexedPropertyGetter(
4468 uint32_t index,
4469 const AccessorInfo& info) {
4470 ApiTestFuzzer::Fuzz();
4471 if (index < 4) {
4472 return v8::Handle<Value>(v8_num(index));
4473 }
4474 return v8::Handle<Value>();
4475}
4476
4477
4478// Make sure that the the interceptor code in the runtime properly handles
4479// merging property name lists for non-string arguments arrays.
4480THREADED_TEST(IndexedInterceptorNonStrictArgsWithIndexedAccessor) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004481 v8::HandleScope scope(v8::Isolate::GetCurrent());
rossberg@chromium.org28a37082011-08-22 11:03:23 +00004482 Local<ObjectTemplate> templ = ObjectTemplate::New();
4483 templ->SetIndexedPropertyHandler(NonStrictIndexedPropertyGetter,
4484 0,
4485 0,
4486 0,
4487 NonStrictArgsIndexedPropertyEnumerator);
4488 LocalContext context;
4489 context->Global()->Set(v8_str("obj"), templ->NewInstance());
4490 Local<Script> create_args_script =
4491 Script::Compile(v8_str(
4492 "var key_count = 0;"
4493 "for (x in obj) {key_count++;} key_count;"));
4494 Local<Value> result = create_args_script->Run();
4495 CHECK_EQ(v8_num(4), result);
4496}
4497
4498
kasperl@chromium.orgeac059f2010-01-25 11:02:06 +00004499static v8::Handle<Value> IdentityIndexedPropertyGetter(
4500 uint32_t index,
4501 const AccessorInfo& info) {
kmillikin@chromium.orgf05f2912010-09-30 10:07:24 +00004502 return v8::Integer::NewFromUnsigned(index);
kasperl@chromium.orgeac059f2010-01-25 11:02:06 +00004503}
4504
4505
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00004506THREADED_TEST(IndexedInterceptorWithGetOwnPropertyDescriptor) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004507 v8::HandleScope scope(v8::Isolate::GetCurrent());
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00004508 Local<ObjectTemplate> templ = ObjectTemplate::New();
4509 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
4510
4511 LocalContext context;
4512 context->Global()->Set(v8_str("obj"), templ->NewInstance());
4513
4514 // Check fast object case.
4515 const char* fast_case_code =
4516 "Object.getOwnPropertyDescriptor(obj, 0).value.toString()";
4517 ExpectString(fast_case_code, "0");
4518
4519 // Check slow case.
4520 const char* slow_case_code =
4521 "obj.x = 1; delete obj.x;"
4522 "Object.getOwnPropertyDescriptor(obj, 1).value.toString()";
4523 ExpectString(slow_case_code, "1");
4524}
4525
4526
kasperl@chromium.orgeac059f2010-01-25 11:02:06 +00004527THREADED_TEST(IndexedInterceptorWithNoSetter) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004528 v8::HandleScope scope(v8::Isolate::GetCurrent());
kasperl@chromium.orgeac059f2010-01-25 11:02:06 +00004529 Local<ObjectTemplate> templ = ObjectTemplate::New();
4530 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
4531
4532 LocalContext context;
4533 context->Global()->Set(v8_str("obj"), templ->NewInstance());
4534
4535 const char* code =
4536 "try {"
4537 " obj[0] = 239;"
4538 " for (var i = 0; i < 100; i++) {"
4539 " var v = obj[0];"
4540 " if (v != 0) throw 'Wrong value ' + v + ' at iteration ' + i;"
4541 " }"
4542 " 'PASSED'"
4543 "} catch(e) {"
4544 " e"
4545 "}";
4546 ExpectString(code, "PASSED");
4547}
4548
4549
ager@chromium.org5c838252010-02-19 08:53:10 +00004550THREADED_TEST(IndexedInterceptorWithAccessorCheck) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004551 v8::HandleScope scope(v8::Isolate::GetCurrent());
ager@chromium.org5c838252010-02-19 08:53:10 +00004552 Local<ObjectTemplate> templ = ObjectTemplate::New();
4553 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
4554
4555 LocalContext context;
4556 Local<v8::Object> obj = templ->NewInstance();
4557 obj->TurnOnAccessCheck();
4558 context->Global()->Set(v8_str("obj"), obj);
4559
4560 const char* code =
4561 "try {"
4562 " for (var i = 0; i < 100; i++) {"
4563 " var v = obj[0];"
4564 " if (v != undefined) throw 'Wrong value ' + v + ' at iteration ' + i;"
4565 " }"
4566 " 'PASSED'"
4567 "} catch(e) {"
4568 " e"
4569 "}";
4570 ExpectString(code, "PASSED");
4571}
4572
4573
4574THREADED_TEST(IndexedInterceptorWithAccessorCheckSwitchedOn) {
4575 i::FLAG_allow_natives_syntax = true;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004576 v8::HandleScope scope(v8::Isolate::GetCurrent());
ager@chromium.org5c838252010-02-19 08:53:10 +00004577 Local<ObjectTemplate> templ = ObjectTemplate::New();
4578 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
4579
4580 LocalContext context;
4581 Local<v8::Object> obj = templ->NewInstance();
4582 context->Global()->Set(v8_str("obj"), obj);
4583
4584 const char* code =
4585 "try {"
4586 " for (var i = 0; i < 100; i++) {"
4587 " var expected = i;"
4588 " if (i == 5) {"
4589 " %EnableAccessChecks(obj);"
4590 " expected = undefined;"
4591 " }"
4592 " var v = obj[i];"
4593 " if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
4594 " if (i == 5) %DisableAccessChecks(obj);"
4595 " }"
4596 " 'PASSED'"
4597 "} catch(e) {"
4598 " e"
4599 "}";
4600 ExpectString(code, "PASSED");
4601}
4602
4603
4604THREADED_TEST(IndexedInterceptorWithDifferentIndices) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004605 v8::HandleScope scope(v8::Isolate::GetCurrent());
ager@chromium.org5c838252010-02-19 08:53:10 +00004606 Local<ObjectTemplate> templ = ObjectTemplate::New();
4607 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
4608
4609 LocalContext context;
4610 Local<v8::Object> obj = templ->NewInstance();
4611 context->Global()->Set(v8_str("obj"), obj);
4612
4613 const char* code =
4614 "try {"
4615 " for (var i = 0; i < 100; i++) {"
4616 " var v = obj[i];"
4617 " if (v != i) throw 'Wrong value ' + v + ' at iteration ' + i;"
4618 " }"
4619 " 'PASSED'"
4620 "} catch(e) {"
4621 " e"
4622 "}";
4623 ExpectString(code, "PASSED");
4624}
4625
4626
kmillikin@chromium.orgf05f2912010-09-30 10:07:24 +00004627THREADED_TEST(IndexedInterceptorWithNegativeIndices) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004628 v8::HandleScope scope(v8::Isolate::GetCurrent());
kmillikin@chromium.orgf05f2912010-09-30 10:07:24 +00004629 Local<ObjectTemplate> templ = ObjectTemplate::New();
4630 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
4631
4632 LocalContext context;
4633 Local<v8::Object> obj = templ->NewInstance();
4634 context->Global()->Set(v8_str("obj"), obj);
4635
4636 const char* code =
4637 "try {"
4638 " for (var i = 0; i < 100; i++) {"
4639 " var expected = i;"
4640 " var key = i;"
4641 " if (i == 25) {"
4642 " key = -1;"
4643 " expected = undefined;"
4644 " }"
4645 " if (i == 50) {"
4646 " /* probe minimal Smi number on 32-bit platforms */"
4647 " key = -(1 << 30);"
4648 " expected = undefined;"
4649 " }"
4650 " if (i == 75) {"
4651 " /* probe minimal Smi number on 64-bit platforms */"
4652 " key = 1 << 31;"
4653 " expected = undefined;"
4654 " }"
4655 " var v = obj[key];"
4656 " if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
4657 " }"
4658 " 'PASSED'"
4659 "} catch(e) {"
4660 " e"
4661 "}";
4662 ExpectString(code, "PASSED");
4663}
4664
4665
ager@chromium.org5c838252010-02-19 08:53:10 +00004666THREADED_TEST(IndexedInterceptorWithNotSmiLookup) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004667 v8::HandleScope scope(v8::Isolate::GetCurrent());
ager@chromium.org5c838252010-02-19 08:53:10 +00004668 Local<ObjectTemplate> templ = ObjectTemplate::New();
4669 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
4670
4671 LocalContext context;
4672 Local<v8::Object> obj = templ->NewInstance();
4673 context->Global()->Set(v8_str("obj"), obj);
4674
4675 const char* code =
4676 "try {"
4677 " for (var i = 0; i < 100; i++) {"
4678 " var expected = i;"
kmillikin@chromium.orgf05f2912010-09-30 10:07:24 +00004679 " var key = i;"
ager@chromium.org5c838252010-02-19 08:53:10 +00004680 " if (i == 50) {"
kmillikin@chromium.orgf05f2912010-09-30 10:07:24 +00004681 " key = 'foobar';"
ager@chromium.org5c838252010-02-19 08:53:10 +00004682 " expected = undefined;"
4683 " }"
kmillikin@chromium.orgf05f2912010-09-30 10:07:24 +00004684 " var v = obj[key];"
ager@chromium.org5c838252010-02-19 08:53:10 +00004685 " if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
4686 " }"
4687 " 'PASSED'"
4688 "} catch(e) {"
4689 " e"
4690 "}";
4691 ExpectString(code, "PASSED");
4692}
4693
4694
4695THREADED_TEST(IndexedInterceptorGoingMegamorphic) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004696 v8::HandleScope scope(v8::Isolate::GetCurrent());
ager@chromium.org5c838252010-02-19 08:53:10 +00004697 Local<ObjectTemplate> templ = ObjectTemplate::New();
4698 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
4699
4700 LocalContext context;
4701 Local<v8::Object> obj = templ->NewInstance();
4702 context->Global()->Set(v8_str("obj"), obj);
4703
4704 const char* code =
4705 "var original = obj;"
4706 "try {"
4707 " for (var i = 0; i < 100; i++) {"
4708 " var expected = i;"
4709 " if (i == 50) {"
4710 " obj = {50: 'foobar'};"
4711 " expected = 'foobar';"
4712 " }"
4713 " var v = obj[i];"
4714 " if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
4715 " if (i == 50) obj = original;"
4716 " }"
4717 " 'PASSED'"
4718 "} catch(e) {"
4719 " e"
4720 "}";
4721 ExpectString(code, "PASSED");
4722}
4723
4724
4725THREADED_TEST(IndexedInterceptorReceiverTurningSmi) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004726 v8::HandleScope scope(v8::Isolate::GetCurrent());
ager@chromium.org5c838252010-02-19 08:53:10 +00004727 Local<ObjectTemplate> templ = ObjectTemplate::New();
4728 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
4729
4730 LocalContext context;
4731 Local<v8::Object> obj = templ->NewInstance();
4732 context->Global()->Set(v8_str("obj"), obj);
4733
4734 const char* code =
4735 "var original = obj;"
4736 "try {"
4737 " for (var i = 0; i < 100; i++) {"
4738 " var expected = i;"
4739 " if (i == 5) {"
4740 " obj = 239;"
4741 " expected = undefined;"
4742 " }"
4743 " var v = obj[i];"
4744 " if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
4745 " if (i == 5) obj = original;"
4746 " }"
4747 " 'PASSED'"
4748 "} catch(e) {"
4749 " e"
4750 "}";
4751 ExpectString(code, "PASSED");
4752}
4753
4754
4755THREADED_TEST(IndexedInterceptorOnProto) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004756 v8::HandleScope scope(v8::Isolate::GetCurrent());
ager@chromium.org5c838252010-02-19 08:53:10 +00004757 Local<ObjectTemplate> templ = ObjectTemplate::New();
4758 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
4759
4760 LocalContext context;
4761 Local<v8::Object> obj = templ->NewInstance();
4762 context->Global()->Set(v8_str("obj"), obj);
4763
4764 const char* code =
4765 "var o = {__proto__: obj};"
4766 "try {"
4767 " for (var i = 0; i < 100; i++) {"
4768 " var v = o[i];"
4769 " if (v != i) throw 'Wrong value ' + v + ' at iteration ' + i;"
4770 " }"
4771 " 'PASSED'"
4772 "} catch(e) {"
4773 " e"
4774 "}";
4775 ExpectString(code, "PASSED");
4776}
4777
4778
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004779THREADED_TEST(MultiContexts) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004780 v8::HandleScope scope(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004781 v8::Handle<ObjectTemplate> templ = ObjectTemplate::New();
4782 templ->Set(v8_str("dummy"), v8::FunctionTemplate::New(DummyCallHandler));
4783
4784 Local<String> password = v8_str("Password");
4785
4786 // Create an environment
4787 LocalContext context0(0, templ);
4788 context0->SetSecurityToken(password);
4789 v8::Handle<v8::Object> global0 = context0->Global();
4790 global0->Set(v8_str("custom"), v8_num(1234));
4791 CHECK_EQ(1234, global0->Get(v8_str("custom"))->Int32Value());
4792
4793 // Create an independent environment
4794 LocalContext context1(0, templ);
4795 context1->SetSecurityToken(password);
4796 v8::Handle<v8::Object> global1 = context1->Global();
4797 global1->Set(v8_str("custom"), v8_num(1234));
4798 CHECK_NE(global0, global1);
4799 CHECK_EQ(1234, global0->Get(v8_str("custom"))->Int32Value());
4800 CHECK_EQ(1234, global1->Get(v8_str("custom"))->Int32Value());
4801
4802 // Now create a new context with the old global
4803 LocalContext context2(0, templ, global1);
4804 context2->SetSecurityToken(password);
4805 v8::Handle<v8::Object> global2 = context2->Global();
4806 CHECK_EQ(global1, global2);
4807 CHECK_EQ(0, global1->Get(v8_str("custom"))->Int32Value());
4808 CHECK_EQ(0, global2->Get(v8_str("custom"))->Int32Value());
4809}
4810
4811
4812THREADED_TEST(FunctionPrototypeAcrossContexts) {
4813 // Make sure that functions created by cloning boilerplates cannot
4814 // communicate through their __proto__ field.
4815
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004816 v8::HandleScope scope(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004817
4818 LocalContext env0;
4819 v8::Handle<v8::Object> global0 =
4820 env0->Global();
4821 v8::Handle<v8::Object> object0 =
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004822 global0->Get(v8_str("Object")).As<v8::Object>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004823 v8::Handle<v8::Object> tostring0 =
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004824 object0->Get(v8_str("toString")).As<v8::Object>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004825 v8::Handle<v8::Object> proto0 =
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004826 tostring0->Get(v8_str("__proto__")).As<v8::Object>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004827 proto0->Set(v8_str("custom"), v8_num(1234));
4828
4829 LocalContext env1;
4830 v8::Handle<v8::Object> global1 =
4831 env1->Global();
4832 v8::Handle<v8::Object> object1 =
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004833 global1->Get(v8_str("Object")).As<v8::Object>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004834 v8::Handle<v8::Object> tostring1 =
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004835 object1->Get(v8_str("toString")).As<v8::Object>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004836 v8::Handle<v8::Object> proto1 =
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004837 tostring1->Get(v8_str("__proto__")).As<v8::Object>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004838 CHECK(!proto1->Has(v8_str("custom")));
4839}
4840
4841
4842THREADED_TEST(Regress892105) {
4843 // Make sure that object and array literals created by cloning
4844 // boilerplates cannot communicate through their __proto__
4845 // field. This is rather difficult to check, but we try to add stuff
4846 // to Object.prototype and Array.prototype and create a new
4847 // environment. This should succeed.
4848
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004849 v8::HandleScope scope(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004850
4851 Local<String> source = v8_str("Object.prototype.obj = 1234;"
4852 "Array.prototype.arr = 4567;"
4853 "8901");
4854
4855 LocalContext env0;
4856 Local<Script> script0 = Script::Compile(source);
4857 CHECK_EQ(8901.0, script0->Run()->NumberValue());
4858
4859 LocalContext env1;
4860 Local<Script> script1 = Script::Compile(source);
4861 CHECK_EQ(8901.0, script1->Run()->NumberValue());
4862}
4863
4864
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004865THREADED_TEST(UndetectableObject) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004866 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004867 v8::HandleScope scope(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004868
4869 Local<v8::FunctionTemplate> desc =
4870 v8::FunctionTemplate::New(0, v8::Handle<Value>());
4871 desc->InstanceTemplate()->MarkAsUndetectable(); // undetectable
4872
4873 Local<v8::Object> obj = desc->GetFunction()->NewInstance();
4874 env->Global()->Set(v8_str("undetectable"), obj);
4875
4876 ExpectString("undetectable.toString()", "[object Object]");
4877 ExpectString("typeof undetectable", "undefined");
4878 ExpectString("typeof(undetectable)", "undefined");
4879 ExpectBoolean("typeof undetectable == 'undefined'", true);
4880 ExpectBoolean("typeof undetectable == 'object'", false);
4881 ExpectBoolean("if (undetectable) { true; } else { false; }", false);
4882 ExpectBoolean("!undetectable", true);
4883
4884 ExpectObject("true&&undetectable", obj);
4885 ExpectBoolean("false&&undetectable", false);
4886 ExpectBoolean("true||undetectable", true);
4887 ExpectObject("false||undetectable", obj);
4888
4889 ExpectObject("undetectable&&true", obj);
4890 ExpectObject("undetectable&&false", obj);
4891 ExpectBoolean("undetectable||true", true);
4892 ExpectBoolean("undetectable||false", false);
4893
4894 ExpectBoolean("undetectable==null", true);
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00004895 ExpectBoolean("null==undetectable", true);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004896 ExpectBoolean("undetectable==undefined", true);
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00004897 ExpectBoolean("undefined==undetectable", true);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004898 ExpectBoolean("undetectable==undetectable", true);
4899
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00004900
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004901 ExpectBoolean("undetectable===null", false);
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00004902 ExpectBoolean("null===undetectable", false);
4903 ExpectBoolean("undetectable===undefined", false);
4904 ExpectBoolean("undefined===undetectable", false);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004905 ExpectBoolean("undetectable===undetectable", true);
4906}
4907
4908
ager@chromium.org04921a82011-06-27 13:21:41 +00004909THREADED_TEST(VoidLiteral) {
ager@chromium.org04921a82011-06-27 13:21:41 +00004910 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004911 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org04921a82011-06-27 13:21:41 +00004912
4913 Local<v8::FunctionTemplate> desc =
4914 v8::FunctionTemplate::New(0, v8::Handle<Value>());
4915 desc->InstanceTemplate()->MarkAsUndetectable(); // undetectable
4916
4917 Local<v8::Object> obj = desc->GetFunction()->NewInstance();
4918 env->Global()->Set(v8_str("undetectable"), obj);
4919
4920 ExpectBoolean("undefined == void 0", true);
4921 ExpectBoolean("undetectable == void 0", true);
4922 ExpectBoolean("null == void 0", true);
4923 ExpectBoolean("undefined === void 0", true);
4924 ExpectBoolean("undetectable === void 0", false);
4925 ExpectBoolean("null === void 0", false);
4926
4927 ExpectBoolean("void 0 == undefined", true);
4928 ExpectBoolean("void 0 == undetectable", true);
4929 ExpectBoolean("void 0 == null", true);
4930 ExpectBoolean("void 0 === undefined", true);
4931 ExpectBoolean("void 0 === undetectable", false);
4932 ExpectBoolean("void 0 === null", false);
4933
4934 ExpectString("(function() {"
4935 " try {"
4936 " return x === void 0;"
4937 " } catch(e) {"
4938 " return e.toString();"
4939 " }"
4940 "})()",
4941 "ReferenceError: x is not defined");
4942 ExpectString("(function() {"
4943 " try {"
4944 " return void 0 === x;"
4945 " } catch(e) {"
4946 " return e.toString();"
4947 " }"
4948 "})()",
4949 "ReferenceError: x is not defined");
4950}
4951
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00004952
4953THREADED_TEST(ExtensibleOnUndetectable) {
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00004954 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004955 v8::HandleScope scope(env->GetIsolate());
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00004956
4957 Local<v8::FunctionTemplate> desc =
4958 v8::FunctionTemplate::New(0, v8::Handle<Value>());
4959 desc->InstanceTemplate()->MarkAsUndetectable(); // undetectable
4960
4961 Local<v8::Object> obj = desc->GetFunction()->NewInstance();
4962 env->Global()->Set(v8_str("undetectable"), obj);
4963
4964 Local<String> source = v8_str("undetectable.x = 42;"
4965 "undetectable.x");
4966
4967 Local<Script> script = Script::Compile(source);
4968
4969 CHECK_EQ(v8::Integer::New(42), script->Run());
4970
4971 ExpectBoolean("Object.isExtensible(undetectable)", true);
4972
4973 source = v8_str("Object.preventExtensions(undetectable);");
4974 script = Script::Compile(source);
4975 script->Run();
4976 ExpectBoolean("Object.isExtensible(undetectable)", false);
4977
4978 source = v8_str("undetectable.y = 2000;");
4979 script = Script::Compile(source);
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00004980 script->Run();
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00004981 ExpectBoolean("undetectable.y == undefined", true);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00004982}
4983
4984
4985
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004986THREADED_TEST(UndetectableString) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004987 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004988 v8::HandleScope scope(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004989
4990 Local<String> obj = String::NewUndetectable("foo");
4991 env->Global()->Set(v8_str("undetectable"), obj);
4992
4993 ExpectString("undetectable", "foo");
4994 ExpectString("typeof undetectable", "undefined");
4995 ExpectString("typeof(undetectable)", "undefined");
4996 ExpectBoolean("typeof undetectable == 'undefined'", true);
4997 ExpectBoolean("typeof undetectable == 'string'", false);
4998 ExpectBoolean("if (undetectable) { true; } else { false; }", false);
4999 ExpectBoolean("!undetectable", true);
5000
5001 ExpectObject("true&&undetectable", obj);
5002 ExpectBoolean("false&&undetectable", false);
5003 ExpectBoolean("true||undetectable", true);
5004 ExpectObject("false||undetectable", obj);
5005
5006 ExpectObject("undetectable&&true", obj);
5007 ExpectObject("undetectable&&false", obj);
5008 ExpectBoolean("undetectable||true", true);
5009 ExpectBoolean("undetectable||false", false);
5010
5011 ExpectBoolean("undetectable==null", true);
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00005012 ExpectBoolean("null==undetectable", true);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005013 ExpectBoolean("undetectable==undefined", true);
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00005014 ExpectBoolean("undefined==undetectable", true);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005015 ExpectBoolean("undetectable==undetectable", true);
5016
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00005017
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005018 ExpectBoolean("undetectable===null", false);
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00005019 ExpectBoolean("null===undetectable", false);
5020 ExpectBoolean("undetectable===undefined", false);
5021 ExpectBoolean("undefined===undetectable", false);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005022 ExpectBoolean("undetectable===undetectable", true);
5023}
5024
5025
vegorov@chromium.org7304bca2011-05-16 12:14:13 +00005026TEST(UndetectableOptimized) {
5027 i::FLAG_allow_natives_syntax = true;
vegorov@chromium.org7304bca2011-05-16 12:14:13 +00005028 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005029 v8::HandleScope scope(env->GetIsolate());
vegorov@chromium.org7304bca2011-05-16 12:14:13 +00005030
5031 Local<String> obj = String::NewUndetectable("foo");
5032 env->Global()->Set(v8_str("undetectable"), obj);
5033 env->Global()->Set(v8_str("detectable"), v8_str("bar"));
5034
5035 ExpectString(
5036 "function testBranch() {"
5037 " if (!%_IsUndetectableObject(undetectable)) throw 1;"
5038 " if (%_IsUndetectableObject(detectable)) throw 2;"
5039 "}\n"
5040 "function testBool() {"
5041 " var b1 = !%_IsUndetectableObject(undetectable);"
5042 " var b2 = %_IsUndetectableObject(detectable);"
5043 " if (b1) throw 3;"
5044 " if (b2) throw 4;"
5045 " return b1 == b2;"
5046 "}\n"
5047 "%OptimizeFunctionOnNextCall(testBranch);"
5048 "%OptimizeFunctionOnNextCall(testBool);"
5049 "for (var i = 0; i < 10; i++) {"
5050 " testBranch();"
5051 " testBool();"
5052 "}\n"
5053 "\"PASS\"",
5054 "PASS");
5055}
5056
5057
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005058template <typename T> static void USE(T) { }
5059
5060
5061// This test is not intended to be run, just type checked.
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00005062static inline void PersistentHandles(v8::Isolate* isolate) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005063 USE(PersistentHandles);
5064 Local<String> str = v8_str("foo");
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00005065 v8::Persistent<String> p_str = v8::Persistent<String>::New(isolate, str);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005066 USE(p_str);
5067 Local<Script> scr = Script::Compile(v8_str(""));
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00005068 v8::Persistent<Script> p_scr = v8::Persistent<Script>::New(isolate, scr);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005069 USE(p_scr);
5070 Local<ObjectTemplate> templ = ObjectTemplate::New();
5071 v8::Persistent<ObjectTemplate> p_templ =
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00005072 v8::Persistent<ObjectTemplate>::New(isolate, templ);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005073 USE(p_templ);
5074}
5075
5076
5077static v8::Handle<Value> HandleLogDelegator(const v8::Arguments& args) {
5078 ApiTestFuzzer::Fuzz();
5079 return v8::Undefined();
5080}
5081
5082
5083THREADED_TEST(GlobalObjectTemplate) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005084 v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005085 Local<ObjectTemplate> global_template = ObjectTemplate::New();
5086 global_template->Set(v8_str("JSNI_Log"),
5087 v8::FunctionTemplate::New(HandleLogDelegator));
5088 v8::Persistent<Context> context = Context::New(0, global_template);
5089 Context::Scope context_scope(context);
5090 Script::Compile(v8_str("JSNI_Log('LOG')"))->Run();
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00005091 context.Dispose(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005092}
5093
5094
5095static const char* kSimpleExtensionSource =
5096 "function Foo() {"
5097 " return 4;"
5098 "}";
5099
5100
5101THREADED_TEST(SimpleExtensions) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005102 v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005103 v8::RegisterExtension(new Extension("simpletest", kSimpleExtensionSource));
5104 const char* extension_names[] = { "simpletest" };
5105 v8::ExtensionConfiguration extensions(1, extension_names);
5106 v8::Handle<Context> context = Context::New(&extensions);
5107 Context::Scope lock(context);
5108 v8::Handle<Value> result = Script::Compile(v8_str("Foo()"))->Run();
5109 CHECK_EQ(result, v8::Integer::New(4));
5110}
5111
5112
danno@chromium.org412fa512012-09-14 13:28:26 +00005113THREADED_TEST(NullExtensions) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005114 v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
danno@chromium.org412fa512012-09-14 13:28:26 +00005115 v8::RegisterExtension(new Extension("nulltest", NULL));
5116 const char* extension_names[] = { "nulltest" };
5117 v8::ExtensionConfiguration extensions(1, extension_names);
5118 v8::Handle<Context> context = Context::New(&extensions);
5119 Context::Scope lock(context);
5120 v8::Handle<Value> result = Script::Compile(v8_str("1+3"))->Run();
5121 CHECK_EQ(result, v8::Integer::New(4));
5122}
5123
5124
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00005125static const char* kEmbeddedExtensionSource =
5126 "function Ret54321(){return 54321;}~~@@$"
5127 "$%% THIS IS A SERIES OF NON-NULL-TERMINATED STRINGS.";
5128static const int kEmbeddedExtensionSourceValidLen = 34;
5129
5130
5131THREADED_TEST(ExtensionMissingSourceLength) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005132 v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00005133 v8::RegisterExtension(new Extension("srclentest_fail",
5134 kEmbeddedExtensionSource));
5135 const char* extension_names[] = { "srclentest_fail" };
5136 v8::ExtensionConfiguration extensions(1, extension_names);
5137 v8::Handle<Context> context = Context::New(&extensions);
5138 CHECK_EQ(0, *context);
5139}
5140
5141
5142THREADED_TEST(ExtensionWithSourceLength) {
5143 for (int source_len = kEmbeddedExtensionSourceValidLen - 1;
5144 source_len <= kEmbeddedExtensionSourceValidLen + 1; ++source_len) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005145 v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00005146 i::ScopedVector<char> extension_name(32);
5147 i::OS::SNPrintF(extension_name, "ext #%d", source_len);
5148 v8::RegisterExtension(new Extension(extension_name.start(),
5149 kEmbeddedExtensionSource, 0, 0,
5150 source_len));
5151 const char* extension_names[1] = { extension_name.start() };
5152 v8::ExtensionConfiguration extensions(1, extension_names);
5153 v8::Handle<Context> context = Context::New(&extensions);
5154 if (source_len == kEmbeddedExtensionSourceValidLen) {
5155 Context::Scope lock(context);
5156 v8::Handle<Value> result = Script::Compile(v8_str("Ret54321()"))->Run();
5157 CHECK_EQ(v8::Integer::New(54321), result);
5158 } else {
5159 // Anything but exactly the right length should fail to compile.
5160 CHECK_EQ(0, *context);
5161 }
5162 }
5163}
5164
5165
ager@chromium.org18ad94b2009-09-02 08:22:29 +00005166static const char* kEvalExtensionSource1 =
5167 "function UseEval1() {"
kasperl@chromium.org2d18d102009-04-15 13:27:32 +00005168 " var x = 42;"
5169 " return eval('x');"
5170 "}";
5171
5172
ager@chromium.org18ad94b2009-09-02 08:22:29 +00005173static const char* kEvalExtensionSource2 =
5174 "(function() {"
5175 " var x = 42;"
5176 " function e() {"
5177 " return eval('x');"
5178 " }"
5179 " this.UseEval2 = e;"
5180 "})()";
5181
5182
kasperl@chromium.org2d18d102009-04-15 13:27:32 +00005183THREADED_TEST(UseEvalFromExtension) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005184 v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
ager@chromium.org18ad94b2009-09-02 08:22:29 +00005185 v8::RegisterExtension(new Extension("evaltest1", kEvalExtensionSource1));
5186 v8::RegisterExtension(new Extension("evaltest2", kEvalExtensionSource2));
5187 const char* extension_names[] = { "evaltest1", "evaltest2" };
5188 v8::ExtensionConfiguration extensions(2, extension_names);
kasperl@chromium.org2d18d102009-04-15 13:27:32 +00005189 v8::Handle<Context> context = Context::New(&extensions);
5190 Context::Scope lock(context);
ager@chromium.org18ad94b2009-09-02 08:22:29 +00005191 v8::Handle<Value> result = Script::Compile(v8_str("UseEval1()"))->Run();
5192 CHECK_EQ(result, v8::Integer::New(42));
5193 result = Script::Compile(v8_str("UseEval2()"))->Run();
kasperl@chromium.org2d18d102009-04-15 13:27:32 +00005194 CHECK_EQ(result, v8::Integer::New(42));
5195}
5196
5197
ager@chromium.org18ad94b2009-09-02 08:22:29 +00005198static const char* kWithExtensionSource1 =
5199 "function UseWith1() {"
kasperl@chromium.org2d18d102009-04-15 13:27:32 +00005200 " var x = 42;"
5201 " with({x:87}) { return x; }"
5202 "}";
5203
5204
ager@chromium.org18ad94b2009-09-02 08:22:29 +00005205
5206static const char* kWithExtensionSource2 =
5207 "(function() {"
5208 " var x = 42;"
5209 " function e() {"
5210 " with ({x:87}) { return x; }"
5211 " }"
5212 " this.UseWith2 = e;"
5213 "})()";
5214
5215
kasperl@chromium.org2d18d102009-04-15 13:27:32 +00005216THREADED_TEST(UseWithFromExtension) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005217 v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
ager@chromium.org18ad94b2009-09-02 08:22:29 +00005218 v8::RegisterExtension(new Extension("withtest1", kWithExtensionSource1));
5219 v8::RegisterExtension(new Extension("withtest2", kWithExtensionSource2));
5220 const char* extension_names[] = { "withtest1", "withtest2" };
5221 v8::ExtensionConfiguration extensions(2, extension_names);
kasperl@chromium.org2d18d102009-04-15 13:27:32 +00005222 v8::Handle<Context> context = Context::New(&extensions);
5223 Context::Scope lock(context);
ager@chromium.org18ad94b2009-09-02 08:22:29 +00005224 v8::Handle<Value> result = Script::Compile(v8_str("UseWith1()"))->Run();
5225 CHECK_EQ(result, v8::Integer::New(87));
5226 result = Script::Compile(v8_str("UseWith2()"))->Run();
kasperl@chromium.org2d18d102009-04-15 13:27:32 +00005227 CHECK_EQ(result, v8::Integer::New(87));
5228}
5229
5230
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005231THREADED_TEST(AutoExtensions) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005232 v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005233 Extension* extension = new Extension("autotest", kSimpleExtensionSource);
5234 extension->set_auto_enable(true);
5235 v8::RegisterExtension(extension);
5236 v8::Handle<Context> context = Context::New();
5237 Context::Scope lock(context);
5238 v8::Handle<Value> result = Script::Compile(v8_str("Foo()"))->Run();
5239 CHECK_EQ(result, v8::Integer::New(4));
5240}
5241
5242
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00005243static const char* kSyntaxErrorInExtensionSource =
5244 "[";
5245
5246
5247// Test that a syntax error in an extension does not cause a fatal
5248// error but results in an empty context.
5249THREADED_TEST(SyntaxErrorExtensions) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005250 v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00005251 v8::RegisterExtension(new Extension("syntaxerror",
5252 kSyntaxErrorInExtensionSource));
5253 const char* extension_names[] = { "syntaxerror" };
5254 v8::ExtensionConfiguration extensions(1, extension_names);
5255 v8::Handle<Context> context = Context::New(&extensions);
5256 CHECK(context.IsEmpty());
5257}
5258
5259
5260static const char* kExceptionInExtensionSource =
5261 "throw 42";
5262
5263
5264// Test that an exception when installing an extension does not cause
5265// a fatal error but results in an empty context.
5266THREADED_TEST(ExceptionExtensions) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005267 v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00005268 v8::RegisterExtension(new Extension("exception",
5269 kExceptionInExtensionSource));
5270 const char* extension_names[] = { "exception" };
5271 v8::ExtensionConfiguration extensions(1, extension_names);
5272 v8::Handle<Context> context = Context::New(&extensions);
5273 CHECK(context.IsEmpty());
5274}
5275
5276
ager@chromium.org5b2fbee2010-09-08 06:38:15 +00005277static const char* kNativeCallInExtensionSource =
5278 "function call_runtime_last_index_of(x) {"
5279 " return %StringLastIndexOf(x, 'bob', 10);"
5280 "}";
5281
5282
5283static const char* kNativeCallTest =
5284 "call_runtime_last_index_of('bobbobboellebobboellebobbob');";
5285
5286// Test that a native runtime calls are supported in extensions.
5287THREADED_TEST(NativeCallInExtensions) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005288 v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
ager@chromium.org5b2fbee2010-09-08 06:38:15 +00005289 v8::RegisterExtension(new Extension("nativecall",
5290 kNativeCallInExtensionSource));
5291 const char* extension_names[] = { "nativecall" };
5292 v8::ExtensionConfiguration extensions(1, extension_names);
5293 v8::Handle<Context> context = Context::New(&extensions);
5294 Context::Scope lock(context);
5295 v8::Handle<Value> result = Script::Compile(v8_str(kNativeCallTest))->Run();
5296 CHECK_EQ(result, v8::Integer::New(3));
5297}
5298
5299
whesse@chromium.org7b260152011-06-20 15:33:18 +00005300class NativeFunctionExtension : public Extension {
5301 public:
5302 NativeFunctionExtension(const char* name,
5303 const char* source,
5304 v8::InvocationCallback fun = &Echo)
5305 : Extension(name, source),
5306 function_(fun) { }
5307
5308 virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction(
5309 v8::Handle<v8::String> name) {
5310 return v8::FunctionTemplate::New(function_);
5311 }
5312
5313 static v8::Handle<v8::Value> Echo(const v8::Arguments& args) {
5314 if (args.Length() >= 1) return (args[0]);
5315 return v8::Undefined();
5316 }
5317 private:
5318 v8::InvocationCallback function_;
5319};
5320
5321
5322THREADED_TEST(NativeFunctionDeclaration) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005323 v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
whesse@chromium.org7b260152011-06-20 15:33:18 +00005324 const char* name = "nativedecl";
5325 v8::RegisterExtension(new NativeFunctionExtension(name,
5326 "native function foo();"));
5327 const char* extension_names[] = { name };
5328 v8::ExtensionConfiguration extensions(1, extension_names);
5329 v8::Handle<Context> context = Context::New(&extensions);
5330 Context::Scope lock(context);
5331 v8::Handle<Value> result = Script::Compile(v8_str("foo(42);"))->Run();
5332 CHECK_EQ(result, v8::Integer::New(42));
5333}
5334
5335
5336THREADED_TEST(NativeFunctionDeclarationError) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005337 v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
lrn@chromium.org67e236d2011-06-23 10:18:16 +00005338 const char* name = "nativedeclerr";
whesse@chromium.org7b260152011-06-20 15:33:18 +00005339 // Syntax error in extension code.
5340 v8::RegisterExtension(new NativeFunctionExtension(name,
5341 "native\nfunction foo();"));
5342 const char* extension_names[] = { name };
5343 v8::ExtensionConfiguration extensions(1, extension_names);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00005344 v8::Handle<Context> context(Context::New(&extensions));
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00005345 CHECK(context.IsEmpty());
whesse@chromium.org7b260152011-06-20 15:33:18 +00005346}
5347
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00005348
whesse@chromium.org7b260152011-06-20 15:33:18 +00005349THREADED_TEST(NativeFunctionDeclarationErrorEscape) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005350 v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
lrn@chromium.org67e236d2011-06-23 10:18:16 +00005351 const char* name = "nativedeclerresc";
whesse@chromium.org7b260152011-06-20 15:33:18 +00005352 // Syntax error in extension code - escape code in "native" means that
5353 // it's not treated as a keyword.
5354 v8::RegisterExtension(new NativeFunctionExtension(
5355 name,
5356 "nativ\\u0065 function foo();"));
5357 const char* extension_names[] = { name };
5358 v8::ExtensionConfiguration extensions(1, extension_names);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00005359 v8::Handle<Context> context(Context::New(&extensions));
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00005360 CHECK(context.IsEmpty());
whesse@chromium.org7b260152011-06-20 15:33:18 +00005361}
5362
5363
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005364static void CheckDependencies(const char* name, const char* expected) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005365 v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005366 v8::ExtensionConfiguration config(1, &name);
5367 LocalContext context(&config);
5368 CHECK_EQ(String::New(expected), context->Global()->Get(v8_str("loaded")));
5369}
5370
5371
5372/*
5373 * Configuration:
5374 *
5375 * /-- B <--\
5376 * A <- -- D <-- E
5377 * \-- C <--/
5378 */
5379THREADED_TEST(ExtensionDependency) {
5380 static const char* kEDeps[] = { "D" };
5381 v8::RegisterExtension(new Extension("E", "this.loaded += 'E';", 1, kEDeps));
5382 static const char* kDDeps[] = { "B", "C" };
5383 v8::RegisterExtension(new Extension("D", "this.loaded += 'D';", 2, kDDeps));
5384 static const char* kBCDeps[] = { "A" };
5385 v8::RegisterExtension(new Extension("B", "this.loaded += 'B';", 1, kBCDeps));
5386 v8::RegisterExtension(new Extension("C", "this.loaded += 'C';", 1, kBCDeps));
5387 v8::RegisterExtension(new Extension("A", "this.loaded += 'A';"));
5388 CheckDependencies("A", "undefinedA");
5389 CheckDependencies("B", "undefinedAB");
5390 CheckDependencies("C", "undefinedAC");
5391 CheckDependencies("D", "undefinedABCD");
5392 CheckDependencies("E", "undefinedABCDE");
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005393 v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005394 static const char* exts[2] = { "C", "E" };
5395 v8::ExtensionConfiguration config(2, exts);
5396 LocalContext context(&config);
5397 CHECK_EQ(v8_str("undefinedACBDE"), context->Global()->Get(v8_str("loaded")));
5398}
5399
5400
5401static const char* kExtensionTestScript =
5402 "native function A();"
5403 "native function B();"
5404 "native function C();"
5405 "function Foo(i) {"
5406 " if (i == 0) return A();"
5407 " if (i == 1) return B();"
5408 " if (i == 2) return C();"
5409 "}";
5410
5411
5412static v8::Handle<Value> CallFun(const v8::Arguments& args) {
5413 ApiTestFuzzer::Fuzz();
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00005414 if (args.IsConstructCall()) {
5415 args.This()->Set(v8_str("data"), args.Data());
5416 return v8::Null();
5417 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005418 return args.Data();
5419}
5420
5421
5422class FunctionExtension : public Extension {
5423 public:
5424 FunctionExtension() : Extension("functiontest", kExtensionTestScript) { }
5425 virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction(
5426 v8::Handle<String> name);
5427};
5428
5429
5430static int lookup_count = 0;
5431v8::Handle<v8::FunctionTemplate> FunctionExtension::GetNativeFunction(
5432 v8::Handle<String> name) {
5433 lookup_count++;
5434 if (name->Equals(v8_str("A"))) {
5435 return v8::FunctionTemplate::New(CallFun, v8::Integer::New(8));
5436 } else if (name->Equals(v8_str("B"))) {
5437 return v8::FunctionTemplate::New(CallFun, v8::Integer::New(7));
5438 } else if (name->Equals(v8_str("C"))) {
5439 return v8::FunctionTemplate::New(CallFun, v8::Integer::New(6));
5440 } else {
5441 return v8::Handle<v8::FunctionTemplate>();
5442 }
5443}
5444
5445
5446THREADED_TEST(FunctionLookup) {
5447 v8::RegisterExtension(new FunctionExtension());
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005448 v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005449 static const char* exts[1] = { "functiontest" };
5450 v8::ExtensionConfiguration config(1, exts);
5451 LocalContext context(&config);
5452 CHECK_EQ(3, lookup_count);
5453 CHECK_EQ(v8::Integer::New(8), Script::Compile(v8_str("Foo(0)"))->Run());
5454 CHECK_EQ(v8::Integer::New(7), Script::Compile(v8_str("Foo(1)"))->Run());
5455 CHECK_EQ(v8::Integer::New(6), Script::Compile(v8_str("Foo(2)"))->Run());
5456}
5457
5458
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00005459THREADED_TEST(NativeFunctionConstructCall) {
5460 v8::RegisterExtension(new FunctionExtension());
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005461 v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00005462 static const char* exts[1] = { "functiontest" };
5463 v8::ExtensionConfiguration config(1, exts);
5464 LocalContext context(&config);
5465 for (int i = 0; i < 10; i++) {
5466 // Run a few times to ensure that allocation of objects doesn't
5467 // change behavior of a constructor function.
5468 CHECK_EQ(v8::Integer::New(8),
5469 Script::Compile(v8_str("(new A()).data"))->Run());
5470 CHECK_EQ(v8::Integer::New(7),
5471 Script::Compile(v8_str("(new B()).data"))->Run());
5472 CHECK_EQ(v8::Integer::New(6),
5473 Script::Compile(v8_str("(new C()).data"))->Run());
5474 }
5475}
5476
5477
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005478static const char* last_location;
5479static const char* last_message;
5480void StoringErrorCallback(const char* location, const char* message) {
5481 if (last_location == NULL) {
5482 last_location = location;
5483 last_message = message;
5484 }
5485}
5486
5487
5488// ErrorReporting creates a circular extensions configuration and
5489// tests that the fatal error handler gets called. This renders V8
5490// unusable and therefore this test cannot be run in parallel.
5491TEST(ErrorReporting) {
5492 v8::V8::SetFatalErrorHandler(StoringErrorCallback);
5493 static const char* aDeps[] = { "B" };
5494 v8::RegisterExtension(new Extension("A", "", 1, aDeps));
5495 static const char* bDeps[] = { "A" };
5496 v8::RegisterExtension(new Extension("B", "", 1, bDeps));
5497 last_location = NULL;
5498 v8::ExtensionConfiguration config(1, bDeps);
5499 v8::Handle<Context> context = Context::New(&config);
5500 CHECK(context.IsEmpty());
5501 CHECK_NE(last_location, NULL);
5502}
5503
5504
ager@chromium.org7c537e22008-10-16 08:43:32 +00005505static const char* js_code_causing_huge_string_flattening =
5506 "var str = 'X';"
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +00005507 "for (var i = 0; i < 30; i++) {"
ager@chromium.org7c537e22008-10-16 08:43:32 +00005508 " str = str + str;"
5509 "}"
5510 "str.match(/X/);";
5511
5512
5513void OOMCallback(const char* location, const char* message) {
5514 exit(0);
5515}
5516
5517
5518TEST(RegexpOutOfMemory) {
5519 // Execute a script that causes out of memory when flattening a string.
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005520 v8::HandleScope scope(v8::Isolate::GetCurrent());
ager@chromium.org7c537e22008-10-16 08:43:32 +00005521 v8::V8::SetFatalErrorHandler(OOMCallback);
5522 LocalContext context;
5523 Local<Script> script =
5524 Script::Compile(String::New(js_code_causing_huge_string_flattening));
5525 last_location = NULL;
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00005526 script->Run();
ager@chromium.org7c537e22008-10-16 08:43:32 +00005527
5528 CHECK(false); // Should not return.
5529}
5530
5531
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005532static void MissingScriptInfoMessageListener(v8::Handle<v8::Message> message,
5533 v8::Handle<Value> data) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00005534 CHECK(message->GetScriptResourceName()->IsUndefined());
5535 CHECK_EQ(v8::Undefined(), message->GetScriptResourceName());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005536 message->GetLineNumber();
5537 message->GetSourceLine();
5538}
5539
5540
5541THREADED_TEST(ErrorWithMissingScriptInfo) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005542 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005543 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005544 v8::V8::AddMessageListener(MissingScriptInfoMessageListener);
5545 Script::Compile(v8_str("throw Error()"))->Run();
5546 v8::V8::RemoveMessageListeners(MissingScriptInfoMessageListener);
5547}
5548
5549
5550int global_index = 0;
5551
5552class Snorkel {
5553 public:
5554 Snorkel() { index_ = global_index++; }
5555 int index_;
5556};
5557
5558class Whammy {
5559 public:
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00005560 explicit Whammy(v8::Isolate* isolate) : cursor_(0), isolate_(isolate) { }
5561 ~Whammy() { script_.Dispose(isolate_); }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005562 v8::Handle<Script> getScript() {
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00005563 if (script_.IsEmpty()) {
5564 script_ = v8::Persistent<Script>::New(isolate_,
5565 v8_compile("({}).blammo"));
5566 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005567 return Local<Script>(*script_);
5568 }
5569
5570 public:
5571 static const int kObjectCount = 256;
5572 int cursor_;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00005573 v8::Isolate* isolate_;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005574 v8::Persistent<v8::Object> objects_[kObjectCount];
5575 v8::Persistent<Script> script_;
5576};
5577
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00005578static void HandleWeakReference(v8::Isolate* isolate,
5579 v8::Persistent<v8::Value> obj,
5580 void* data) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005581 Snorkel* snorkel = reinterpret_cast<Snorkel*>(data);
5582 delete snorkel;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00005583 obj.ClearWeak(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005584}
5585
5586v8::Handle<Value> WhammyPropertyGetter(Local<String> name,
5587 const AccessorInfo& info) {
5588 Whammy* whammy =
5589 static_cast<Whammy*>(v8::Handle<v8::External>::Cast(info.Data())->Value());
5590
5591 v8::Persistent<v8::Object> prev = whammy->objects_[whammy->cursor_];
5592
5593 v8::Handle<v8::Object> obj = v8::Object::New();
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00005594 v8::Persistent<v8::Object> global =
5595 v8::Persistent<v8::Object>::New(info.GetIsolate(), obj);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005596 if (!prev.IsEmpty()) {
5597 prev->Set(v8_str("next"), obj);
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00005598 prev.MakeWeak(info.GetIsolate(), new Snorkel(), &HandleWeakReference);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005599 whammy->objects_[whammy->cursor_].Clear();
5600 }
5601 whammy->objects_[whammy->cursor_] = global;
5602 whammy->cursor_ = (whammy->cursor_ + 1) % Whammy::kObjectCount;
5603 return whammy->getScript()->Run();
5604}
5605
5606THREADED_TEST(WeakReference) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005607 v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005608 v8::Handle<v8::ObjectTemplate> templ= v8::ObjectTemplate::New();
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00005609 Whammy* whammy = new Whammy(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005610 templ->SetNamedPropertyHandler(WhammyPropertyGetter,
5611 0, 0, 0, 0,
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +00005612 v8::External::New(whammy));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005613 const char* extension_list[] = { "v8/gc" };
5614 v8::ExtensionConfiguration extensions(1, extension_list);
5615 v8::Persistent<Context> context = Context::New(&extensions);
5616 Context::Scope context_scope(context);
5617
5618 v8::Handle<v8::Object> interceptor = templ->NewInstance();
5619 context->Global()->Set(v8_str("whammy"), interceptor);
5620 const char* code =
5621 "var last;"
5622 "for (var i = 0; i < 10000; i++) {"
5623 " var obj = whammy.length;"
5624 " if (last) last.next = obj;"
5625 " last = obj;"
5626 "}"
5627 "gc();"
5628 "4";
5629 v8::Handle<Value> result = CompileRun(code);
5630 CHECK_EQ(4.0, result->NumberValue());
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +00005631 delete whammy;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00005632 context.Dispose(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005633}
5634
5635
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00005636static void DisposeAndSetFlag(v8::Isolate* isolate,
5637 v8::Persistent<v8::Value> obj,
5638 void* data) {
5639 obj.Dispose(isolate);
ager@chromium.orgc4c92722009-11-18 14:12:51 +00005640 obj.Clear();
ager@chromium.orgc4c92722009-11-18 14:12:51 +00005641 *(reinterpret_cast<bool*>(data)) = true;
5642}
5643
ager@chromium.orgc4c92722009-11-18 14:12:51 +00005644
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00005645THREADED_TEST(IndependentWeakHandle) {
ager@chromium.orgc4c92722009-11-18 14:12:51 +00005646 v8::Persistent<Context> context = Context::New();
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00005647 v8::Isolate* iso = context->GetIsolate();
ager@chromium.orgc4c92722009-11-18 14:12:51 +00005648 Context::Scope context_scope(context);
5649
mvstanton@chromium.orge4ac3ef2012-11-12 14:53:34 +00005650 v8::Persistent<v8::Object> object_a, object_b;
ager@chromium.orgc4c92722009-11-18 14:12:51 +00005651
5652 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005653 v8::HandleScope handle_scope(iso);
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00005654 object_a = v8::Persistent<v8::Object>::New(iso, v8::Object::New());
5655 object_b = v8::Persistent<v8::Object>::New(iso, v8::Object::New());
ager@chromium.orgc4c92722009-11-18 14:12:51 +00005656 }
5657
5658 bool object_a_disposed = false;
mvstanton@chromium.orge4ac3ef2012-11-12 14:53:34 +00005659 bool object_b_disposed = false;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00005660 object_a.MakeWeak(iso, &object_a_disposed, &DisposeAndSetFlag);
5661 object_b.MakeWeak(iso, &object_b_disposed, &DisposeAndSetFlag);
5662 CHECK(!object_b.IsIndependent(iso));
5663 object_a.MarkIndependent(iso);
5664 object_b.MarkIndependent(iso);
5665 CHECK(object_b.IsIndependent(iso));
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00005666 HEAP->PerformScavenge();
5667 CHECK(object_a_disposed);
mvstanton@chromium.orge4ac3ef2012-11-12 14:53:34 +00005668 CHECK(object_b_disposed);
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00005669}
ager@chromium.orgc4c92722009-11-18 14:12:51 +00005670
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00005671
5672static void InvokeScavenge() {
5673 HEAP->PerformScavenge();
5674}
5675
5676
5677static void InvokeMarkSweep() {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00005678 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00005679}
5680
5681
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00005682static void ForceScavenge(v8::Isolate* isolate,
5683 v8::Persistent<v8::Value> obj,
5684 void* data) {
5685 obj.Dispose(isolate);
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00005686 obj.Clear();
5687 *(reinterpret_cast<bool*>(data)) = true;
5688 InvokeScavenge();
5689}
5690
5691
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00005692static void ForceMarkSweep(v8::Isolate* isolate,
5693 v8::Persistent<v8::Value> obj,
5694 void* data) {
5695 obj.Dispose(isolate);
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00005696 obj.Clear();
5697 *(reinterpret_cast<bool*>(data)) = true;
5698 InvokeMarkSweep();
5699}
5700
5701
5702THREADED_TEST(GCFromWeakCallbacks) {
5703 v8::Persistent<Context> context = Context::New();
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00005704 v8::Isolate* isolate = context->GetIsolate();
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00005705 Context::Scope context_scope(context);
5706
5707 static const int kNumberOfGCTypes = 2;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00005708 v8::NearDeathCallback gc_forcing_callback[kNumberOfGCTypes] =
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00005709 {&ForceScavenge, &ForceMarkSweep};
5710
5711 typedef void (*GCInvoker)();
5712 GCInvoker invoke_gc[kNumberOfGCTypes] = {&InvokeScavenge, &InvokeMarkSweep};
5713
5714 for (int outer_gc = 0; outer_gc < kNumberOfGCTypes; outer_gc++) {
5715 for (int inner_gc = 0; inner_gc < kNumberOfGCTypes; inner_gc++) {
5716 v8::Persistent<v8::Object> object;
5717 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005718 v8::HandleScope handle_scope(isolate);
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00005719 object = v8::Persistent<v8::Object>::New(isolate, v8::Object::New());
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00005720 }
5721 bool disposed = false;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00005722 object.MakeWeak(isolate, &disposed, gc_forcing_callback[inner_gc]);
5723 object.MarkIndependent(isolate);
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00005724 invoke_gc[outer_gc]();
5725 CHECK(disposed);
5726 }
ager@chromium.orgc4c92722009-11-18 14:12:51 +00005727 }
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00005728}
5729
5730
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00005731static void RevivingCallback(v8::Isolate* isolate,
5732 v8::Persistent<v8::Value> obj,
5733 void* data) {
5734 obj.ClearWeak(isolate);
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00005735 *(reinterpret_cast<bool*>(data)) = true;
5736}
5737
5738
5739THREADED_TEST(IndependentHandleRevival) {
5740 v8::Persistent<Context> context = Context::New();
5741 Context::Scope context_scope(context);
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00005742 v8::Isolate* isolate = context->GetIsolate();
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00005743
5744 v8::Persistent<v8::Object> object;
5745 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005746 v8::HandleScope handle_scope(isolate);
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00005747 object = v8::Persistent<v8::Object>::New(isolate, v8::Object::New());
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00005748 object->Set(v8_str("x"), v8::Integer::New(1));
5749 v8::Local<String> y_str = v8_str("y");
5750 object->Set(y_str, y_str);
5751 }
5752 bool revived = false;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00005753 object.MakeWeak(isolate, &revived, &RevivingCallback);
5754 object.MarkIndependent(isolate);
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00005755 HEAP->PerformScavenge();
5756 CHECK(revived);
yangguo@chromium.orgd2899aa2012-06-21 11:16:20 +00005757 HEAP->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00005758 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005759 v8::HandleScope handle_scope(isolate);
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00005760 v8::Local<String> y_str = v8_str("y");
5761 CHECK_EQ(v8::Integer::New(1), object->Get(v8_str("x")));
5762 CHECK(object->Get(y_str)->Equals(y_str));
5763 }
ager@chromium.orgc4c92722009-11-18 14:12:51 +00005764}
5765
5766
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005767v8::Handle<Function> args_fun;
5768
5769
5770static v8::Handle<Value> ArgumentsTestCallback(const v8::Arguments& args) {
5771 ApiTestFuzzer::Fuzz();
5772 CHECK_EQ(args_fun, args.Callee());
5773 CHECK_EQ(3, args.Length());
5774 CHECK_EQ(v8::Integer::New(1), args[0]);
5775 CHECK_EQ(v8::Integer::New(2), args[1]);
5776 CHECK_EQ(v8::Integer::New(3), args[2]);
5777 CHECK_EQ(v8::Undefined(), args[3]);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005778 v8::HandleScope scope(args.GetIsolate());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00005779 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005780 return v8::Undefined();
5781}
5782
5783
5784THREADED_TEST(Arguments) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005785 v8::HandleScope scope(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005786 v8::Handle<v8::ObjectTemplate> global = ObjectTemplate::New();
5787 global->Set(v8_str("f"), v8::FunctionTemplate::New(ArgumentsTestCallback));
5788 LocalContext context(NULL, global);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00005789 args_fun = context->Global()->Get(v8_str("f")).As<Function>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005790 v8_compile("f(1, 2, 3)")->Run();
5791}
5792
5793
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005794static v8::Handle<Value> NoBlockGetterX(Local<String> name,
5795 const AccessorInfo&) {
5796 return v8::Handle<Value>();
5797}
5798
5799
5800static v8::Handle<Value> NoBlockGetterI(uint32_t index,
5801 const AccessorInfo&) {
5802 return v8::Handle<Value>();
5803}
5804
5805
5806static v8::Handle<v8::Boolean> PDeleter(Local<String> name,
5807 const AccessorInfo&) {
5808 if (!name->Equals(v8_str("foo"))) {
5809 return v8::Handle<v8::Boolean>(); // not intercepted
5810 }
5811
5812 return v8::False(); // intercepted, and don't delete the property
5813}
5814
5815
5816static v8::Handle<v8::Boolean> IDeleter(uint32_t index, const AccessorInfo&) {
5817 if (index != 2) {
5818 return v8::Handle<v8::Boolean>(); // not intercepted
5819 }
5820
5821 return v8::False(); // intercepted, and don't delete the property
5822}
5823
5824
5825THREADED_TEST(Deleter) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005826 v8::HandleScope scope(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005827 v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
5828 obj->SetNamedPropertyHandler(NoBlockGetterX, NULL, NULL, PDeleter, NULL);
5829 obj->SetIndexedPropertyHandler(NoBlockGetterI, NULL, NULL, IDeleter, NULL);
5830 LocalContext context;
5831 context->Global()->Set(v8_str("k"), obj->NewInstance());
5832 CompileRun(
5833 "k.foo = 'foo';"
5834 "k.bar = 'bar';"
5835 "k[2] = 2;"
5836 "k[4] = 4;");
5837 CHECK(v8_compile("delete k.foo")->Run()->IsFalse());
5838 CHECK(v8_compile("delete k.bar")->Run()->IsTrue());
5839
5840 CHECK_EQ(v8_compile("k.foo")->Run(), v8_str("foo"));
5841 CHECK(v8_compile("k.bar")->Run()->IsUndefined());
5842
5843 CHECK(v8_compile("delete k[2]")->Run()->IsFalse());
5844 CHECK(v8_compile("delete k[4]")->Run()->IsTrue());
5845
5846 CHECK_EQ(v8_compile("k[2]")->Run(), v8_num(2));
5847 CHECK(v8_compile("k[4]")->Run()->IsUndefined());
5848}
5849
5850
5851static v8::Handle<Value> GetK(Local<String> name, const AccessorInfo&) {
5852 ApiTestFuzzer::Fuzz();
ager@chromium.org65dad4b2009-04-23 08:48:43 +00005853 if (name->Equals(v8_str("foo")) ||
5854 name->Equals(v8_str("bar")) ||
5855 name->Equals(v8_str("baz"))) {
5856 return v8::Undefined();
5857 }
5858 return v8::Handle<Value>();
5859}
5860
5861
5862static v8::Handle<Value> IndexedGetK(uint32_t index, const AccessorInfo&) {
5863 ApiTestFuzzer::Fuzz();
5864 if (index == 0 || index == 1) return v8::Undefined();
5865 return v8::Handle<Value>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005866}
5867
5868
5869static v8::Handle<v8::Array> NamedEnum(const AccessorInfo&) {
5870 ApiTestFuzzer::Fuzz();
5871 v8::Handle<v8::Array> result = v8::Array::New(3);
5872 result->Set(v8::Integer::New(0), v8_str("foo"));
5873 result->Set(v8::Integer::New(1), v8_str("bar"));
5874 result->Set(v8::Integer::New(2), v8_str("baz"));
5875 return result;
5876}
5877
5878
5879static v8::Handle<v8::Array> IndexedEnum(const AccessorInfo&) {
5880 ApiTestFuzzer::Fuzz();
5881 v8::Handle<v8::Array> result = v8::Array::New(2);
ager@chromium.org65dad4b2009-04-23 08:48:43 +00005882 result->Set(v8::Integer::New(0), v8_str("0"));
5883 result->Set(v8::Integer::New(1), v8_str("1"));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005884 return result;
5885}
5886
5887
5888THREADED_TEST(Enumerators) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005889 v8::HandleScope scope(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005890 v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
5891 obj->SetNamedPropertyHandler(GetK, NULL, NULL, NULL, NamedEnum);
ager@chromium.org65dad4b2009-04-23 08:48:43 +00005892 obj->SetIndexedPropertyHandler(IndexedGetK, NULL, NULL, NULL, IndexedEnum);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005893 LocalContext context;
5894 context->Global()->Set(v8_str("k"), obj->NewInstance());
5895 v8::Handle<v8::Array> result = v8::Handle<v8::Array>::Cast(CompileRun(
ager@chromium.org65dad4b2009-04-23 08:48:43 +00005896 "k[10] = 0;"
5897 "k.a = 0;"
5898 "k[5] = 0;"
5899 "k.b = 0;"
5900 "k[4294967295] = 0;"
5901 "k.c = 0;"
5902 "k[4294967296] = 0;"
5903 "k.d = 0;"
5904 "k[140000] = 0;"
5905 "k.e = 0;"
5906 "k[30000000000] = 0;"
5907 "k.f = 0;"
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005908 "var result = [];"
5909 "for (var prop in k) {"
5910 " result.push(prop);"
5911 "}"
5912 "result"));
ager@chromium.org65dad4b2009-04-23 08:48:43 +00005913 // Check that we get all the property names returned including the
5914 // ones from the enumerators in the right order: indexed properties
5915 // in numerical order, indexed interceptor properties, named
5916 // properties in insertion order, named interceptor properties.
5917 // This order is not mandated by the spec, so this test is just
5918 // documenting our behavior.
5919 CHECK_EQ(17, result->Length());
5920 // Indexed properties in numerical order.
5921 CHECK_EQ(v8_str("5"), result->Get(v8::Integer::New(0)));
5922 CHECK_EQ(v8_str("10"), result->Get(v8::Integer::New(1)));
5923 CHECK_EQ(v8_str("140000"), result->Get(v8::Integer::New(2)));
5924 CHECK_EQ(v8_str("4294967295"), result->Get(v8::Integer::New(3)));
5925 // Indexed interceptor properties in the order they are returned
5926 // from the enumerator interceptor.
5927 CHECK_EQ(v8_str("0"), result->Get(v8::Integer::New(4)));
5928 CHECK_EQ(v8_str("1"), result->Get(v8::Integer::New(5)));
5929 // Named properties in insertion order.
5930 CHECK_EQ(v8_str("a"), result->Get(v8::Integer::New(6)));
5931 CHECK_EQ(v8_str("b"), result->Get(v8::Integer::New(7)));
5932 CHECK_EQ(v8_str("c"), result->Get(v8::Integer::New(8)));
5933 CHECK_EQ(v8_str("4294967296"), result->Get(v8::Integer::New(9)));
5934 CHECK_EQ(v8_str("d"), result->Get(v8::Integer::New(10)));
5935 CHECK_EQ(v8_str("e"), result->Get(v8::Integer::New(11)));
5936 CHECK_EQ(v8_str("30000000000"), result->Get(v8::Integer::New(12)));
5937 CHECK_EQ(v8_str("f"), result->Get(v8::Integer::New(13)));
5938 // Named interceptor properties.
5939 CHECK_EQ(v8_str("foo"), result->Get(v8::Integer::New(14)));
5940 CHECK_EQ(v8_str("bar"), result->Get(v8::Integer::New(15)));
5941 CHECK_EQ(v8_str("baz"), result->Get(v8::Integer::New(16)));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005942}
5943
5944
5945int p_getter_count;
5946int p_getter_count2;
5947
5948
5949static v8::Handle<Value> PGetter(Local<String> name, const AccessorInfo& info) {
5950 ApiTestFuzzer::Fuzz();
5951 p_getter_count++;
5952 v8::Handle<v8::Object> global = Context::GetCurrent()->Global();
5953 CHECK_EQ(info.Holder(), global->Get(v8_str("o1")));
5954 if (name->Equals(v8_str("p1"))) {
5955 CHECK_EQ(info.This(), global->Get(v8_str("o1")));
5956 } else if (name->Equals(v8_str("p2"))) {
5957 CHECK_EQ(info.This(), global->Get(v8_str("o2")));
5958 } else if (name->Equals(v8_str("p3"))) {
5959 CHECK_EQ(info.This(), global->Get(v8_str("o3")));
5960 } else if (name->Equals(v8_str("p4"))) {
5961 CHECK_EQ(info.This(), global->Get(v8_str("o4")));
5962 }
5963 return v8::Undefined();
5964}
5965
5966
5967static void RunHolderTest(v8::Handle<v8::ObjectTemplate> obj) {
5968 ApiTestFuzzer::Fuzz();
5969 LocalContext context;
5970 context->Global()->Set(v8_str("o1"), obj->NewInstance());
5971 CompileRun(
5972 "o1.__proto__ = { };"
5973 "var o2 = { __proto__: o1 };"
5974 "var o3 = { __proto__: o2 };"
5975 "var o4 = { __proto__: o3 };"
5976 "for (var i = 0; i < 10; i++) o4.p4;"
5977 "for (var i = 0; i < 10; i++) o3.p3;"
5978 "for (var i = 0; i < 10; i++) o2.p2;"
5979 "for (var i = 0; i < 10; i++) o1.p1;");
5980}
5981
5982
5983static v8::Handle<Value> PGetter2(Local<String> name,
5984 const AccessorInfo& info) {
5985 ApiTestFuzzer::Fuzz();
5986 p_getter_count2++;
5987 v8::Handle<v8::Object> global = Context::GetCurrent()->Global();
5988 CHECK_EQ(info.Holder(), global->Get(v8_str("o1")));
5989 if (name->Equals(v8_str("p1"))) {
5990 CHECK_EQ(info.This(), global->Get(v8_str("o1")));
5991 } else if (name->Equals(v8_str("p2"))) {
5992 CHECK_EQ(info.This(), global->Get(v8_str("o2")));
5993 } else if (name->Equals(v8_str("p3"))) {
5994 CHECK_EQ(info.This(), global->Get(v8_str("o3")));
5995 } else if (name->Equals(v8_str("p4"))) {
5996 CHECK_EQ(info.This(), global->Get(v8_str("o4")));
5997 }
5998 return v8::Undefined();
5999}
6000
6001
6002THREADED_TEST(GetterHolders) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00006003 v8::HandleScope scope(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006004 v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
6005 obj->SetAccessor(v8_str("p1"), PGetter);
6006 obj->SetAccessor(v8_str("p2"), PGetter);
6007 obj->SetAccessor(v8_str("p3"), PGetter);
6008 obj->SetAccessor(v8_str("p4"), PGetter);
6009 p_getter_count = 0;
6010 RunHolderTest(obj);
6011 CHECK_EQ(40, p_getter_count);
6012}
6013
6014
6015THREADED_TEST(PreInterceptorHolders) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00006016 v8::HandleScope scope(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006017 v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
6018 obj->SetNamedPropertyHandler(PGetter2);
6019 p_getter_count2 = 0;
6020 RunHolderTest(obj);
6021 CHECK_EQ(40, p_getter_count2);
6022}
6023
6024
6025THREADED_TEST(ObjectInstantiation) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00006026 v8::HandleScope scope(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006027 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
6028 templ->SetAccessor(v8_str("t"), PGetter2);
6029 LocalContext context;
6030 context->Global()->Set(v8_str("o"), templ->NewInstance());
6031 for (int i = 0; i < 100; i++) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00006032 v8::HandleScope inner_scope(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006033 v8::Handle<v8::Object> obj = templ->NewInstance();
6034 CHECK_NE(obj, context->Global()->Get(v8_str("o")));
6035 context->Global()->Set(v8_str("o2"), obj);
6036 v8::Handle<Value> value =
6037 Script::Compile(v8_str("o.__proto__ === o2.__proto__"))->Run();
6038 CHECK_EQ(v8::True(), value);
6039 context->Global()->Set(v8_str("o"), obj);
6040 }
6041}
6042
6043
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00006044static int StrCmp16(uint16_t* a, uint16_t* b) {
6045 while (true) {
6046 if (*a == 0 && *b == 0) return 0;
6047 if (*a != *b) return 0 + *a - *b;
6048 a++;
6049 b++;
6050 }
6051}
6052
6053
6054static int StrNCmp16(uint16_t* a, uint16_t* b, int n) {
6055 while (true) {
6056 if (n-- == 0) return 0;
6057 if (*a == 0 && *b == 0) return 0;
6058 if (*a != *b) return 0 + *a - *b;
6059 a++;
6060 b++;
6061 }
6062}
6063
6064
yangguo@chromium.org154ff992012-03-13 08:09:54 +00006065int GetUtf8Length(Handle<String> str) {
6066 int len = str->Utf8Length();
6067 if (len < 0) {
6068 i::Handle<i::String> istr(v8::Utils::OpenHandle(*str));
6069 i::FlattenString(istr);
6070 len = str->Utf8Length();
6071 }
6072 return len;
6073}
6074
6075
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006076THREADED_TEST(StringWrite) {
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00006077 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00006078 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006079 v8::Handle<String> str = v8_str("abcde");
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00006080 // abc<Icelandic eth><Unicode snowman>.
6081 v8::Handle<String> str2 = v8_str("abc\303\260\342\230\203");
yangguo@chromium.org304cc332012-07-24 07:59:48 +00006082 v8::Handle<String> str3 = v8::String::New("abc\0def", 7);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00006083 const int kStride = 4; // Must match stride in for loops in JS below.
6084 CompileRun(
6085 "var left = '';"
6086 "for (var i = 0; i < 0xd800; i += 4) {"
6087 " left = left + String.fromCharCode(i);"
6088 "}");
6089 CompileRun(
6090 "var right = '';"
6091 "for (var i = 0; i < 0xd800; i += 4) {"
6092 " right = String.fromCharCode(i) + right;"
6093 "}");
6094 v8::Handle<v8::Object> global = Context::GetCurrent()->Global();
6095 Handle<String> left_tree = global->Get(v8_str("left")).As<String>();
6096 Handle<String> right_tree = global->Get(v8_str("right")).As<String>();
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00006097
6098 CHECK_EQ(5, str2->Length());
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00006099 CHECK_EQ(0xd800 / kStride, left_tree->Length());
6100 CHECK_EQ(0xd800 / kStride, right_tree->Length());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006101
6102 char buf[100];
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00006103 char utf8buf[0xd800 * 3];
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00006104 uint16_t wbuf[100];
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006105 int len;
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00006106 int charlen;
6107
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00006108 memset(utf8buf, 0x1, 1000);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00006109 len = str2->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00006110 CHECK_EQ(9, len);
6111 CHECK_EQ(5, charlen);
6112 CHECK_EQ(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00006113
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00006114 memset(utf8buf, 0x1, 1000);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00006115 len = str2->WriteUtf8(utf8buf, 8, &charlen);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00006116 CHECK_EQ(8, len);
6117 CHECK_EQ(5, charlen);
6118 CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\342\230\203\1", 9));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00006119
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00006120 memset(utf8buf, 0x1, 1000);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00006121 len = str2->WriteUtf8(utf8buf, 7, &charlen);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00006122 CHECK_EQ(5, len);
6123 CHECK_EQ(4, charlen);
6124 CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00006125
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00006126 memset(utf8buf, 0x1, 1000);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00006127 len = str2->WriteUtf8(utf8buf, 6, &charlen);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00006128 CHECK_EQ(5, len);
6129 CHECK_EQ(4, charlen);
6130 CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00006131
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00006132 memset(utf8buf, 0x1, 1000);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00006133 len = str2->WriteUtf8(utf8buf, 5, &charlen);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00006134 CHECK_EQ(5, len);
6135 CHECK_EQ(4, charlen);
6136 CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00006137
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00006138 memset(utf8buf, 0x1, 1000);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00006139 len = str2->WriteUtf8(utf8buf, 4, &charlen);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00006140 CHECK_EQ(3, len);
6141 CHECK_EQ(3, charlen);
6142 CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00006143
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00006144 memset(utf8buf, 0x1, 1000);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00006145 len = str2->WriteUtf8(utf8buf, 3, &charlen);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00006146 CHECK_EQ(3, len);
6147 CHECK_EQ(3, charlen);
6148 CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00006149
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00006150 memset(utf8buf, 0x1, 1000);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00006151 len = str2->WriteUtf8(utf8buf, 2, &charlen);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00006152 CHECK_EQ(2, len);
6153 CHECK_EQ(2, charlen);
6154 CHECK_EQ(0, strncmp(utf8buf, "ab\1", 3));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006155
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00006156 memset(utf8buf, 0x1, sizeof(utf8buf));
yangguo@chromium.org154ff992012-03-13 08:09:54 +00006157 len = GetUtf8Length(left_tree);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00006158 int utf8_expected =
6159 (0x80 + (0x800 - 0x80) * 2 + (0xd800 - 0x800) * 3) / kStride;
6160 CHECK_EQ(utf8_expected, len);
6161 len = left_tree->WriteUtf8(utf8buf, utf8_expected, &charlen);
6162 CHECK_EQ(utf8_expected, len);
6163 CHECK_EQ(0xd800 / kStride, charlen);
6164 CHECK_EQ(0xed, static_cast<unsigned char>(utf8buf[utf8_expected - 3]));
6165 CHECK_EQ(0x9f, static_cast<unsigned char>(utf8buf[utf8_expected - 2]));
6166 CHECK_EQ(0xc0 - kStride,
6167 static_cast<unsigned char>(utf8buf[utf8_expected - 1]));
6168 CHECK_EQ(1, utf8buf[utf8_expected]);
6169
6170 memset(utf8buf, 0x1, sizeof(utf8buf));
yangguo@chromium.org154ff992012-03-13 08:09:54 +00006171 len = GetUtf8Length(right_tree);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00006172 CHECK_EQ(utf8_expected, len);
6173 len = right_tree->WriteUtf8(utf8buf, utf8_expected, &charlen);
6174 CHECK_EQ(utf8_expected, len);
6175 CHECK_EQ(0xd800 / kStride, charlen);
6176 CHECK_EQ(0xed, static_cast<unsigned char>(utf8buf[0]));
6177 CHECK_EQ(0x9f, static_cast<unsigned char>(utf8buf[1]));
6178 CHECK_EQ(0xc0 - kStride, static_cast<unsigned char>(utf8buf[2]));
6179 CHECK_EQ(1, utf8buf[utf8_expected]);
6180
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006181 memset(buf, 0x1, sizeof(buf));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00006182 memset(wbuf, 0x1, sizeof(wbuf));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006183 len = str->WriteAscii(buf);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00006184 CHECK_EQ(5, len);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00006185 len = str->Write(wbuf);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00006186 CHECK_EQ(5, len);
6187 CHECK_EQ(0, strcmp("abcde", buf));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00006188 uint16_t answer1[] = {'a', 'b', 'c', 'd', 'e', '\0'};
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00006189 CHECK_EQ(0, StrCmp16(answer1, wbuf));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006190
6191 memset(buf, 0x1, sizeof(buf));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00006192 memset(wbuf, 0x1, sizeof(wbuf));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006193 len = str->WriteAscii(buf, 0, 4);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00006194 CHECK_EQ(4, len);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00006195 len = str->Write(wbuf, 0, 4);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00006196 CHECK_EQ(4, len);
6197 CHECK_EQ(0, strncmp("abcd\1", buf, 5));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00006198 uint16_t answer2[] = {'a', 'b', 'c', 'd', 0x101};
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00006199 CHECK_EQ(0, StrNCmp16(answer2, wbuf, 5));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006200
6201 memset(buf, 0x1, sizeof(buf));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00006202 memset(wbuf, 0x1, sizeof(wbuf));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006203 len = str->WriteAscii(buf, 0, 5);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00006204 CHECK_EQ(5, len);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00006205 len = str->Write(wbuf, 0, 5);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00006206 CHECK_EQ(5, len);
6207 CHECK_EQ(0, strncmp("abcde\1", buf, 6));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00006208 uint16_t answer3[] = {'a', 'b', 'c', 'd', 'e', 0x101};
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00006209 CHECK_EQ(0, StrNCmp16(answer3, wbuf, 6));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006210
6211 memset(buf, 0x1, sizeof(buf));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00006212 memset(wbuf, 0x1, sizeof(wbuf));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006213 len = str->WriteAscii(buf, 0, 6);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00006214 CHECK_EQ(5, len);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00006215 len = str->Write(wbuf, 0, 6);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00006216 CHECK_EQ(5, len);
6217 CHECK_EQ(0, strcmp("abcde", buf));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00006218 uint16_t answer4[] = {'a', 'b', 'c', 'd', 'e', '\0'};
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00006219 CHECK_EQ(0, StrCmp16(answer4, wbuf));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006220
6221 memset(buf, 0x1, sizeof(buf));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00006222 memset(wbuf, 0x1, sizeof(wbuf));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006223 len = str->WriteAscii(buf, 4, -1);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00006224 CHECK_EQ(1, len);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00006225 len = str->Write(wbuf, 4, -1);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00006226 CHECK_EQ(1, len);
6227 CHECK_EQ(0, strcmp("e", buf));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00006228 uint16_t answer5[] = {'e', '\0'};
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00006229 CHECK_EQ(0, StrCmp16(answer5, wbuf));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006230
6231 memset(buf, 0x1, sizeof(buf));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00006232 memset(wbuf, 0x1, sizeof(wbuf));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006233 len = str->WriteAscii(buf, 4, 6);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00006234 CHECK_EQ(1, len);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00006235 len = str->Write(wbuf, 4, 6);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00006236 CHECK_EQ(1, len);
6237 CHECK_EQ(0, strcmp("e", buf));
6238 CHECK_EQ(0, StrCmp16(answer5, wbuf));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006239
6240 memset(buf, 0x1, sizeof(buf));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00006241 memset(wbuf, 0x1, sizeof(wbuf));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006242 len = str->WriteAscii(buf, 4, 1);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00006243 CHECK_EQ(1, len);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00006244 len = str->Write(wbuf, 4, 1);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00006245 CHECK_EQ(1, len);
6246 CHECK_EQ(0, strncmp("e\1", buf, 2));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00006247 uint16_t answer6[] = {'e', 0x101};
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00006248 CHECK_EQ(0, StrNCmp16(answer6, wbuf, 2));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00006249
6250 memset(buf, 0x1, sizeof(buf));
6251 memset(wbuf, 0x1, sizeof(wbuf));
6252 len = str->WriteAscii(buf, 3, 1);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00006253 CHECK_EQ(1, len);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00006254 len = str->Write(wbuf, 3, 1);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00006255 CHECK_EQ(1, len);
6256 CHECK_EQ(0, strncmp("d\1", buf, 2));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00006257 uint16_t answer7[] = {'d', 0x101};
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00006258 CHECK_EQ(0, StrNCmp16(answer7, wbuf, 2));
ricow@chromium.orgddd545c2011-08-24 12:02:41 +00006259
6260 memset(wbuf, 0x1, sizeof(wbuf));
6261 wbuf[5] = 'X';
6262 len = str->Write(wbuf, 0, 6, String::NO_NULL_TERMINATION);
6263 CHECK_EQ(5, len);
6264 CHECK_EQ('X', wbuf[5]);
6265 uint16_t answer8a[] = {'a', 'b', 'c', 'd', 'e'};
6266 uint16_t answer8b[] = {'a', 'b', 'c', 'd', 'e', '\0'};
6267 CHECK_EQ(0, StrNCmp16(answer8a, wbuf, 5));
6268 CHECK_NE(0, StrCmp16(answer8b, wbuf));
6269 wbuf[5] = '\0';
6270 CHECK_EQ(0, StrCmp16(answer8b, wbuf));
6271
6272 memset(buf, 0x1, sizeof(buf));
6273 buf[5] = 'X';
6274 len = str->WriteAscii(buf, 0, 6, String::NO_NULL_TERMINATION);
6275 CHECK_EQ(5, len);
6276 CHECK_EQ('X', buf[5]);
6277 CHECK_EQ(0, strncmp("abcde", buf, 5));
6278 CHECK_NE(0, strcmp("abcde", buf));
6279 buf[5] = '\0';
6280 CHECK_EQ(0, strcmp("abcde", buf));
6281
6282 memset(utf8buf, 0x1, sizeof(utf8buf));
6283 utf8buf[8] = 'X';
6284 len = str2->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen,
6285 String::NO_NULL_TERMINATION);
6286 CHECK_EQ(8, len);
6287 CHECK_EQ('X', utf8buf[8]);
6288 CHECK_EQ(5, charlen);
6289 CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\342\230\203", 8));
6290 CHECK_NE(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
6291 utf8buf[8] = '\0';
6292 CHECK_EQ(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
yangguo@chromium.org304cc332012-07-24 07:59:48 +00006293
6294 memset(utf8buf, 0x1, sizeof(utf8buf));
6295 utf8buf[5] = 'X';
6296 len = str->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen,
6297 String::NO_NULL_TERMINATION);
6298 CHECK_EQ(5, len);
6299 CHECK_EQ('X', utf8buf[5]); // Test that the sixth character is untouched.
6300 CHECK_EQ(5, charlen);
6301 utf8buf[5] = '\0';
6302 CHECK_EQ(0, strcmp(utf8buf, "abcde"));
6303
6304 memset(buf, 0x1, sizeof(buf));
6305 len = str3->WriteAscii(buf);
6306 CHECK_EQ(7, len);
6307 CHECK_EQ(0, strcmp("abc def", buf));
6308
6309 memset(buf, 0x1, sizeof(buf));
6310 len = str3->WriteAscii(buf, 0, -1, String::PRESERVE_ASCII_NULL);
6311 CHECK_EQ(7, len);
6312 CHECK_EQ(0, strcmp("abc", buf));
6313 CHECK_EQ(0, buf[3]);
6314 CHECK_EQ(0, strcmp("def", buf + 4));
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00006315
6316 CHECK_EQ(0, str->WriteAscii(NULL, 0, 0, String::NO_NULL_TERMINATION));
6317 CHECK_EQ(0, str->WriteUtf8(NULL, 0, 0, String::NO_NULL_TERMINATION));
6318 CHECK_EQ(0, str->Write(NULL, 0, 0, String::NO_NULL_TERMINATION));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006319}
6320
6321
yangguo@chromium.org154ff992012-03-13 08:09:54 +00006322static void Utf16Helper(
6323 LocalContext& context,
6324 const char* name,
6325 const char* lengths_name,
6326 int len) {
6327 Local<v8::Array> a =
6328 Local<v8::Array>::Cast(context->Global()->Get(v8_str(name)));
6329 Local<v8::Array> alens =
6330 Local<v8::Array>::Cast(context->Global()->Get(v8_str(lengths_name)));
6331 for (int i = 0; i < len; i++) {
6332 Local<v8::String> string =
6333 Local<v8::String>::Cast(a->Get(i));
6334 Local<v8::Number> expected_len =
6335 Local<v8::Number>::Cast(alens->Get(i));
6336 int length = GetUtf8Length(string);
6337 CHECK_EQ(static_cast<int>(expected_len->Value()), length);
6338 }
6339}
6340
6341
6342static uint16_t StringGet(Handle<String> str, int index) {
6343 i::Handle<i::String> istring =
6344 v8::Utils::OpenHandle(String::Cast(*str));
6345 return istring->Get(index);
6346}
6347
6348
6349static void WriteUtf8Helper(
6350 LocalContext& context,
6351 const char* name,
6352 const char* lengths_name,
6353 int len) {
6354 Local<v8::Array> b =
6355 Local<v8::Array>::Cast(context->Global()->Get(v8_str(name)));
6356 Local<v8::Array> alens =
6357 Local<v8::Array>::Cast(context->Global()->Get(v8_str(lengths_name)));
6358 char buffer[1000];
6359 char buffer2[1000];
6360 for (int i = 0; i < len; i++) {
6361 Local<v8::String> string =
6362 Local<v8::String>::Cast(b->Get(i));
6363 Local<v8::Number> expected_len =
6364 Local<v8::Number>::Cast(alens->Get(i));
6365 int utf8_length = static_cast<int>(expected_len->Value());
6366 for (int j = utf8_length + 1; j >= 0; j--) {
6367 memset(reinterpret_cast<void*>(&buffer), 42, sizeof(buffer));
6368 memset(reinterpret_cast<void*>(&buffer2), 42, sizeof(buffer2));
6369 int nchars;
6370 int utf8_written =
6371 string->WriteUtf8(buffer, j, &nchars, String::NO_OPTIONS);
6372 int utf8_written2 =
6373 string->WriteUtf8(buffer2, j, &nchars, String::NO_NULL_TERMINATION);
6374 CHECK_GE(utf8_length + 1, utf8_written);
6375 CHECK_GE(utf8_length, utf8_written2);
6376 for (int k = 0; k < utf8_written2; k++) {
6377 CHECK_EQ(buffer[k], buffer2[k]);
6378 }
6379 CHECK(nchars * 3 >= utf8_written - 1);
6380 CHECK(nchars <= utf8_written);
6381 if (j == utf8_length + 1) {
6382 CHECK_EQ(utf8_written2, utf8_length);
6383 CHECK_EQ(utf8_written2 + 1, utf8_written);
6384 }
6385 CHECK_EQ(buffer[utf8_written], 42);
6386 if (j > utf8_length) {
6387 if (utf8_written != 0) CHECK_EQ(buffer[utf8_written - 1], 0);
6388 if (utf8_written > 1) CHECK_NE(buffer[utf8_written - 2], 42);
6389 Handle<String> roundtrip = v8_str(buffer);
6390 CHECK(roundtrip->Equals(string));
6391 } else {
6392 if (utf8_written != 0) CHECK_NE(buffer[utf8_written - 1], 42);
6393 }
6394 if (utf8_written2 != 0) CHECK_NE(buffer[utf8_written - 1], 42);
6395 if (nchars >= 2) {
6396 uint16_t trail = StringGet(string, nchars - 1);
6397 uint16_t lead = StringGet(string, nchars - 2);
6398 if (((lead & 0xfc00) == 0xd800) &&
6399 ((trail & 0xfc00) == 0xdc00)) {
6400 unsigned char u1 = buffer2[utf8_written2 - 4];
6401 unsigned char u2 = buffer2[utf8_written2 - 3];
6402 unsigned char u3 = buffer2[utf8_written2 - 2];
6403 unsigned char u4 = buffer2[utf8_written2 - 1];
6404 CHECK_EQ((u1 & 0xf8), 0xf0);
6405 CHECK_EQ((u2 & 0xc0), 0x80);
6406 CHECK_EQ((u3 & 0xc0), 0x80);
6407 CHECK_EQ((u4 & 0xc0), 0x80);
6408 uint32_t c = 0x10000 + ((lead & 0x3ff) << 10) + (trail & 0x3ff);
6409 CHECK_EQ((u4 & 0x3f), (c & 0x3f));
6410 CHECK_EQ((u3 & 0x3f), ((c >> 6) & 0x3f));
6411 CHECK_EQ((u2 & 0x3f), ((c >> 12) & 0x3f));
6412 CHECK_EQ((u1 & 0x3), c >> 18);
6413 }
6414 }
6415 }
6416 }
6417}
6418
6419
6420THREADED_TEST(Utf16) {
6421 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00006422 v8::HandleScope scope(context->GetIsolate());
yangguo@chromium.org154ff992012-03-13 08:09:54 +00006423 CompileRun(
6424 "var pad = '01234567890123456789';"
6425 "var p = [];"
6426 "var plens = [20, 3, 3];"
6427 "p.push('01234567890123456789');"
6428 "var lead = 0xd800;"
6429 "var trail = 0xdc00;"
6430 "p.push(String.fromCharCode(0xd800));"
6431 "p.push(String.fromCharCode(0xdc00));"
6432 "var a = [];"
6433 "var b = [];"
danno@chromium.org88aa0582012-03-23 15:11:57 +00006434 "var c = [];"
yangguo@chromium.org154ff992012-03-13 08:09:54 +00006435 "var alens = [];"
6436 "for (var i = 0; i < 3; i++) {"
6437 " p[1] = String.fromCharCode(lead++);"
6438 " for (var j = 0; j < 3; j++) {"
6439 " p[2] = String.fromCharCode(trail++);"
6440 " a.push(p[i] + p[j]);"
6441 " b.push(p[i] + p[j]);"
danno@chromium.org88aa0582012-03-23 15:11:57 +00006442 " c.push(p[i] + p[j]);"
yangguo@chromium.org154ff992012-03-13 08:09:54 +00006443 " alens.push(plens[i] + plens[j]);"
6444 " }"
6445 "}"
6446 "alens[5] -= 2;" // Here the surrogate pairs match up.
6447 "var a2 = [];"
6448 "var b2 = [];"
danno@chromium.org88aa0582012-03-23 15:11:57 +00006449 "var c2 = [];"
yangguo@chromium.org154ff992012-03-13 08:09:54 +00006450 "var a2lens = [];"
6451 "for (var m = 0; m < 9; m++) {"
6452 " for (var n = 0; n < 9; n++) {"
6453 " a2.push(a[m] + a[n]);"
6454 " b2.push(b[m] + b[n]);"
danno@chromium.org88aa0582012-03-23 15:11:57 +00006455 " var newc = 'x' + c[m] + c[n] + 'y';"
6456 " c2.push(newc.substring(1, newc.length - 1));"
yangguo@chromium.org154ff992012-03-13 08:09:54 +00006457 " var utf = alens[m] + alens[n];" // And here.
6458 // The 'n's that start with 0xdc.. are 6-8
6459 // The 'm's that end with 0xd8.. are 1, 4 and 7
6460 " if ((m % 3) == 1 && n >= 6) utf -= 2;"
6461 " a2lens.push(utf);"
6462 " }"
6463 "}");
6464 Utf16Helper(context, "a", "alens", 9);
6465 Utf16Helper(context, "a2", "a2lens", 81);
6466 WriteUtf8Helper(context, "b", "alens", 9);
6467 WriteUtf8Helper(context, "b2", "a2lens", 81);
danno@chromium.org88aa0582012-03-23 15:11:57 +00006468 WriteUtf8Helper(context, "c2", "a2lens", 81);
yangguo@chromium.org154ff992012-03-13 08:09:54 +00006469}
6470
6471
6472static bool SameSymbol(Handle<String> s1, Handle<String> s2) {
6473 i::Handle<i::String> is1(v8::Utils::OpenHandle(*s1));
6474 i::Handle<i::String> is2(v8::Utils::OpenHandle(*s2));
6475 return *is1 == *is2;
6476}
6477
6478
6479static void SameSymbolHelper(const char* a, const char* b) {
6480 Handle<String> symbol1 = v8::String::NewSymbol(a);
6481 Handle<String> symbol2 = v8::String::NewSymbol(b);
6482 CHECK(SameSymbol(symbol1, symbol2));
6483}
6484
6485
6486THREADED_TEST(Utf16Symbol) {
6487 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00006488 v8::HandleScope scope(context->GetIsolate());
yangguo@chromium.org154ff992012-03-13 08:09:54 +00006489
6490 Handle<String> symbol1 = v8::String::NewSymbol("abc");
6491 Handle<String> symbol2 = v8::String::NewSymbol("abc");
6492 CHECK(SameSymbol(symbol1, symbol2));
6493
6494 SameSymbolHelper("\360\220\220\205", // 4 byte encoding.
6495 "\355\240\201\355\260\205"); // 2 3-byte surrogates.
6496 SameSymbolHelper("\355\240\201\355\260\206", // 2 3-byte surrogates.
6497 "\360\220\220\206"); // 4 byte encoding.
6498 SameSymbolHelper("x\360\220\220\205", // 4 byte encoding.
6499 "x\355\240\201\355\260\205"); // 2 3-byte surrogates.
6500 SameSymbolHelper("x\355\240\201\355\260\206", // 2 3-byte surrogates.
6501 "x\360\220\220\206"); // 4 byte encoding.
6502 CompileRun(
6503 "var sym0 = 'benedictus';"
6504 "var sym0b = 'S\303\270ren';"
6505 "var sym1 = '\355\240\201\355\260\207';"
6506 "var sym2 = '\360\220\220\210';"
6507 "var sym3 = 'x\355\240\201\355\260\207';"
6508 "var sym4 = 'x\360\220\220\210';"
6509 "if (sym1.length != 2) throw sym1;"
6510 "if (sym1.charCodeAt(1) != 0xdc07) throw sym1.charCodeAt(1);"
6511 "if (sym2.length != 2) throw sym2;"
6512 "if (sym2.charCodeAt(1) != 0xdc08) throw sym2.charCodeAt(2);"
6513 "if (sym3.length != 3) throw sym3;"
6514 "if (sym3.charCodeAt(2) != 0xdc07) throw sym1.charCodeAt(2);"
6515 "if (sym4.length != 3) throw sym4;"
6516 "if (sym4.charCodeAt(2) != 0xdc08) throw sym2.charCodeAt(2);");
6517 Handle<String> sym0 = v8::String::NewSymbol("benedictus");
6518 Handle<String> sym0b = v8::String::NewSymbol("S\303\270ren");
6519 Handle<String> sym1 = v8::String::NewSymbol("\355\240\201\355\260\207");
6520 Handle<String> sym2 = v8::String::NewSymbol("\360\220\220\210");
6521 Handle<String> sym3 = v8::String::NewSymbol("x\355\240\201\355\260\207");
6522 Handle<String> sym4 = v8::String::NewSymbol("x\360\220\220\210");
6523 v8::Local<v8::Object> global = context->Global();
6524 Local<Value> s0 = global->Get(v8_str("sym0"));
6525 Local<Value> s0b = global->Get(v8_str("sym0b"));
6526 Local<Value> s1 = global->Get(v8_str("sym1"));
6527 Local<Value> s2 = global->Get(v8_str("sym2"));
6528 Local<Value> s3 = global->Get(v8_str("sym3"));
6529 Local<Value> s4 = global->Get(v8_str("sym4"));
6530 CHECK(SameSymbol(sym0, Handle<String>(String::Cast(*s0))));
6531 CHECK(SameSymbol(sym0b, Handle<String>(String::Cast(*s0b))));
6532 CHECK(SameSymbol(sym1, Handle<String>(String::Cast(*s1))));
6533 CHECK(SameSymbol(sym2, Handle<String>(String::Cast(*s2))));
6534 CHECK(SameSymbol(sym3, Handle<String>(String::Cast(*s3))));
6535 CHECK(SameSymbol(sym4, Handle<String>(String::Cast(*s4))));
6536}
6537
6538
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006539THREADED_TEST(ToArrayIndex) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006540 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00006541 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006542
6543 v8::Handle<String> str = v8_str("42");
6544 v8::Handle<v8::Uint32> index = str->ToArrayIndex();
6545 CHECK(!index.IsEmpty());
6546 CHECK_EQ(42.0, index->Uint32Value());
6547 str = v8_str("42asdf");
6548 index = str->ToArrayIndex();
6549 CHECK(index.IsEmpty());
6550 str = v8_str("-42");
6551 index = str->ToArrayIndex();
6552 CHECK(index.IsEmpty());
6553 str = v8_str("4294967295");
6554 index = str->ToArrayIndex();
6555 CHECK(!index.IsEmpty());
6556 CHECK_EQ(4294967295.0, index->Uint32Value());
6557 v8::Handle<v8::Number> num = v8::Number::New(1);
6558 index = num->ToArrayIndex();
6559 CHECK(!index.IsEmpty());
6560 CHECK_EQ(1.0, index->Uint32Value());
6561 num = v8::Number::New(-1);
6562 index = num->ToArrayIndex();
6563 CHECK(index.IsEmpty());
6564 v8::Handle<v8::Object> obj = v8::Object::New();
6565 index = obj->ToArrayIndex();
6566 CHECK(index.IsEmpty());
6567}
6568
6569
6570THREADED_TEST(ErrorConstruction) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006571 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00006572 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006573
6574 v8::Handle<String> foo = v8_str("foo");
6575 v8::Handle<String> message = v8_str("message");
6576 v8::Handle<Value> range_error = v8::Exception::RangeError(foo);
6577 CHECK(range_error->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00006578 CHECK(range_error.As<v8::Object>()->Get(message)->Equals(foo));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006579 v8::Handle<Value> reference_error = v8::Exception::ReferenceError(foo);
6580 CHECK(reference_error->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00006581 CHECK(reference_error.As<v8::Object>()->Get(message)->Equals(foo));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006582 v8::Handle<Value> syntax_error = v8::Exception::SyntaxError(foo);
6583 CHECK(syntax_error->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00006584 CHECK(syntax_error.As<v8::Object>()->Get(message)->Equals(foo));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006585 v8::Handle<Value> type_error = v8::Exception::TypeError(foo);
6586 CHECK(type_error->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00006587 CHECK(type_error.As<v8::Object>()->Get(message)->Equals(foo));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006588 v8::Handle<Value> error = v8::Exception::Error(foo);
6589 CHECK(error->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00006590 CHECK(error.As<v8::Object>()->Get(message)->Equals(foo));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006591}
6592
6593
6594static v8::Handle<Value> YGetter(Local<String> name, const AccessorInfo& info) {
6595 ApiTestFuzzer::Fuzz();
6596 return v8_num(10);
6597}
6598
6599
6600static void YSetter(Local<String> name,
6601 Local<Value> value,
6602 const AccessorInfo& info) {
6603 if (info.This()->Has(name)) {
6604 info.This()->Delete(name);
6605 }
6606 info.This()->Set(name, value);
6607}
6608
6609
6610THREADED_TEST(DeleteAccessor) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00006611 v8::HandleScope scope(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006612 v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
6613 obj->SetAccessor(v8_str("y"), YGetter, YSetter);
6614 LocalContext context;
6615 v8::Handle<v8::Object> holder = obj->NewInstance();
6616 context->Global()->Set(v8_str("holder"), holder);
6617 v8::Handle<Value> result = CompileRun(
6618 "holder.y = 11; holder.y = 12; holder.y");
6619 CHECK_EQ(12, result->Uint32Value());
6620}
6621
6622
6623THREADED_TEST(TypeSwitch) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00006624 v8::HandleScope scope(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006625 v8::Handle<v8::FunctionTemplate> templ1 = v8::FunctionTemplate::New();
6626 v8::Handle<v8::FunctionTemplate> templ2 = v8::FunctionTemplate::New();
6627 v8::Handle<v8::FunctionTemplate> templ3 = v8::FunctionTemplate::New();
6628 v8::Handle<v8::FunctionTemplate> templs[3] = { templ1, templ2, templ3 };
6629 v8::Handle<v8::TypeSwitch> type_switch = v8::TypeSwitch::New(3, templs);
6630 LocalContext context;
6631 v8::Handle<v8::Object> obj0 = v8::Object::New();
6632 v8::Handle<v8::Object> obj1 = templ1->GetFunction()->NewInstance();
6633 v8::Handle<v8::Object> obj2 = templ2->GetFunction()->NewInstance();
6634 v8::Handle<v8::Object> obj3 = templ3->GetFunction()->NewInstance();
6635 for (int i = 0; i < 10; i++) {
6636 CHECK_EQ(0, type_switch->match(obj0));
6637 CHECK_EQ(1, type_switch->match(obj1));
6638 CHECK_EQ(2, type_switch->match(obj2));
6639 CHECK_EQ(3, type_switch->match(obj3));
6640 CHECK_EQ(3, type_switch->match(obj3));
6641 CHECK_EQ(2, type_switch->match(obj2));
6642 CHECK_EQ(1, type_switch->match(obj1));
6643 CHECK_EQ(0, type_switch->match(obj0));
6644 }
6645}
6646
6647
6648// For use within the TestSecurityHandler() test.
6649static bool g_security_callback_result = false;
6650static bool NamedSecurityTestCallback(Local<v8::Object> global,
6651 Local<Value> name,
6652 v8::AccessType type,
6653 Local<Value> data) {
6654 // Always allow read access.
6655 if (type == v8::ACCESS_GET)
6656 return true;
6657
6658 // Sometimes allow other access.
6659 return g_security_callback_result;
6660}
6661
6662
6663static bool IndexedSecurityTestCallback(Local<v8::Object> global,
6664 uint32_t key,
6665 v8::AccessType type,
6666 Local<Value> data) {
6667 // Always allow read access.
6668 if (type == v8::ACCESS_GET)
6669 return true;
6670
6671 // Sometimes allow other access.
6672 return g_security_callback_result;
6673}
6674
6675
6676static int trouble_nesting = 0;
6677static v8::Handle<Value> TroubleCallback(const v8::Arguments& args) {
6678 ApiTestFuzzer::Fuzz();
6679 trouble_nesting++;
6680
6681 // Call a JS function that throws an uncaught exception.
6682 Local<v8::Object> arg_this = Context::GetCurrent()->Global();
6683 Local<Value> trouble_callee = (trouble_nesting == 3) ?
6684 arg_this->Get(v8_str("trouble_callee")) :
6685 arg_this->Get(v8_str("trouble_caller"));
6686 CHECK(trouble_callee->IsFunction());
6687 return Function::Cast(*trouble_callee)->Call(arg_this, 0, NULL);
6688}
6689
6690
6691static int report_count = 0;
6692static void ApiUncaughtExceptionTestListener(v8::Handle<v8::Message>,
6693 v8::Handle<Value>) {
6694 report_count++;
6695}
6696
6697
6698// Counts uncaught exceptions, but other tests running in parallel
6699// also have uncaught exceptions.
6700TEST(ApiUncaughtException) {
ager@chromium.org8bb60582008-12-11 12:02:20 +00006701 report_count = 0;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006702 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00006703 v8::HandleScope scope(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006704 v8::V8::AddMessageListener(ApiUncaughtExceptionTestListener);
6705
6706 Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(TroubleCallback);
6707 v8::Local<v8::Object> global = env->Global();
6708 global->Set(v8_str("trouble"), fun->GetFunction());
6709
6710 Script::Compile(v8_str("function trouble_callee() {"
6711 " var x = null;"
6712 " return x.foo;"
6713 "};"
6714 "function trouble_caller() {"
6715 " trouble();"
6716 "};"))->Run();
6717 Local<Value> trouble = global->Get(v8_str("trouble"));
6718 CHECK(trouble->IsFunction());
6719 Local<Value> trouble_callee = global->Get(v8_str("trouble_callee"));
6720 CHECK(trouble_callee->IsFunction());
6721 Local<Value> trouble_caller = global->Get(v8_str("trouble_caller"));
6722 CHECK(trouble_caller->IsFunction());
6723 Function::Cast(*trouble_caller)->Call(global, 0, NULL);
6724 CHECK_EQ(1, report_count);
ager@chromium.org8bb60582008-12-11 12:02:20 +00006725 v8::V8::RemoveMessageListeners(ApiUncaughtExceptionTestListener);
6726}
6727
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00006728static const char* script_resource_name = "ExceptionInNativeScript.js";
6729static void ExceptionInNativeScriptTestListener(v8::Handle<v8::Message> message,
6730 v8::Handle<Value>) {
6731 v8::Handle<v8::Value> name_val = message->GetScriptResourceName();
6732 CHECK(!name_val.IsEmpty() && name_val->IsString());
6733 v8::String::AsciiValue name(message->GetScriptResourceName());
6734 CHECK_EQ(script_resource_name, *name);
6735 CHECK_EQ(3, message->GetLineNumber());
6736 v8::String::AsciiValue source_line(message->GetSourceLine());
6737 CHECK_EQ(" new o.foo();", *source_line);
6738}
6739
6740TEST(ExceptionInNativeScript) {
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00006741 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00006742 v8::HandleScope scope(env->GetIsolate());
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00006743 v8::V8::AddMessageListener(ExceptionInNativeScriptTestListener);
6744
6745 Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(TroubleCallback);
6746 v8::Local<v8::Object> global = env->Global();
6747 global->Set(v8_str("trouble"), fun->GetFunction());
6748
6749 Script::Compile(v8_str("function trouble() {\n"
6750 " var o = {};\n"
6751 " new o.foo();\n"
6752 "};"), v8::String::New(script_resource_name))->Run();
6753 Local<Value> trouble = global->Get(v8_str("trouble"));
6754 CHECK(trouble->IsFunction());
6755 Function::Cast(*trouble)->Call(global, 0, NULL);
6756 v8::V8::RemoveMessageListeners(ExceptionInNativeScriptTestListener);
6757}
6758
ager@chromium.org8bb60582008-12-11 12:02:20 +00006759
6760TEST(CompilationErrorUsingTryCatchHandler) {
ager@chromium.org8bb60582008-12-11 12:02:20 +00006761 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00006762 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org8bb60582008-12-11 12:02:20 +00006763 v8::TryCatch try_catch;
6764 Script::Compile(v8_str("This doesn't &*&@#$&*^ compile."));
6765 CHECK_NE(NULL, *try_catch.Exception());
6766 CHECK(try_catch.HasCaught());
6767}
6768
6769
6770TEST(TryCatchFinallyUsingTryCatchHandler) {
ager@chromium.org8bb60582008-12-11 12:02:20 +00006771 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00006772 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org8bb60582008-12-11 12:02:20 +00006773 v8::TryCatch try_catch;
6774 Script::Compile(v8_str("try { throw ''; } catch (e) {}"))->Run();
6775 CHECK(!try_catch.HasCaught());
6776 Script::Compile(v8_str("try { throw ''; } finally {}"))->Run();
6777 CHECK(try_catch.HasCaught());
6778 try_catch.Reset();
6779 Script::Compile(v8_str("(function() {"
6780 "try { throw ''; } finally { return; }"
6781 "})()"))->Run();
6782 CHECK(!try_catch.HasCaught());
6783 Script::Compile(v8_str("(function()"
6784 " { try { throw ''; } finally { throw 0; }"
6785 "})()"))->Run();
6786 CHECK(try_catch.HasCaught());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006787}
6788
6789
6790// SecurityHandler can't be run twice
6791TEST(SecurityHandler) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00006792 v8::HandleScope scope0(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006793 v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
6794 global_template->SetAccessCheckCallbacks(NamedSecurityTestCallback,
6795 IndexedSecurityTestCallback);
6796 // Create an environment
6797 v8::Persistent<Context> context0 =
6798 Context::New(NULL, global_template);
6799 context0->Enter();
6800
6801 v8::Handle<v8::Object> global0 = context0->Global();
6802 v8::Handle<Script> script0 = v8_compile("foo = 111");
6803 script0->Run();
6804 global0->Set(v8_str("0"), v8_num(999));
6805 v8::Handle<Value> foo0 = global0->Get(v8_str("foo"));
6806 CHECK_EQ(111, foo0->Int32Value());
6807 v8::Handle<Value> z0 = global0->Get(v8_str("0"));
6808 CHECK_EQ(999, z0->Int32Value());
6809
6810 // Create another environment, should fail security checks.
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00006811 v8::HandleScope scope1(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006812
6813 v8::Persistent<Context> context1 =
6814 Context::New(NULL, global_template);
6815 context1->Enter();
6816
6817 v8::Handle<v8::Object> global1 = context1->Global();
6818 global1->Set(v8_str("othercontext"), global0);
6819 // This set will fail the security check.
6820 v8::Handle<Script> script1 =
6821 v8_compile("othercontext.foo = 222; othercontext[0] = 888;");
6822 script1->Run();
6823 // This read will pass the security check.
6824 v8::Handle<Value> foo1 = global0->Get(v8_str("foo"));
6825 CHECK_EQ(111, foo1->Int32Value());
6826 // This read will pass the security check.
6827 v8::Handle<Value> z1 = global0->Get(v8_str("0"));
6828 CHECK_EQ(999, z1->Int32Value());
6829
6830 // Create another environment, should pass security checks.
6831 { g_security_callback_result = true; // allow security handler to pass.
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00006832 v8::HandleScope scope2(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006833 LocalContext context2;
6834 v8::Handle<v8::Object> global2 = context2->Global();
6835 global2->Set(v8_str("othercontext"), global0);
6836 v8::Handle<Script> script2 =
6837 v8_compile("othercontext.foo = 333; othercontext[0] = 888;");
6838 script2->Run();
6839 v8::Handle<Value> foo2 = global0->Get(v8_str("foo"));
6840 CHECK_EQ(333, foo2->Int32Value());
6841 v8::Handle<Value> z2 = global0->Get(v8_str("0"));
6842 CHECK_EQ(888, z2->Int32Value());
6843 }
6844
6845 context1->Exit();
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00006846 context1.Dispose(context1->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006847
6848 context0->Exit();
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00006849 context0.Dispose(context0->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006850}
6851
6852
6853THREADED_TEST(SecurityChecks) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006854 LocalContext env1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00006855 v8::HandleScope handle_scope(env1->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006856 v8::Persistent<Context> env2 = Context::New();
6857
6858 Local<Value> foo = v8_str("foo");
6859 Local<Value> bar = v8_str("bar");
6860
6861 // Set to the same domain.
6862 env1->SetSecurityToken(foo);
6863
6864 // Create a function in env1.
6865 Script::Compile(v8_str("spy=function(){return spy;}"))->Run();
6866 Local<Value> spy = env1->Global()->Get(v8_str("spy"));
6867 CHECK(spy->IsFunction());
6868
6869 // Create another function accessing global objects.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00006870 Script::Compile(v8_str("spy2=function(){return new this.Array();}"))->Run();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006871 Local<Value> spy2 = env1->Global()->Get(v8_str("spy2"));
6872 CHECK(spy2->IsFunction());
6873
6874 // Switch to env2 in the same domain and invoke spy on env2.
6875 {
6876 env2->SetSecurityToken(foo);
6877 // Enter env2
6878 Context::Scope scope_env2(env2);
6879 Local<Value> result = Function::Cast(*spy)->Call(env2->Global(), 0, NULL);
6880 CHECK(result->IsFunction());
6881 }
6882
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006883 {
6884 env2->SetSecurityToken(bar);
6885 Context::Scope scope_env2(env2);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006886
6887 // Call cross_domain_call, it should throw an exception
6888 v8::TryCatch try_catch;
6889 Function::Cast(*spy2)->Call(env2->Global(), 0, NULL);
6890 CHECK(try_catch.HasCaught());
6891 }
6892
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00006893 env2.Dispose(env2->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006894}
6895
6896
6897// Regression test case for issue 1183439.
6898THREADED_TEST(SecurityChecksForPrototypeChain) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006899 LocalContext current;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00006900 v8::HandleScope scope(current->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006901 v8::Persistent<Context> other = Context::New();
6902
6903 // Change context to be able to get to the Object function in the
6904 // other context without hitting the security checks.
6905 v8::Local<Value> other_object;
6906 { Context::Scope scope(other);
6907 other_object = other->Global()->Get(v8_str("Object"));
6908 other->Global()->Set(v8_num(42), v8_num(87));
6909 }
6910
6911 current->Global()->Set(v8_str("other"), other->Global());
6912 CHECK(v8_compile("other")->Run()->Equals(other->Global()));
6913
6914 // Make sure the security check fails here and we get an undefined
6915 // result instead of getting the Object function. Repeat in a loop
6916 // to make sure to exercise the IC code.
6917 v8::Local<Script> access_other0 = v8_compile("other.Object");
6918 v8::Local<Script> access_other1 = v8_compile("other[42]");
6919 for (int i = 0; i < 5; i++) {
6920 CHECK(!access_other0->Run()->Equals(other_object));
6921 CHECK(access_other0->Run()->IsUndefined());
6922 CHECK(!access_other1->Run()->Equals(v8_num(87)));
6923 CHECK(access_other1->Run()->IsUndefined());
6924 }
6925
6926 // Create an object that has 'other' in its prototype chain and make
6927 // sure we cannot access the Object function indirectly through
6928 // that. Repeat in a loop to make sure to exercise the IC code.
6929 v8_compile("function F() { };"
6930 "F.prototype = other;"
6931 "var f = new F();")->Run();
6932 v8::Local<Script> access_f0 = v8_compile("f.Object");
6933 v8::Local<Script> access_f1 = v8_compile("f[42]");
6934 for (int j = 0; j < 5; j++) {
6935 CHECK(!access_f0->Run()->Equals(other_object));
6936 CHECK(access_f0->Run()->IsUndefined());
6937 CHECK(!access_f1->Run()->Equals(v8_num(87)));
6938 CHECK(access_f1->Run()->IsUndefined());
6939 }
6940
6941 // Now it gets hairy: Set the prototype for the other global object
6942 // to be the current global object. The prototype chain for 'f' now
6943 // goes through 'other' but ends up in the current global object.
6944 { Context::Scope scope(other);
6945 other->Global()->Set(v8_str("__proto__"), current->Global());
6946 }
6947 // Set a named and an index property on the current global
6948 // object. To force the lookup to go through the other global object,
6949 // the properties must not exist in the other global object.
6950 current->Global()->Set(v8_str("foo"), v8_num(100));
6951 current->Global()->Set(v8_num(99), v8_num(101));
6952 // Try to read the properties from f and make sure that the access
6953 // gets stopped by the security checks on the other global object.
6954 Local<Script> access_f2 = v8_compile("f.foo");
6955 Local<Script> access_f3 = v8_compile("f[99]");
6956 for (int k = 0; k < 5; k++) {
6957 CHECK(!access_f2->Run()->Equals(v8_num(100)));
6958 CHECK(access_f2->Run()->IsUndefined());
6959 CHECK(!access_f3->Run()->Equals(v8_num(101)));
6960 CHECK(access_f3->Run()->IsUndefined());
6961 }
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00006962 other.Dispose(other->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006963}
6964
6965
6966THREADED_TEST(CrossDomainDelete) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006967 LocalContext env1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00006968 v8::HandleScope handle_scope(env1->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006969 v8::Persistent<Context> env2 = Context::New();
6970
6971 Local<Value> foo = v8_str("foo");
6972 Local<Value> bar = v8_str("bar");
6973
6974 // Set to the same domain.
6975 env1->SetSecurityToken(foo);
6976 env2->SetSecurityToken(foo);
6977
6978 env1->Global()->Set(v8_str("prop"), v8_num(3));
6979 env2->Global()->Set(v8_str("env1"), env1->Global());
6980
6981 // Change env2 to a different domain and delete env1.prop.
6982 env2->SetSecurityToken(bar);
6983 {
6984 Context::Scope scope_env2(env2);
6985 Local<Value> result =
6986 Script::Compile(v8_str("delete env1.prop"))->Run();
6987 CHECK(result->IsFalse());
6988 }
6989
6990 // Check that env1.prop still exists.
6991 Local<Value> v = env1->Global()->Get(v8_str("prop"));
6992 CHECK(v->IsNumber());
6993 CHECK_EQ(3, v->Int32Value());
6994
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00006995 env2.Dispose(env2->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006996}
6997
6998
ager@chromium.org870a0b62008-11-04 11:43:05 +00006999THREADED_TEST(CrossDomainIsPropertyEnumerable) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00007000 LocalContext env1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00007001 v8::HandleScope handle_scope(env1->GetIsolate());
ager@chromium.org870a0b62008-11-04 11:43:05 +00007002 v8::Persistent<Context> env2 = Context::New();
7003
7004 Local<Value> foo = v8_str("foo");
7005 Local<Value> bar = v8_str("bar");
7006
7007 // Set to the same domain.
7008 env1->SetSecurityToken(foo);
7009 env2->SetSecurityToken(foo);
7010
7011 env1->Global()->Set(v8_str("prop"), v8_num(3));
7012 env2->Global()->Set(v8_str("env1"), env1->Global());
7013
7014 // env1.prop is enumerable in env2.
7015 Local<String> test = v8_str("propertyIsEnumerable.call(env1, 'prop')");
7016 {
7017 Context::Scope scope_env2(env2);
7018 Local<Value> result = Script::Compile(test)->Run();
7019 CHECK(result->IsTrue());
7020 }
7021
7022 // Change env2 to a different domain and test again.
7023 env2->SetSecurityToken(bar);
7024 {
7025 Context::Scope scope_env2(env2);
7026 Local<Value> result = Script::Compile(test)->Run();
7027 CHECK(result->IsFalse());
7028 }
7029
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00007030 env2.Dispose(env2->GetIsolate());
ager@chromium.org870a0b62008-11-04 11:43:05 +00007031}
7032
7033
ager@chromium.org236ad962008-09-25 09:45:57 +00007034THREADED_TEST(CrossDomainForIn) {
ager@chromium.org236ad962008-09-25 09:45:57 +00007035 LocalContext env1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00007036 v8::HandleScope handle_scope(env1->GetIsolate());
ager@chromium.org236ad962008-09-25 09:45:57 +00007037 v8::Persistent<Context> env2 = Context::New();
7038
7039 Local<Value> foo = v8_str("foo");
7040 Local<Value> bar = v8_str("bar");
7041
7042 // Set to the same domain.
7043 env1->SetSecurityToken(foo);
7044 env2->SetSecurityToken(foo);
7045
7046 env1->Global()->Set(v8_str("prop"), v8_num(3));
7047 env2->Global()->Set(v8_str("env1"), env1->Global());
7048
7049 // Change env2 to a different domain and set env1's global object
7050 // as the __proto__ of an object in env2 and enumerate properties
7051 // in for-in. It shouldn't enumerate properties on env1's global
7052 // object.
7053 env2->SetSecurityToken(bar);
7054 {
7055 Context::Scope scope_env2(env2);
7056 Local<Value> result =
7057 CompileRun("(function(){var obj = {'__proto__':env1};"
7058 "for (var p in obj)"
7059 " if (p == 'prop') return false;"
7060 "return true;})()");
7061 CHECK(result->IsTrue());
7062 }
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00007063 env2.Dispose(env2->GetIsolate());
ager@chromium.org236ad962008-09-25 09:45:57 +00007064}
7065
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007066
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00007067TEST(ContextDetachGlobal) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00007068 LocalContext env1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00007069 v8::HandleScope handle_scope(env1->GetIsolate());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00007070 v8::Persistent<Context> env2 = Context::New();
7071
7072 Local<v8::Object> global1 = env1->Global();
7073
7074 Local<Value> foo = v8_str("foo");
7075
7076 // Set to the same domain.
7077 env1->SetSecurityToken(foo);
7078 env2->SetSecurityToken(foo);
7079
7080 // Enter env2
7081 env2->Enter();
7082
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +00007083 // Create a function in env2 and add a reference to it in env1.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00007084 Local<v8::Object> global2 = env2->Global();
7085 global2->Set(v8_str("prop"), v8::Integer::New(1));
7086 CompileRun("function getProp() {return prop;}");
7087
7088 env1->Global()->Set(v8_str("getProp"),
7089 global2->Get(v8_str("getProp")));
7090
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +00007091 // Detach env2's global, and reuse the global object of env2
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00007092 env2->Exit();
7093 env2->DetachGlobal();
7094 // env2 has a new global object.
7095 CHECK(!env2->Global()->Equals(global2));
7096
7097 v8::Persistent<Context> env3 =
7098 Context::New(0, v8::Handle<v8::ObjectTemplate>(), global2);
7099 env3->SetSecurityToken(v8_str("bar"));
7100 env3->Enter();
7101
7102 Local<v8::Object> global3 = env3->Global();
7103 CHECK_EQ(global2, global3);
7104 CHECK(global3->Get(v8_str("prop"))->IsUndefined());
7105 CHECK(global3->Get(v8_str("getProp"))->IsUndefined());
7106 global3->Set(v8_str("prop"), v8::Integer::New(-1));
7107 global3->Set(v8_str("prop2"), v8::Integer::New(2));
7108 env3->Exit();
7109
7110 // Call getProp in env1, and it should return the value 1
7111 {
7112 Local<Value> get_prop = global1->Get(v8_str("getProp"));
7113 CHECK(get_prop->IsFunction());
7114 v8::TryCatch try_catch;
7115 Local<Value> r = Function::Cast(*get_prop)->Call(global1, 0, NULL);
7116 CHECK(!try_catch.HasCaught());
7117 CHECK_EQ(1, r->Int32Value());
7118 }
7119
7120 // Check that env3 is not accessible from env1
7121 {
7122 Local<Value> r = global3->Get(v8_str("prop2"));
7123 CHECK(r->IsUndefined());
7124 }
7125
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00007126 env2.Dispose(env2->GetIsolate());
7127 env3.Dispose(env3->GetIsolate());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00007128}
7129
7130
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +00007131TEST(DetachAndReattachGlobal) {
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +00007132 LocalContext env1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00007133 v8::HandleScope scope(env1->GetIsolate());
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +00007134
7135 // Create second environment.
7136 v8::Persistent<Context> env2 = Context::New();
7137
7138 Local<Value> foo = v8_str("foo");
7139
7140 // Set same security token for env1 and env2.
7141 env1->SetSecurityToken(foo);
7142 env2->SetSecurityToken(foo);
7143
7144 // Create a property on the global object in env2.
7145 {
7146 v8::Context::Scope scope(env2);
7147 env2->Global()->Set(v8_str("p"), v8::Integer::New(42));
7148 }
7149
7150 // Create a reference to env2 global from env1 global.
7151 env1->Global()->Set(v8_str("other"), env2->Global());
7152
7153 // Check that we have access to other.p in env2 from env1.
7154 Local<Value> result = CompileRun("other.p");
7155 CHECK(result->IsInt32());
7156 CHECK_EQ(42, result->Int32Value());
7157
7158 // Hold on to global from env2 and detach global from env2.
7159 Local<v8::Object> global2 = env2->Global();
7160 env2->DetachGlobal();
7161
7162 // Check that the global has been detached. No other.p property can
7163 // be found.
7164 result = CompileRun("other.p");
7165 CHECK(result->IsUndefined());
7166
7167 // Reuse global2 for env3.
7168 v8::Persistent<Context> env3 =
7169 Context::New(0, v8::Handle<v8::ObjectTemplate>(), global2);
7170 CHECK_EQ(global2, env3->Global());
7171
7172 // Start by using the same security token for env3 as for env1 and env2.
7173 env3->SetSecurityToken(foo);
7174
7175 // Create a property on the global object in env3.
7176 {
7177 v8::Context::Scope scope(env3);
7178 env3->Global()->Set(v8_str("p"), v8::Integer::New(24));
7179 }
7180
7181 // Check that other.p is now the property in env3 and that we have access.
7182 result = CompileRun("other.p");
7183 CHECK(result->IsInt32());
7184 CHECK_EQ(24, result->Int32Value());
7185
7186 // Change security token for env3 to something different from env1 and env2.
7187 env3->SetSecurityToken(v8_str("bar"));
7188
7189 // Check that we do not have access to other.p in env1. |other| is now
7190 // the global object for env3 which has a different security token,
7191 // so access should be blocked.
7192 result = CompileRun("other.p");
7193 CHECK(result->IsUndefined());
7194
7195 // Detach the global for env3 and reattach it to env2.
7196 env3->DetachGlobal();
7197 env2->ReattachGlobal(global2);
7198
7199 // Check that we have access to other.p again in env1. |other| is now
7200 // the global object for env2 which has the same security token as env1.
7201 result = CompileRun("other.p");
7202 CHECK(result->IsInt32());
7203 CHECK_EQ(42, result->Int32Value());
7204
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00007205 env2.Dispose(env2->GetIsolate());
7206 env3.Dispose(env3->GetIsolate());
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +00007207}
7208
7209
ricow@chromium.org83aa5492011-02-07 12:42:56 +00007210static bool allowed_access_type[v8::ACCESS_KEYS + 1] = { false };
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007211static bool NamedAccessBlocker(Local<v8::Object> global,
7212 Local<Value> name,
7213 v8::AccessType type,
7214 Local<Value> data) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00007215 return Context::GetCurrent()->Global()->Equals(global) ||
7216 allowed_access_type[type];
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007217}
7218
7219
7220static bool IndexedAccessBlocker(Local<v8::Object> global,
7221 uint32_t key,
7222 v8::AccessType type,
7223 Local<Value> data) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +00007224 return Context::GetCurrent()->Global()->Equals(global) ||
7225 allowed_access_type[type];
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007226}
7227
7228
7229static int g_echo_value = -1;
7230static v8::Handle<Value> EchoGetter(Local<String> name,
7231 const AccessorInfo& info) {
7232 return v8_num(g_echo_value);
7233}
7234
7235
7236static void EchoSetter(Local<String> name,
7237 Local<Value> value,
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00007238 const AccessorInfo&) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007239 if (value->IsNumber())
7240 g_echo_value = value->Int32Value();
7241}
7242
7243
7244static v8::Handle<Value> UnreachableGetter(Local<String> name,
7245 const AccessorInfo& info) {
7246 CHECK(false); // This function should not be called..
7247 return v8::Undefined();
7248}
7249
7250
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00007251static void UnreachableSetter(Local<String>, Local<Value>,
7252 const AccessorInfo&) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007253 CHECK(false); // This function should nto be called.
7254}
7255
7256
ricow@chromium.org83aa5492011-02-07 12:42:56 +00007257TEST(AccessControl) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00007258 v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007259 v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
7260
7261 global_template->SetAccessCheckCallbacks(NamedAccessBlocker,
7262 IndexedAccessBlocker);
7263
7264 // Add an accessor accessible by cross-domain JS code.
7265 global_template->SetAccessor(
7266 v8_str("accessible_prop"),
7267 EchoGetter, EchoSetter,
7268 v8::Handle<Value>(),
7269 v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
7270
7271 // Add an accessor that is not accessible by cross-domain JS code.
ager@chromium.org870a0b62008-11-04 11:43:05 +00007272 global_template->SetAccessor(v8_str("blocked_prop"),
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007273 UnreachableGetter, UnreachableSetter,
7274 v8::Handle<Value>(),
7275 v8::DEFAULT);
7276
7277 // Create an environment
7278 v8::Persistent<Context> context0 = Context::New(NULL, global_template);
7279 context0->Enter();
7280
7281 v8::Handle<v8::Object> global0 = context0->Global();
7282
ricow@chromium.org83aa5492011-02-07 12:42:56 +00007283 // Define a property with JS getter and setter.
7284 CompileRun(
7285 "function getter() { return 'getter'; };\n"
7286 "function setter() { return 'setter'; }\n"
7287 "Object.defineProperty(this, 'js_accessor_p', {get:getter, set:setter})");
7288
7289 Local<Value> getter = global0->Get(v8_str("getter"));
7290 Local<Value> setter = global0->Get(v8_str("setter"));
7291
7292 // And define normal element.
7293 global0->Set(239, v8_str("239"));
7294
7295 // Define an element with JS getter and setter.
7296 CompileRun(
7297 "function el_getter() { return 'el_getter'; };\n"
7298 "function el_setter() { return 'el_setter'; };\n"
7299 "Object.defineProperty(this, '42', {get: el_getter, set: el_setter});");
7300
7301 Local<Value> el_getter = global0->Get(v8_str("el_getter"));
7302 Local<Value> el_setter = global0->Get(v8_str("el_setter"));
7303
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00007304 v8::HandleScope scope1(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007305
7306 v8::Persistent<Context> context1 = Context::New();
7307 context1->Enter();
7308
7309 v8::Handle<v8::Object> global1 = context1->Global();
7310 global1->Set(v8_str("other"), global0);
7311
ricow@chromium.org83aa5492011-02-07 12:42:56 +00007312 // Access blocked property.
7313 CompileRun("other.blocked_prop = 1");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007314
ricow@chromium.org83aa5492011-02-07 12:42:56 +00007315 ExpectUndefined("other.blocked_prop");
7316 ExpectUndefined(
7317 "Object.getOwnPropertyDescriptor(other, 'blocked_prop')");
7318 ExpectFalse("propertyIsEnumerable.call(other, 'blocked_prop')");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007319
ricow@chromium.org83aa5492011-02-07 12:42:56 +00007320 // Enable ACCESS_HAS
7321 allowed_access_type[v8::ACCESS_HAS] = true;
7322 ExpectUndefined("other.blocked_prop");
7323 // ... and now we can get the descriptor...
7324 ExpectUndefined(
antonm@chromium.orgdca01352011-01-31 17:15:05 +00007325 "Object.getOwnPropertyDescriptor(other, 'blocked_prop').value");
ricow@chromium.org83aa5492011-02-07 12:42:56 +00007326 // ... and enumerate the property.
7327 ExpectTrue("propertyIsEnumerable.call(other, 'blocked_prop')");
7328 allowed_access_type[v8::ACCESS_HAS] = false;
antonm@chromium.orgdca01352011-01-31 17:15:05 +00007329
ricow@chromium.org83aa5492011-02-07 12:42:56 +00007330 // Access blocked element.
7331 CompileRun("other[239] = 1");
7332
7333 ExpectUndefined("other[239]");
7334 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '239')");
7335 ExpectFalse("propertyIsEnumerable.call(other, '239')");
7336
7337 // Enable ACCESS_HAS
7338 allowed_access_type[v8::ACCESS_HAS] = true;
7339 ExpectUndefined("other[239]");
7340 // ... and now we can get the descriptor...
7341 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '239').value");
7342 // ... and enumerate the property.
7343 ExpectTrue("propertyIsEnumerable.call(other, '239')");
7344 allowed_access_type[v8::ACCESS_HAS] = false;
7345
7346 // Access a property with JS accessor.
7347 CompileRun("other.js_accessor_p = 2");
7348
7349 ExpectUndefined("other.js_accessor_p");
7350 ExpectUndefined(
7351 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p')");
7352
7353 // Enable ACCESS_HAS.
7354 allowed_access_type[v8::ACCESS_HAS] = true;
7355 ExpectUndefined("other.js_accessor_p");
7356 ExpectUndefined(
7357 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get");
7358 ExpectUndefined(
7359 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set");
7360 ExpectUndefined(
7361 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
7362 allowed_access_type[v8::ACCESS_HAS] = false;
7363
7364 // Enable both ACCESS_HAS and ACCESS_GET.
7365 allowed_access_type[v8::ACCESS_HAS] = true;
7366 allowed_access_type[v8::ACCESS_GET] = true;
7367
7368 ExpectString("other.js_accessor_p", "getter");
7369 ExpectObject(
7370 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get", getter);
7371 ExpectUndefined(
7372 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set");
7373 ExpectUndefined(
7374 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
7375
7376 allowed_access_type[v8::ACCESS_GET] = false;
7377 allowed_access_type[v8::ACCESS_HAS] = false;
7378
7379 // Enable both ACCESS_HAS and ACCESS_SET.
7380 allowed_access_type[v8::ACCESS_HAS] = true;
7381 allowed_access_type[v8::ACCESS_SET] = true;
7382
7383 ExpectUndefined("other.js_accessor_p");
7384 ExpectUndefined(
7385 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get");
7386 ExpectObject(
7387 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set", setter);
7388 ExpectUndefined(
7389 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
7390
7391 allowed_access_type[v8::ACCESS_SET] = false;
7392 allowed_access_type[v8::ACCESS_HAS] = false;
7393
7394 // Enable both ACCESS_HAS, ACCESS_GET and ACCESS_SET.
7395 allowed_access_type[v8::ACCESS_HAS] = true;
7396 allowed_access_type[v8::ACCESS_GET] = true;
7397 allowed_access_type[v8::ACCESS_SET] = true;
7398
7399 ExpectString("other.js_accessor_p", "getter");
7400 ExpectObject(
7401 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get", getter);
7402 ExpectObject(
7403 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set", setter);
7404 ExpectUndefined(
7405 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
7406
7407 allowed_access_type[v8::ACCESS_SET] = false;
7408 allowed_access_type[v8::ACCESS_GET] = false;
7409 allowed_access_type[v8::ACCESS_HAS] = false;
7410
7411 // Access an element with JS accessor.
7412 CompileRun("other[42] = 2");
7413
7414 ExpectUndefined("other[42]");
7415 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42')");
7416
7417 // Enable ACCESS_HAS.
7418 allowed_access_type[v8::ACCESS_HAS] = true;
7419 ExpectUndefined("other[42]");
7420 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').get");
7421 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').set");
7422 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
7423 allowed_access_type[v8::ACCESS_HAS] = false;
7424
7425 // Enable both ACCESS_HAS and ACCESS_GET.
7426 allowed_access_type[v8::ACCESS_HAS] = true;
7427 allowed_access_type[v8::ACCESS_GET] = true;
7428
7429 ExpectString("other[42]", "el_getter");
7430 ExpectObject("Object.getOwnPropertyDescriptor(other, '42').get", el_getter);
7431 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').set");
7432 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
7433
7434 allowed_access_type[v8::ACCESS_GET] = false;
7435 allowed_access_type[v8::ACCESS_HAS] = false;
7436
7437 // Enable both ACCESS_HAS and ACCESS_SET.
7438 allowed_access_type[v8::ACCESS_HAS] = true;
7439 allowed_access_type[v8::ACCESS_SET] = true;
7440
7441 ExpectUndefined("other[42]");
7442 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').get");
7443 ExpectObject("Object.getOwnPropertyDescriptor(other, '42').set", el_setter);
7444 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
7445
7446 allowed_access_type[v8::ACCESS_SET] = false;
7447 allowed_access_type[v8::ACCESS_HAS] = false;
7448
7449 // Enable both ACCESS_HAS, ACCESS_GET and ACCESS_SET.
7450 allowed_access_type[v8::ACCESS_HAS] = true;
7451 allowed_access_type[v8::ACCESS_GET] = true;
7452 allowed_access_type[v8::ACCESS_SET] = true;
7453
7454 ExpectString("other[42]", "el_getter");
7455 ExpectObject("Object.getOwnPropertyDescriptor(other, '42').get", el_getter);
7456 ExpectObject("Object.getOwnPropertyDescriptor(other, '42').set", el_setter);
7457 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
7458
7459 allowed_access_type[v8::ACCESS_SET] = false;
7460 allowed_access_type[v8::ACCESS_GET] = false;
7461 allowed_access_type[v8::ACCESS_HAS] = false;
7462
7463 v8::Handle<Value> value;
ager@chromium.org870a0b62008-11-04 11:43:05 +00007464
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007465 // Access accessible property
antonm@chromium.orgdca01352011-01-31 17:15:05 +00007466 value = CompileRun("other.accessible_prop = 3");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007467 CHECK(value->IsNumber());
7468 CHECK_EQ(3, value->Int32Value());
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00007469 CHECK_EQ(3, g_echo_value);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007470
antonm@chromium.orgdca01352011-01-31 17:15:05 +00007471 value = CompileRun("other.accessible_prop");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007472 CHECK(value->IsNumber());
7473 CHECK_EQ(3, value->Int32Value());
7474
antonm@chromium.orgdca01352011-01-31 17:15:05 +00007475 value = CompileRun(
7476 "Object.getOwnPropertyDescriptor(other, 'accessible_prop').value");
7477 CHECK(value->IsNumber());
7478 CHECK_EQ(3, value->Int32Value());
7479
7480 value = CompileRun("propertyIsEnumerable.call(other, 'accessible_prop')");
ager@chromium.org870a0b62008-11-04 11:43:05 +00007481 CHECK(value->IsTrue());
7482
7483 // Enumeration doesn't enumerate accessors from inaccessible objects in
7484 // the prototype chain even if the accessors are in themselves accessible.
antonm@chromium.orgdca01352011-01-31 17:15:05 +00007485 value =
ager@chromium.org870a0b62008-11-04 11:43:05 +00007486 CompileRun("(function(){var obj = {'__proto__':other};"
7487 "for (var p in obj)"
7488 " if (p == 'accessible_prop' || p == 'blocked_prop') {"
7489 " return false;"
7490 " }"
7491 "return true;})()");
antonm@chromium.orgdca01352011-01-31 17:15:05 +00007492 CHECK(value->IsTrue());
ager@chromium.org870a0b62008-11-04 11:43:05 +00007493
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007494 context1->Exit();
7495 context0->Exit();
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00007496 context1.Dispose(context1->GetIsolate());
7497 context0.Dispose(context0->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007498}
7499
7500
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00007501TEST(AccessControlES5) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00007502 v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
ricow@chromium.org65001782011-02-15 13:36:41 +00007503 v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
7504
7505 global_template->SetAccessCheckCallbacks(NamedAccessBlocker,
7506 IndexedAccessBlocker);
7507
ricow@chromium.orgf5a18a22011-03-15 10:00:20 +00007508 // Add accessible accessor.
7509 global_template->SetAccessor(
7510 v8_str("accessible_prop"),
7511 EchoGetter, EchoSetter,
7512 v8::Handle<Value>(),
7513 v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
7514
7515
ricow@chromium.org65001782011-02-15 13:36:41 +00007516 // Add an accessor that is not accessible by cross-domain JS code.
7517 global_template->SetAccessor(v8_str("blocked_prop"),
7518 UnreachableGetter, UnreachableSetter,
7519 v8::Handle<Value>(),
7520 v8::DEFAULT);
7521
7522 // Create an environment
7523 v8::Persistent<Context> context0 = Context::New(NULL, global_template);
7524 context0->Enter();
7525
7526 v8::Handle<v8::Object> global0 = context0->Global();
7527
7528 v8::Persistent<Context> context1 = Context::New();
7529 context1->Enter();
7530 v8::Handle<v8::Object> global1 = context1->Global();
7531 global1->Set(v8_str("other"), global0);
7532
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00007533 // Regression test for issue 1154.
ricow@chromium.org65001782011-02-15 13:36:41 +00007534 ExpectTrue("Object.keys(other).indexOf('blocked_prop') == -1");
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00007535
7536 ExpectUndefined("other.blocked_prop");
7537
7538 // Regression test for issue 1027.
7539 CompileRun("Object.defineProperty(\n"
7540 " other, 'blocked_prop', {configurable: false})");
7541 ExpectUndefined("other.blocked_prop");
7542 ExpectUndefined(
7543 "Object.getOwnPropertyDescriptor(other, 'blocked_prop')");
7544
7545 // Regression test for issue 1171.
7546 ExpectTrue("Object.isExtensible(other)");
7547 CompileRun("Object.preventExtensions(other)");
7548 ExpectTrue("Object.isExtensible(other)");
7549
7550 // Object.seal and Object.freeze.
7551 CompileRun("Object.freeze(other)");
7552 ExpectTrue("Object.isExtensible(other)");
7553
7554 CompileRun("Object.seal(other)");
7555 ExpectTrue("Object.isExtensible(other)");
ricow@chromium.orgf5a18a22011-03-15 10:00:20 +00007556
7557 // Regression test for issue 1250.
7558 // Make sure that we can set the accessible accessors value using normal
7559 // assignment.
7560 CompileRun("other.accessible_prop = 42");
7561 CHECK_EQ(42, g_echo_value);
7562
7563 v8::Handle<Value> value;
7564 // We follow Safari in ignoring assignments to host object accessors.
7565 CompileRun("Object.defineProperty(other, 'accessible_prop', {value: -1})");
7566 value = CompileRun("other.accessible_prop == 42");
7567 CHECK(value->IsTrue());
ricow@chromium.org65001782011-02-15 13:36:41 +00007568}
7569
7570
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00007571static bool GetOwnPropertyNamesNamedBlocker(Local<v8::Object> global,
7572 Local<Value> name,
7573 v8::AccessType type,
7574 Local<Value> data) {
7575 return false;
7576}
7577
7578
7579static bool GetOwnPropertyNamesIndexedBlocker(Local<v8::Object> global,
7580 uint32_t key,
7581 v8::AccessType type,
7582 Local<Value> data) {
7583 return false;
7584}
7585
7586
7587THREADED_TEST(AccessControlGetOwnPropertyNames) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00007588 v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00007589 v8::Handle<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New();
7590
7591 obj_template->Set(v8_str("x"), v8::Integer::New(42));
7592 obj_template->SetAccessCheckCallbacks(GetOwnPropertyNamesNamedBlocker,
7593 GetOwnPropertyNamesIndexedBlocker);
7594
7595 // Create an environment
7596 v8::Persistent<Context> context0 = Context::New(NULL, obj_template);
7597 context0->Enter();
7598
7599 v8::Handle<v8::Object> global0 = context0->Global();
7600
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00007601 v8::HandleScope scope1(v8::Isolate::GetCurrent());
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00007602
7603 v8::Persistent<Context> context1 = Context::New();
7604 context1->Enter();
7605
7606 v8::Handle<v8::Object> global1 = context1->Global();
7607 global1->Set(v8_str("other"), global0);
7608 global1->Set(v8_str("object"), obj_template->NewInstance());
7609
7610 v8::Handle<Value> value;
7611
7612 // Attempt to get the property names of the other global object and
7613 // of an object that requires access checks. Accessing the other
7614 // global object should be blocked by access checks on the global
7615 // proxy object. Accessing the object that requires access checks
7616 // is blocked by the access checks on the object itself.
7617 value = CompileRun("Object.getOwnPropertyNames(other).length == 0");
7618 CHECK(value->IsTrue());
7619
7620 value = CompileRun("Object.getOwnPropertyNames(object).length == 0");
7621 CHECK(value->IsTrue());
7622
7623 context1->Exit();
7624 context0->Exit();
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00007625 context1.Dispose(context1->GetIsolate());
7626 context0.Dispose(context0->GetIsolate());
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00007627}
7628
7629
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +00007630static v8::Handle<v8::Array> IndexedPropertyEnumerator(const AccessorInfo&) {
7631 v8::Handle<v8::Array> result = v8::Array::New(2);
7632 result->Set(0, v8::Integer::New(7));
7633 result->Set(1, v8::Object::New());
7634 return result;
7635}
7636
7637
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00007638static v8::Handle<v8::Array> NamedPropertyEnumerator(const AccessorInfo& info) {
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +00007639 v8::Handle<v8::Array> result = v8::Array::New(2);
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00007640 result->Set(0, v8_str("x"));
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +00007641 result->Set(1, v8::Object::New());
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00007642 return result;
7643}
7644
7645
7646THREADED_TEST(GetOwnPropertyNamesWithInterceptor) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00007647 v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00007648 v8::Handle<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New();
7649
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +00007650 obj_template->Set(v8_str("7"), v8::Integer::New(7));
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00007651 obj_template->Set(v8_str("x"), v8::Integer::New(42));
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +00007652 obj_template->SetIndexedPropertyHandler(NULL, NULL, NULL, NULL,
7653 IndexedPropertyEnumerator);
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00007654 obj_template->SetNamedPropertyHandler(NULL, NULL, NULL, NULL,
7655 NamedPropertyEnumerator);
7656
7657 LocalContext context;
7658 v8::Handle<v8::Object> global = context->Global();
7659 global->Set(v8_str("object"), obj_template->NewInstance());
7660
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +00007661 v8::Handle<v8::Value> result =
7662 CompileRun("Object.getOwnPropertyNames(object)");
7663 CHECK(result->IsArray());
7664 v8::Handle<v8::Array> result_array = v8::Handle<v8::Array>::Cast(result);
7665 CHECK_EQ(3, result_array->Length());
7666 CHECK(result_array->Get(0)->IsString());
7667 CHECK(result_array->Get(1)->IsString());
7668 CHECK(result_array->Get(2)->IsString());
7669 CHECK_EQ(v8_str("7"), result_array->Get(0));
7670 CHECK_EQ(v8_str("[object Object]"), result_array->Get(1));
7671 CHECK_EQ(v8_str("x"), result_array->Get(2));
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00007672}
7673
7674
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007675static v8::Handle<Value> ConstTenGetter(Local<String> name,
7676 const AccessorInfo& info) {
7677 return v8_num(10);
7678}
7679
7680
7681THREADED_TEST(CrossDomainAccessors) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00007682 v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007683
7684 v8::Handle<v8::FunctionTemplate> func_template = v8::FunctionTemplate::New();
7685
7686 v8::Handle<v8::ObjectTemplate> global_template =
7687 func_template->InstanceTemplate();
7688
7689 v8::Handle<v8::ObjectTemplate> proto_template =
7690 func_template->PrototypeTemplate();
7691
7692 // Add an accessor to proto that's accessible by cross-domain JS code.
7693 proto_template->SetAccessor(v8_str("accessible"),
7694 ConstTenGetter, 0,
7695 v8::Handle<Value>(),
7696 v8::ALL_CAN_READ);
7697
7698 // Add an accessor that is not accessible by cross-domain JS code.
7699 global_template->SetAccessor(v8_str("unreachable"),
7700 UnreachableGetter, 0,
7701 v8::Handle<Value>(),
7702 v8::DEFAULT);
7703
7704 v8::Persistent<Context> context0 = Context::New(NULL, global_template);
7705 context0->Enter();
7706
7707 Local<v8::Object> global = context0->Global();
7708 // Add a normal property that shadows 'accessible'
7709 global->Set(v8_str("accessible"), v8_num(11));
7710
7711 // Enter a new context.
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00007712 v8::HandleScope scope1(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007713 v8::Persistent<Context> context1 = Context::New();
7714 context1->Enter();
7715
7716 v8::Handle<v8::Object> global1 = context1->Global();
7717 global1->Set(v8_str("other"), global);
7718
7719 // Should return 10, instead of 11
7720 v8::Handle<Value> value = v8_compile("other.accessible")->Run();
7721 CHECK(value->IsNumber());
7722 CHECK_EQ(10, value->Int32Value());
7723
7724 value = v8_compile("other.unreachable")->Run();
7725 CHECK(value->IsUndefined());
7726
7727 context1->Exit();
7728 context0->Exit();
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00007729 context1.Dispose(context1->GetIsolate());
7730 context0.Dispose(context0->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007731}
7732
7733
7734static int named_access_count = 0;
7735static int indexed_access_count = 0;
7736
7737static bool NamedAccessCounter(Local<v8::Object> global,
7738 Local<Value> name,
7739 v8::AccessType type,
7740 Local<Value> data) {
7741 named_access_count++;
7742 return true;
7743}
7744
7745
7746static bool IndexedAccessCounter(Local<v8::Object> global,
7747 uint32_t key,
7748 v8::AccessType type,
7749 Local<Value> data) {
7750 indexed_access_count++;
7751 return true;
7752}
7753
7754
7755// This one is too easily disturbed by other tests.
7756TEST(AccessControlIC) {
7757 named_access_count = 0;
7758 indexed_access_count = 0;
7759
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00007760 v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007761
7762 // Create an environment.
7763 v8::Persistent<Context> context0 = Context::New();
7764 context0->Enter();
7765
7766 // Create an object that requires access-check functions to be
7767 // called for cross-domain access.
7768 v8::Handle<v8::ObjectTemplate> object_template = v8::ObjectTemplate::New();
7769 object_template->SetAccessCheckCallbacks(NamedAccessCounter,
7770 IndexedAccessCounter);
7771 Local<v8::Object> object = object_template->NewInstance();
7772
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00007773 v8::HandleScope scope1(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007774
7775 // Create another environment.
7776 v8::Persistent<Context> context1 = Context::New();
7777 context1->Enter();
7778
7779 // Make easy access to the object from the other environment.
7780 v8::Handle<v8::Object> global1 = context1->Global();
7781 global1->Set(v8_str("obj"), object);
7782
7783 v8::Handle<Value> value;
7784
7785 // Check that the named access-control function is called every time.
ager@chromium.org8bb60582008-12-11 12:02:20 +00007786 CompileRun("function testProp(obj) {"
7787 " for (var i = 0; i < 10; i++) obj.prop = 1;"
7788 " for (var j = 0; j < 10; j++) obj.prop;"
7789 " return obj.prop"
7790 "}");
7791 value = CompileRun("testProp(obj)");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007792 CHECK(value->IsNumber());
7793 CHECK_EQ(1, value->Int32Value());
7794 CHECK_EQ(21, named_access_count);
7795
7796 // Check that the named access-control function is called every time.
ager@chromium.org8bb60582008-12-11 12:02:20 +00007797 CompileRun("var p = 'prop';"
7798 "function testKeyed(obj) {"
7799 " for (var i = 0; i < 10; i++) obj[p] = 1;"
7800 " for (var j = 0; j < 10; j++) obj[p];"
7801 " return obj[p];"
7802 "}");
7803 // Use obj which requires access checks. No inline caching is used
7804 // in that case.
7805 value = CompileRun("testKeyed(obj)");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007806 CHECK(value->IsNumber());
7807 CHECK_EQ(1, value->Int32Value());
7808 CHECK_EQ(42, named_access_count);
ager@chromium.org8bb60582008-12-11 12:02:20 +00007809 // Force the inline caches into generic state and try again.
7810 CompileRun("testKeyed({ a: 0 })");
7811 CompileRun("testKeyed({ b: 0 })");
7812 value = CompileRun("testKeyed(obj)");
7813 CHECK(value->IsNumber());
7814 CHECK_EQ(1, value->Int32Value());
7815 CHECK_EQ(63, named_access_count);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007816
7817 // Check that the indexed access-control function is called every time.
ager@chromium.org8bb60582008-12-11 12:02:20 +00007818 CompileRun("function testIndexed(obj) {"
7819 " for (var i = 0; i < 10; i++) obj[0] = 1;"
7820 " for (var j = 0; j < 10; j++) obj[0];"
7821 " return obj[0]"
7822 "}");
7823 value = CompileRun("testIndexed(obj)");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007824 CHECK(value->IsNumber());
7825 CHECK_EQ(1, value->Int32Value());
7826 CHECK_EQ(21, indexed_access_count);
ager@chromium.org8bb60582008-12-11 12:02:20 +00007827 // Force the inline caches into generic state.
7828 CompileRun("testIndexed(new Array(1))");
7829 // Test that the indexed access check is called.
7830 value = CompileRun("testIndexed(obj)");
7831 CHECK(value->IsNumber());
7832 CHECK_EQ(1, value->Int32Value());
7833 CHECK_EQ(42, indexed_access_count);
7834
7835 // Check that the named access check is called when invoking
7836 // functions on an object that requires access checks.
7837 CompileRun("obj.f = function() {}");
7838 CompileRun("function testCallNormal(obj) {"
7839 " for (var i = 0; i < 10; i++) obj.f();"
7840 "}");
7841 CompileRun("testCallNormal(obj)");
7842 CHECK_EQ(74, named_access_count);
7843
7844 // Force obj into slow case.
7845 value = CompileRun("delete obj.prop");
7846 CHECK(value->BooleanValue());
7847 // Force inline caches into dictionary probing mode.
7848 CompileRun("var o = { x: 0 }; delete o.x; testProp(o);");
7849 // Test that the named access check is called.
7850 value = CompileRun("testProp(obj);");
7851 CHECK(value->IsNumber());
7852 CHECK_EQ(1, value->Int32Value());
7853 CHECK_EQ(96, named_access_count);
7854
7855 // Force the call inline cache into dictionary probing mode.
7856 CompileRun("o.f = function() {}; testCallNormal(o)");
7857 // Test that the named access check is still called for each
7858 // invocation of the function.
7859 value = CompileRun("testCallNormal(obj)");
7860 CHECK_EQ(106, named_access_count);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007861
7862 context1->Exit();
7863 context0->Exit();
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00007864 context1.Dispose(context1->GetIsolate());
7865 context0.Dispose(context0->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007866}
7867
7868
7869static bool NamedAccessFlatten(Local<v8::Object> global,
7870 Local<Value> name,
7871 v8::AccessType type,
7872 Local<Value> data) {
7873 char buf[100];
7874 int len;
7875
7876 CHECK(name->IsString());
7877
7878 memset(buf, 0x1, sizeof(buf));
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00007879 len = name.As<String>()->WriteAscii(buf);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007880 CHECK_EQ(4, len);
7881
7882 uint16_t buf2[100];
7883
7884 memset(buf, 0x1, sizeof(buf));
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00007885 len = name.As<String>()->Write(buf2);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007886 CHECK_EQ(4, len);
7887
7888 return true;
7889}
7890
7891
7892static bool IndexedAccessFlatten(Local<v8::Object> global,
7893 uint32_t key,
7894 v8::AccessType type,
7895 Local<Value> data) {
7896 return true;
7897}
7898
7899
7900// Regression test. In access checks, operations that may cause
7901// garbage collection are not allowed. It used to be the case that
7902// using the Write operation on a string could cause a garbage
7903// collection due to flattening of the string. This is no longer the
7904// case.
7905THREADED_TEST(AccessControlFlatten) {
7906 named_access_count = 0;
7907 indexed_access_count = 0;
7908
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00007909 v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007910
7911 // Create an environment.
7912 v8::Persistent<Context> context0 = Context::New();
7913 context0->Enter();
7914
7915 // Create an object that requires access-check functions to be
7916 // called for cross-domain access.
7917 v8::Handle<v8::ObjectTemplate> object_template = v8::ObjectTemplate::New();
7918 object_template->SetAccessCheckCallbacks(NamedAccessFlatten,
7919 IndexedAccessFlatten);
7920 Local<v8::Object> object = object_template->NewInstance();
7921
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00007922 v8::HandleScope scope1(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007923
7924 // Create another environment.
7925 v8::Persistent<Context> context1 = Context::New();
7926 context1->Enter();
7927
7928 // Make easy access to the object from the other environment.
7929 v8::Handle<v8::Object> global1 = context1->Global();
7930 global1->Set(v8_str("obj"), object);
7931
7932 v8::Handle<Value> value;
7933
7934 value = v8_compile("var p = 'as' + 'df';")->Run();
7935 value = v8_compile("obj[p];")->Run();
7936
7937 context1->Exit();
7938 context0->Exit();
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00007939 context1.Dispose(context1->GetIsolate());
7940 context0.Dispose(context0->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007941}
7942
7943
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00007944static v8::Handle<Value> AccessControlNamedGetter(
7945 Local<String>, const AccessorInfo&) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007946 return v8::Integer::New(42);
7947}
7948
7949
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00007950static v8::Handle<Value> AccessControlNamedSetter(
7951 Local<String>, Local<Value> value, const AccessorInfo&) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007952 return value;
7953}
7954
7955
7956static v8::Handle<Value> AccessControlIndexedGetter(
7957 uint32_t index,
7958 const AccessorInfo& info) {
7959 return v8_num(42);
7960}
7961
7962
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00007963static v8::Handle<Value> AccessControlIndexedSetter(
7964 uint32_t, Local<Value> value, const AccessorInfo&) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007965 return value;
7966}
7967
7968
7969THREADED_TEST(AccessControlInterceptorIC) {
7970 named_access_count = 0;
7971 indexed_access_count = 0;
7972
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00007973 v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007974
7975 // Create an environment.
7976 v8::Persistent<Context> context0 = Context::New();
7977 context0->Enter();
7978
7979 // Create an object that requires access-check functions to be
7980 // called for cross-domain access. The object also has interceptors
7981 // interceptor.
7982 v8::Handle<v8::ObjectTemplate> object_template = v8::ObjectTemplate::New();
7983 object_template->SetAccessCheckCallbacks(NamedAccessCounter,
7984 IndexedAccessCounter);
7985 object_template->SetNamedPropertyHandler(AccessControlNamedGetter,
7986 AccessControlNamedSetter);
7987 object_template->SetIndexedPropertyHandler(AccessControlIndexedGetter,
7988 AccessControlIndexedSetter);
7989 Local<v8::Object> object = object_template->NewInstance();
7990
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00007991 v8::HandleScope scope1(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007992
7993 // Create another environment.
7994 v8::Persistent<Context> context1 = Context::New();
7995 context1->Enter();
7996
7997 // Make easy access to the object from the other environment.
7998 v8::Handle<v8::Object> global1 = context1->Global();
7999 global1->Set(v8_str("obj"), object);
8000
8001 v8::Handle<Value> value;
8002
8003 // Check that the named access-control function is called every time
8004 // eventhough there is an interceptor on the object.
8005 value = v8_compile("for (var i = 0; i < 10; i++) obj.x = 1;")->Run();
8006 value = v8_compile("for (var i = 0; i < 10; i++) obj.x;"
8007 "obj.x")->Run();
8008 CHECK(value->IsNumber());
8009 CHECK_EQ(42, value->Int32Value());
8010 CHECK_EQ(21, named_access_count);
8011
8012 value = v8_compile("var p = 'x';")->Run();
8013 value = v8_compile("for (var i = 0; i < 10; i++) obj[p] = 1;")->Run();
8014 value = v8_compile("for (var i = 0; i < 10; i++) obj[p];"
8015 "obj[p]")->Run();
8016 CHECK(value->IsNumber());
8017 CHECK_EQ(42, value->Int32Value());
8018 CHECK_EQ(42, named_access_count);
8019
8020 // Check that the indexed access-control function is called every
8021 // time eventhough there is an interceptor on the object.
8022 value = v8_compile("for (var i = 0; i < 10; i++) obj[0] = 1;")->Run();
8023 value = v8_compile("for (var i = 0; i < 10; i++) obj[0];"
8024 "obj[0]")->Run();
8025 CHECK(value->IsNumber());
8026 CHECK_EQ(42, value->Int32Value());
8027 CHECK_EQ(21, indexed_access_count);
8028
8029 context1->Exit();
8030 context0->Exit();
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00008031 context1.Dispose(context1->GetIsolate());
8032 context0.Dispose(context0->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008033}
8034
8035
8036THREADED_TEST(Version) {
8037 v8::V8::GetVersion();
8038}
8039
8040
8041static v8::Handle<Value> InstanceFunctionCallback(const v8::Arguments& args) {
8042 ApiTestFuzzer::Fuzz();
8043 return v8_num(12);
8044}
8045
8046
8047THREADED_TEST(InstanceProperties) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008048 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008049 v8::HandleScope handle_scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008050
8051 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
8052 Local<ObjectTemplate> instance = t->InstanceTemplate();
8053
8054 instance->Set(v8_str("x"), v8_num(42));
8055 instance->Set(v8_str("f"),
8056 v8::FunctionTemplate::New(InstanceFunctionCallback));
8057
8058 Local<Value> o = t->GetFunction()->NewInstance();
8059
8060 context->Global()->Set(v8_str("i"), o);
8061 Local<Value> value = Script::Compile(v8_str("i.x"))->Run();
8062 CHECK_EQ(42, value->Int32Value());
8063
8064 value = Script::Compile(v8_str("i.f()"))->Run();
8065 CHECK_EQ(12, value->Int32Value());
8066}
8067
8068
8069static v8::Handle<Value>
8070GlobalObjectInstancePropertiesGet(Local<String> key, const AccessorInfo&) {
8071 ApiTestFuzzer::Fuzz();
8072 return v8::Handle<Value>();
8073}
8074
8075
8076THREADED_TEST(GlobalObjectInstanceProperties) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008077 v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008078
8079 Local<Value> global_object;
8080
8081 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
8082 t->InstanceTemplate()->SetNamedPropertyHandler(
8083 GlobalObjectInstancePropertiesGet);
8084 Local<ObjectTemplate> instance_template = t->InstanceTemplate();
8085 instance_template->Set(v8_str("x"), v8_num(42));
8086 instance_template->Set(v8_str("f"),
8087 v8::FunctionTemplate::New(InstanceFunctionCallback));
8088
kasperl@chromium.orga5551262010-12-07 12:49:48 +00008089 // The script to check how Crankshaft compiles missing global function
8090 // invocations. function g is not defined and should throw on call.
8091 const char* script =
8092 "function wrapper(call) {"
8093 " var x = 0, y = 1;"
8094 " for (var i = 0; i < 1000; i++) {"
8095 " x += i * 100;"
8096 " y += i * 100;"
8097 " }"
8098 " if (call) g();"
8099 "}"
8100 "for (var i = 0; i < 17; i++) wrapper(false);"
8101 "var thrown = 0;"
8102 "try { wrapper(true); } catch (e) { thrown = 1; };"
8103 "thrown";
8104
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008105 {
8106 LocalContext env(NULL, instance_template);
8107 // Hold on to the global object so it can be used again in another
8108 // environment initialization.
8109 global_object = env->Global();
8110
8111 Local<Value> value = Script::Compile(v8_str("x"))->Run();
8112 CHECK_EQ(42, value->Int32Value());
8113 value = Script::Compile(v8_str("f()"))->Run();
8114 CHECK_EQ(12, value->Int32Value());
kasperl@chromium.orga5551262010-12-07 12:49:48 +00008115 value = Script::Compile(v8_str(script))->Run();
8116 CHECK_EQ(1, value->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008117 }
8118
8119 {
8120 // Create new environment reusing the global object.
8121 LocalContext env(NULL, instance_template, global_object);
8122 Local<Value> value = Script::Compile(v8_str("x"))->Run();
8123 CHECK_EQ(42, value->Int32Value());
8124 value = Script::Compile(v8_str("f()"))->Run();
8125 CHECK_EQ(12, value->Int32Value());
kasperl@chromium.orga5551262010-12-07 12:49:48 +00008126 value = Script::Compile(v8_str(script))->Run();
8127 CHECK_EQ(1, value->Int32Value());
8128 }
8129}
8130
8131
8132THREADED_TEST(CallKnownGlobalReceiver) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008133 v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
kasperl@chromium.orga5551262010-12-07 12:49:48 +00008134
8135 Local<Value> global_object;
8136
8137 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
8138 Local<ObjectTemplate> instance_template = t->InstanceTemplate();
8139
8140 // The script to check that we leave global object not
8141 // global object proxy on stack when we deoptimize from inside
8142 // arguments evaluation.
8143 // To provoke error we need to both force deoptimization
8144 // from arguments evaluation and to force CallIC to take
8145 // CallIC_Miss code path that can't cope with global proxy.
8146 const char* script =
8147 "function bar(x, y) { try { } finally { } }"
8148 "function baz(x) { try { } finally { } }"
8149 "function bom(x) { try { } finally { } }"
8150 "function foo(x) { bar([x], bom(2)); }"
8151 "for (var i = 0; i < 10000; i++) foo(1);"
8152 "foo";
8153
8154 Local<Value> foo;
8155 {
8156 LocalContext env(NULL, instance_template);
8157 // Hold on to the global object so it can be used again in another
8158 // environment initialization.
8159 global_object = env->Global();
8160 foo = Script::Compile(v8_str(script))->Run();
8161 }
8162
8163 {
8164 // Create new environment reusing the global object.
8165 LocalContext env(NULL, instance_template, global_object);
8166 env->Global()->Set(v8_str("foo"), foo);
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00008167 Script::Compile(v8_str("foo()"))->Run();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008168 }
8169}
8170
8171
8172static v8::Handle<Value> ShadowFunctionCallback(const v8::Arguments& args) {
8173 ApiTestFuzzer::Fuzz();
8174 return v8_num(42);
8175}
8176
8177
8178static int shadow_y;
8179static int shadow_y_setter_call_count;
8180static int shadow_y_getter_call_count;
8181
8182
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00008183static void ShadowYSetter(Local<String>, Local<Value>, const AccessorInfo&) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008184 shadow_y_setter_call_count++;
8185 shadow_y = 42;
8186}
8187
8188
8189static v8::Handle<Value> ShadowYGetter(Local<String> name,
8190 const AccessorInfo& info) {
8191 ApiTestFuzzer::Fuzz();
8192 shadow_y_getter_call_count++;
8193 return v8_num(shadow_y);
8194}
8195
8196
8197static v8::Handle<Value> ShadowIndexedGet(uint32_t index,
8198 const AccessorInfo& info) {
8199 return v8::Handle<Value>();
8200}
8201
8202
8203static v8::Handle<Value> ShadowNamedGet(Local<String> key,
8204 const AccessorInfo&) {
8205 return v8::Handle<Value>();
8206}
8207
8208
8209THREADED_TEST(ShadowObject) {
8210 shadow_y = shadow_y_setter_call_count = shadow_y_getter_call_count = 0;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008211 v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008212
8213 Local<ObjectTemplate> global_template = v8::ObjectTemplate::New();
8214 LocalContext context(NULL, global_template);
8215
8216 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
8217 t->InstanceTemplate()->SetNamedPropertyHandler(ShadowNamedGet);
8218 t->InstanceTemplate()->SetIndexedPropertyHandler(ShadowIndexedGet);
8219 Local<ObjectTemplate> proto = t->PrototypeTemplate();
8220 Local<ObjectTemplate> instance = t->InstanceTemplate();
8221
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008222 proto->Set(v8_str("f"),
mmassi@chromium.org49a44672012-12-04 13:52:03 +00008223 v8::FunctionTemplate::New(ShadowFunctionCallback, Local<Value>()));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008224 proto->Set(v8_str("x"), v8_num(12));
8225
8226 instance->SetAccessor(v8_str("y"), ShadowYGetter, ShadowYSetter);
8227
8228 Local<Value> o = t->GetFunction()->NewInstance();
8229 context->Global()->Set(v8_str("__proto__"), o);
8230
8231 Local<Value> value =
ricow@chromium.orgd2be9012011-06-01 06:00:58 +00008232 Script::Compile(v8_str("this.propertyIsEnumerable(0)"))->Run();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008233 CHECK(value->IsBoolean());
8234 CHECK(!value->BooleanValue());
8235
8236 value = Script::Compile(v8_str("x"))->Run();
8237 CHECK_EQ(12, value->Int32Value());
8238
8239 value = Script::Compile(v8_str("f()"))->Run();
8240 CHECK_EQ(42, value->Int32Value());
8241
mmassi@chromium.org7028c052012-06-13 11:51:58 +00008242 Script::Compile(v8_str("y = 43"))->Run();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008243 CHECK_EQ(1, shadow_y_setter_call_count);
8244 value = Script::Compile(v8_str("y"))->Run();
8245 CHECK_EQ(1, shadow_y_getter_call_count);
8246 CHECK_EQ(42, value->Int32Value());
8247}
8248
8249
8250THREADED_TEST(HiddenPrototype) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008251 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008252 v8::HandleScope handle_scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008253
8254 Local<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New();
8255 t0->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
8256 Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New();
8257 t1->SetHiddenPrototype(true);
8258 t1->InstanceTemplate()->Set(v8_str("y"), v8_num(1));
8259 Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New();
8260 t2->SetHiddenPrototype(true);
8261 t2->InstanceTemplate()->Set(v8_str("z"), v8_num(2));
8262 Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New();
8263 t3->InstanceTemplate()->Set(v8_str("u"), v8_num(3));
8264
8265 Local<v8::Object> o0 = t0->GetFunction()->NewInstance();
8266 Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
8267 Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
8268 Local<v8::Object> o3 = t3->GetFunction()->NewInstance();
8269
8270 // Setting the prototype on an object skips hidden prototypes.
8271 CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
8272 o0->Set(v8_str("__proto__"), o1);
8273 CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
8274 CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
8275 o0->Set(v8_str("__proto__"), o2);
8276 CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
8277 CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
8278 CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
8279 o0->Set(v8_str("__proto__"), o3);
8280 CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
8281 CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
8282 CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
8283 CHECK_EQ(3, o0->Get(v8_str("u"))->Int32Value());
8284
8285 // Getting the prototype of o0 should get the first visible one
8286 // which is o3. Therefore, z should not be defined on the prototype
8287 // object.
8288 Local<Value> proto = o0->Get(v8_str("__proto__"));
8289 CHECK(proto->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00008290 CHECK(proto.As<v8::Object>()->Get(v8_str("z"))->IsUndefined());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008291}
8292
8293
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00008294THREADED_TEST(HiddenPrototypeSet) {
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00008295 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008296 v8::HandleScope handle_scope(context->GetIsolate());
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00008297
8298 Local<v8::FunctionTemplate> ot = v8::FunctionTemplate::New();
8299 Local<v8::FunctionTemplate> ht = v8::FunctionTemplate::New();
8300 ht->SetHiddenPrototype(true);
8301 Local<v8::FunctionTemplate> pt = v8::FunctionTemplate::New();
8302 ht->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
8303
8304 Local<v8::Object> o = ot->GetFunction()->NewInstance();
8305 Local<v8::Object> h = ht->GetFunction()->NewInstance();
8306 Local<v8::Object> p = pt->GetFunction()->NewInstance();
8307 o->Set(v8_str("__proto__"), h);
8308 h->Set(v8_str("__proto__"), p);
8309
8310 // Setting a property that exists on the hidden prototype goes there.
8311 o->Set(v8_str("x"), v8_num(7));
8312 CHECK_EQ(7, o->Get(v8_str("x"))->Int32Value());
8313 CHECK_EQ(7, h->Get(v8_str("x"))->Int32Value());
8314 CHECK(p->Get(v8_str("x"))->IsUndefined());
8315
8316 // Setting a new property should not be forwarded to the hidden prototype.
8317 o->Set(v8_str("y"), v8_num(6));
8318 CHECK_EQ(6, o->Get(v8_str("y"))->Int32Value());
8319 CHECK(h->Get(v8_str("y"))->IsUndefined());
8320 CHECK(p->Get(v8_str("y"))->IsUndefined());
8321
8322 // Setting a property that only exists on a prototype of the hidden prototype
8323 // is treated normally again.
8324 p->Set(v8_str("z"), v8_num(8));
8325 CHECK_EQ(8, o->Get(v8_str("z"))->Int32Value());
8326 CHECK_EQ(8, h->Get(v8_str("z"))->Int32Value());
8327 CHECK_EQ(8, p->Get(v8_str("z"))->Int32Value());
8328 o->Set(v8_str("z"), v8_num(9));
8329 CHECK_EQ(9, o->Get(v8_str("z"))->Int32Value());
8330 CHECK_EQ(8, h->Get(v8_str("z"))->Int32Value());
8331 CHECK_EQ(8, p->Get(v8_str("z"))->Int32Value());
8332}
8333
8334
8335// Regression test for issue 2457.
8336THREADED_TEST(HiddenPrototypeIdentityHash) {
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00008337 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008338 v8::HandleScope handle_scope(context->GetIsolate());
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00008339
8340 Handle<FunctionTemplate> t = FunctionTemplate::New();
8341 t->SetHiddenPrototype(true);
8342 t->InstanceTemplate()->Set(v8_str("foo"), v8_num(75));
8343 Handle<Object> p = t->GetFunction()->NewInstance();
8344 Handle<Object> o = Object::New();
8345 o->SetPrototype(p);
8346
8347 int hash = o->GetIdentityHash();
8348 USE(hash);
8349 o->Set(v8_str("foo"), v8_num(42));
8350 ASSERT_EQ(hash, o->GetIdentityHash());
8351}
8352
8353
ager@chromium.org5c838252010-02-19 08:53:10 +00008354THREADED_TEST(SetPrototype) {
ager@chromium.org5c838252010-02-19 08:53:10 +00008355 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008356 v8::HandleScope handle_scope(context->GetIsolate());
ager@chromium.org5c838252010-02-19 08:53:10 +00008357
8358 Local<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New();
8359 t0->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
8360 Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New();
8361 t1->SetHiddenPrototype(true);
8362 t1->InstanceTemplate()->Set(v8_str("y"), v8_num(1));
8363 Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New();
8364 t2->SetHiddenPrototype(true);
8365 t2->InstanceTemplate()->Set(v8_str("z"), v8_num(2));
8366 Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New();
8367 t3->InstanceTemplate()->Set(v8_str("u"), v8_num(3));
8368
8369 Local<v8::Object> o0 = t0->GetFunction()->NewInstance();
8370 Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
8371 Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
8372 Local<v8::Object> o3 = t3->GetFunction()->NewInstance();
8373
8374 // Setting the prototype on an object does not skip hidden prototypes.
8375 CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
8376 CHECK(o0->SetPrototype(o1));
8377 CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
8378 CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
8379 CHECK(o1->SetPrototype(o2));
8380 CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
8381 CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
8382 CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
8383 CHECK(o2->SetPrototype(o3));
8384 CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
8385 CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
8386 CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
8387 CHECK_EQ(3, o0->Get(v8_str("u"))->Int32Value());
8388
8389 // Getting the prototype of o0 should get the first visible one
8390 // which is o3. Therefore, z should not be defined on the prototype
8391 // object.
8392 Local<Value> proto = o0->Get(v8_str("__proto__"));
8393 CHECK(proto->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00008394 CHECK_EQ(proto.As<v8::Object>(), o3);
ager@chromium.org5c838252010-02-19 08:53:10 +00008395
8396 // However, Object::GetPrototype ignores hidden prototype.
8397 Local<Value> proto0 = o0->GetPrototype();
8398 CHECK(proto0->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00008399 CHECK_EQ(proto0.As<v8::Object>(), o1);
ager@chromium.org5c838252010-02-19 08:53:10 +00008400
8401 Local<Value> proto1 = o1->GetPrototype();
8402 CHECK(proto1->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00008403 CHECK_EQ(proto1.As<v8::Object>(), o2);
ager@chromium.org5c838252010-02-19 08:53:10 +00008404
8405 Local<Value> proto2 = o2->GetPrototype();
8406 CHECK(proto2->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00008407 CHECK_EQ(proto2.As<v8::Object>(), o3);
ager@chromium.org5c838252010-02-19 08:53:10 +00008408}
8409
8410
ricow@chromium.org27bf2882011-11-17 08:34:43 +00008411// Getting property names of an object with a prototype chain that
8412// triggers dictionary elements in GetLocalPropertyNames() shouldn't
8413// crash the runtime.
8414THREADED_TEST(Regress91517) {
8415 i::FLAG_allow_natives_syntax = true;
ricow@chromium.org27bf2882011-11-17 08:34:43 +00008416 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008417 v8::HandleScope handle_scope(context->GetIsolate());
ricow@chromium.org27bf2882011-11-17 08:34:43 +00008418
8419 Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New();
8420 t1->SetHiddenPrototype(true);
8421 t1->InstanceTemplate()->Set(v8_str("foo"), v8_num(1));
8422 Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New();
8423 t2->SetHiddenPrototype(true);
8424 t2->InstanceTemplate()->Set(v8_str("fuz1"), v8_num(2));
8425 t2->InstanceTemplate()->Set(v8_str("objects"), v8::Object::New());
8426 t2->InstanceTemplate()->Set(v8_str("fuz2"), v8_num(2));
8427 Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New();
8428 t3->SetHiddenPrototype(true);
8429 t3->InstanceTemplate()->Set(v8_str("boo"), v8_num(3));
8430 Local<v8::FunctionTemplate> t4 = v8::FunctionTemplate::New();
8431 t4->InstanceTemplate()->Set(v8_str("baz"), v8_num(4));
8432
8433 // Force dictionary-based properties.
8434 i::ScopedVector<char> name_buf(1024);
8435 for (int i = 1; i <= 1000; i++) {
8436 i::OS::SNPrintF(name_buf, "sdf%d", i);
8437 t2->InstanceTemplate()->Set(v8_str(name_buf.start()), v8_num(2));
8438 }
8439
8440 Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
8441 Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
8442 Local<v8::Object> o3 = t3->GetFunction()->NewInstance();
8443 Local<v8::Object> o4 = t4->GetFunction()->NewInstance();
8444
8445 // Create prototype chain of hidden prototypes.
8446 CHECK(o4->SetPrototype(o3));
8447 CHECK(o3->SetPrototype(o2));
8448 CHECK(o2->SetPrototype(o1));
8449
8450 // Call the runtime version of GetLocalPropertyNames() on the natively
8451 // created object through JavaScript.
8452 context->Global()->Set(v8_str("obj"), o4);
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +00008453 CompileRun("var names = %GetLocalPropertyNames(obj, true);");
ricow@chromium.org27bf2882011-11-17 08:34:43 +00008454
8455 ExpectInt32("names.length", 1006);
8456 ExpectTrue("names.indexOf(\"baz\") >= 0");
8457 ExpectTrue("names.indexOf(\"boo\") >= 0");
8458 ExpectTrue("names.indexOf(\"foo\") >= 0");
8459 ExpectTrue("names.indexOf(\"fuz1\") >= 0");
8460 ExpectTrue("names.indexOf(\"fuz2\") >= 0");
8461 ExpectFalse("names[1005] == undefined");
8462}
8463
8464
ricow@chromium.org2c99e282011-07-28 09:15:17 +00008465THREADED_TEST(FunctionReadOnlyPrototype) {
ager@chromium.org04921a82011-06-27 13:21:41 +00008466 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008467 v8::HandleScope handle_scope(context->GetIsolate());
ager@chromium.org04921a82011-06-27 13:21:41 +00008468
8469 Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New();
ricow@chromium.org2c99e282011-07-28 09:15:17 +00008470 t1->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(42));
8471 t1->ReadOnlyPrototype();
ager@chromium.org04921a82011-06-27 13:21:41 +00008472 context->Global()->Set(v8_str("func1"), t1->GetFunction());
ricow@chromium.org2c99e282011-07-28 09:15:17 +00008473 // Configured value of ReadOnly flag.
ager@chromium.org04921a82011-06-27 13:21:41 +00008474 CHECK(CompileRun(
8475 "(function() {"
8476 " descriptor = Object.getOwnPropertyDescriptor(func1, 'prototype');"
ricow@chromium.org2c99e282011-07-28 09:15:17 +00008477 " return (descriptor['writable'] == false);"
ager@chromium.org04921a82011-06-27 13:21:41 +00008478 "})()")->BooleanValue());
ricow@chromium.org2c99e282011-07-28 09:15:17 +00008479 CHECK_EQ(42, CompileRun("func1.prototype.x")->Int32Value());
8480 CHECK_EQ(42,
8481 CompileRun("func1.prototype = {}; func1.prototype.x")->Int32Value());
ager@chromium.org04921a82011-06-27 13:21:41 +00008482
8483 Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New();
ricow@chromium.org2c99e282011-07-28 09:15:17 +00008484 t2->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(42));
ager@chromium.org04921a82011-06-27 13:21:41 +00008485 context->Global()->Set(v8_str("func2"), t2->GetFunction());
ricow@chromium.org2c99e282011-07-28 09:15:17 +00008486 // Default value of ReadOnly flag.
ager@chromium.org04921a82011-06-27 13:21:41 +00008487 CHECK(CompileRun(
8488 "(function() {"
8489 " descriptor = Object.getOwnPropertyDescriptor(func2, 'prototype');"
ricow@chromium.org2c99e282011-07-28 09:15:17 +00008490 " return (descriptor['writable'] == true);"
ager@chromium.org04921a82011-06-27 13:21:41 +00008491 "})()")->BooleanValue());
ricow@chromium.org2c99e282011-07-28 09:15:17 +00008492 CHECK_EQ(42, CompileRun("func2.prototype.x")->Int32Value());
ager@chromium.org04921a82011-06-27 13:21:41 +00008493}
8494
8495
ager@chromium.org5c838252010-02-19 08:53:10 +00008496THREADED_TEST(SetPrototypeThrows) {
ager@chromium.org5c838252010-02-19 08:53:10 +00008497 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008498 v8::HandleScope handle_scope(context->GetIsolate());
ager@chromium.org5c838252010-02-19 08:53:10 +00008499
8500 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
8501
8502 Local<v8::Object> o0 = t->GetFunction()->NewInstance();
8503 Local<v8::Object> o1 = t->GetFunction()->NewInstance();
8504
8505 CHECK(o0->SetPrototype(o1));
8506 // If setting the prototype leads to the cycle, SetPrototype should
8507 // return false and keep VM in sane state.
8508 v8::TryCatch try_catch;
8509 CHECK(!o1->SetPrototype(o0));
8510 CHECK(!try_catch.HasCaught());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00008511 ASSERT(!i::Isolate::Current()->has_pending_exception());
ager@chromium.org5c838252010-02-19 08:53:10 +00008512
8513 CHECK_EQ(42, CompileRun("function f() { return 42; }; f()")->Int32Value());
8514}
8515
8516
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008517THREADED_TEST(GetterSetterExceptions) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008518 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008519 v8::HandleScope handle_scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008520 CompileRun(
8521 "function Foo() { };"
8522 "function Throw() { throw 5; };"
8523 "var x = { };"
8524 "x.__defineSetter__('set', Throw);"
8525 "x.__defineGetter__('get', Throw);");
8526 Local<v8::Object> x =
8527 Local<v8::Object>::Cast(context->Global()->Get(v8_str("x")));
8528 v8::TryCatch try_catch;
8529 x->Set(v8_str("set"), v8::Integer::New(8));
8530 x->Get(v8_str("get"));
8531 x->Set(v8_str("set"), v8::Integer::New(8));
8532 x->Get(v8_str("get"));
8533 x->Set(v8_str("set"), v8::Integer::New(8));
8534 x->Get(v8_str("get"));
8535 x->Set(v8_str("set"), v8::Integer::New(8));
8536 x->Get(v8_str("get"));
8537}
8538
8539
8540THREADED_TEST(Constructor) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008541 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008542 v8::HandleScope handle_scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008543 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
8544 templ->SetClassName(v8_str("Fun"));
8545 Local<Function> cons = templ->GetFunction();
8546 context->Global()->Set(v8_str("Fun"), cons);
8547 Local<v8::Object> inst = cons->NewInstance();
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00008548 i::Handle<i::JSObject> obj(v8::Utils::OpenHandle(*inst));
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00008549 CHECK(obj->IsJSObject());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008550 Local<Value> value = CompileRun("(new Fun()).constructor === Fun");
8551 CHECK(value->BooleanValue());
8552}
8553
lrn@chromium.org1c092762011-05-09 09:42:16 +00008554
8555static Handle<Value> ConstructorCallback(const Arguments& args) {
8556 ApiTestFuzzer::Fuzz();
8557 Local<Object> This;
8558
8559 if (args.IsConstructCall()) {
8560 Local<Object> Holder = args.Holder();
8561 This = Object::New();
8562 Local<Value> proto = Holder->GetPrototype();
8563 if (proto->IsObject()) {
8564 This->SetPrototype(proto);
8565 }
8566 } else {
8567 This = args.This();
8568 }
8569
8570 This->Set(v8_str("a"), args[0]);
8571 return This;
8572}
8573
8574
8575static Handle<Value> FakeConstructorCallback(const Arguments& args) {
8576 ApiTestFuzzer::Fuzz();
8577 return args[0];
8578}
8579
8580
8581THREADED_TEST(ConstructorForObject) {
lrn@chromium.org1c092762011-05-09 09:42:16 +00008582 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008583 v8::HandleScope handle_scope(context->GetIsolate());
lrn@chromium.org1c092762011-05-09 09:42:16 +00008584
8585 { Local<ObjectTemplate> instance_template = ObjectTemplate::New();
8586 instance_template->SetCallAsFunctionHandler(ConstructorCallback);
8587 Local<Object> instance = instance_template->NewInstance();
8588 context->Global()->Set(v8_str("obj"), instance);
8589 v8::TryCatch try_catch;
8590 Local<Value> value;
8591 CHECK(!try_catch.HasCaught());
8592
8593 // Call the Object's constructor with a 32-bit signed integer.
8594 value = CompileRun("(function() { var o = new obj(28); return o.a; })()");
8595 CHECK(!try_catch.HasCaught());
8596 CHECK(value->IsInt32());
8597 CHECK_EQ(28, value->Int32Value());
8598
8599 Local<Value> args1[] = { v8_num(28) };
8600 Local<Value> value_obj1 = instance->CallAsConstructor(1, args1);
8601 CHECK(value_obj1->IsObject());
8602 Local<Object> object1 = Local<Object>::Cast(value_obj1);
8603 value = object1->Get(v8_str("a"));
8604 CHECK(value->IsInt32());
8605 CHECK(!try_catch.HasCaught());
8606 CHECK_EQ(28, value->Int32Value());
8607
8608 // Call the Object's constructor with a String.
8609 value = CompileRun(
8610 "(function() { var o = new obj('tipli'); return o.a; })()");
8611 CHECK(!try_catch.HasCaught());
8612 CHECK(value->IsString());
8613 String::AsciiValue string_value1(value->ToString());
8614 CHECK_EQ("tipli", *string_value1);
8615
8616 Local<Value> args2[] = { v8_str("tipli") };
8617 Local<Value> value_obj2 = instance->CallAsConstructor(1, args2);
8618 CHECK(value_obj2->IsObject());
8619 Local<Object> object2 = Local<Object>::Cast(value_obj2);
8620 value = object2->Get(v8_str("a"));
8621 CHECK(!try_catch.HasCaught());
8622 CHECK(value->IsString());
8623 String::AsciiValue string_value2(value->ToString());
8624 CHECK_EQ("tipli", *string_value2);
8625
8626 // Call the Object's constructor with a Boolean.
8627 value = CompileRun("(function() { var o = new obj(true); return o.a; })()");
8628 CHECK(!try_catch.HasCaught());
8629 CHECK(value->IsBoolean());
8630 CHECK_EQ(true, value->BooleanValue());
8631
yangguo@chromium.org80c42ed2011-08-31 09:03:56 +00008632 Handle<Value> args3[] = { v8::True() };
lrn@chromium.org1c092762011-05-09 09:42:16 +00008633 Local<Value> value_obj3 = instance->CallAsConstructor(1, args3);
8634 CHECK(value_obj3->IsObject());
8635 Local<Object> object3 = Local<Object>::Cast(value_obj3);
8636 value = object3->Get(v8_str("a"));
8637 CHECK(!try_catch.HasCaught());
8638 CHECK(value->IsBoolean());
8639 CHECK_EQ(true, value->BooleanValue());
8640
8641 // Call the Object's constructor with undefined.
8642 Handle<Value> args4[] = { v8::Undefined() };
8643 Local<Value> value_obj4 = instance->CallAsConstructor(1, args4);
8644 CHECK(value_obj4->IsObject());
8645 Local<Object> object4 = Local<Object>::Cast(value_obj4);
8646 value = object4->Get(v8_str("a"));
8647 CHECK(!try_catch.HasCaught());
8648 CHECK(value->IsUndefined());
8649
8650 // Call the Object's constructor with null.
8651 Handle<Value> args5[] = { v8::Null() };
8652 Local<Value> value_obj5 = instance->CallAsConstructor(1, args5);
8653 CHECK(value_obj5->IsObject());
8654 Local<Object> object5 = Local<Object>::Cast(value_obj5);
8655 value = object5->Get(v8_str("a"));
8656 CHECK(!try_catch.HasCaught());
8657 CHECK(value->IsNull());
8658 }
8659
8660 // Check exception handling when there is no constructor set for the Object.
8661 { Local<ObjectTemplate> instance_template = ObjectTemplate::New();
8662 Local<Object> instance = instance_template->NewInstance();
8663 context->Global()->Set(v8_str("obj2"), instance);
8664 v8::TryCatch try_catch;
8665 Local<Value> value;
8666 CHECK(!try_catch.HasCaught());
8667
8668 value = CompileRun("new obj2(28)");
8669 CHECK(try_catch.HasCaught());
8670 String::AsciiValue exception_value1(try_catch.Exception());
8671 CHECK_EQ("TypeError: object is not a function", *exception_value1);
8672 try_catch.Reset();
8673
8674 Local<Value> args[] = { v8_num(29) };
8675 value = instance->CallAsConstructor(1, args);
8676 CHECK(try_catch.HasCaught());
8677 String::AsciiValue exception_value2(try_catch.Exception());
8678 CHECK_EQ("TypeError: #<Object> is not a function", *exception_value2);
8679 try_catch.Reset();
8680 }
8681
8682 // Check the case when constructor throws exception.
8683 { Local<ObjectTemplate> instance_template = ObjectTemplate::New();
8684 instance_template->SetCallAsFunctionHandler(ThrowValue);
8685 Local<Object> instance = instance_template->NewInstance();
8686 context->Global()->Set(v8_str("obj3"), instance);
8687 v8::TryCatch try_catch;
8688 Local<Value> value;
8689 CHECK(!try_catch.HasCaught());
8690
8691 value = CompileRun("new obj3(22)");
8692 CHECK(try_catch.HasCaught());
8693 String::AsciiValue exception_value1(try_catch.Exception());
8694 CHECK_EQ("22", *exception_value1);
8695 try_catch.Reset();
8696
8697 Local<Value> args[] = { v8_num(23) };
8698 value = instance->CallAsConstructor(1, args);
8699 CHECK(try_catch.HasCaught());
8700 String::AsciiValue exception_value2(try_catch.Exception());
8701 CHECK_EQ("23", *exception_value2);
8702 try_catch.Reset();
8703 }
8704
8705 // Check whether constructor returns with an object or non-object.
8706 { Local<FunctionTemplate> function_template =
8707 FunctionTemplate::New(FakeConstructorCallback);
8708 Local<Function> function = function_template->GetFunction();
8709 Local<Object> instance1 = function;
8710 context->Global()->Set(v8_str("obj4"), instance1);
8711 v8::TryCatch try_catch;
8712 Local<Value> value;
8713 CHECK(!try_catch.HasCaught());
8714
8715 CHECK(instance1->IsObject());
8716 CHECK(instance1->IsFunction());
8717
8718 value = CompileRun("new obj4(28)");
8719 CHECK(!try_catch.HasCaught());
8720 CHECK(value->IsObject());
8721
8722 Local<Value> args1[] = { v8_num(28) };
8723 value = instance1->CallAsConstructor(1, args1);
8724 CHECK(!try_catch.HasCaught());
8725 CHECK(value->IsObject());
8726
8727 Local<ObjectTemplate> instance_template = ObjectTemplate::New();
8728 instance_template->SetCallAsFunctionHandler(FakeConstructorCallback);
8729 Local<Object> instance2 = instance_template->NewInstance();
8730 context->Global()->Set(v8_str("obj5"), instance2);
8731 CHECK(!try_catch.HasCaught());
8732
8733 CHECK(instance2->IsObject());
8734 CHECK(!instance2->IsFunction());
8735
8736 value = CompileRun("new obj5(28)");
8737 CHECK(!try_catch.HasCaught());
8738 CHECK(!value->IsObject());
8739
8740 Local<Value> args2[] = { v8_num(28) };
8741 value = instance2->CallAsConstructor(1, args2);
8742 CHECK(!try_catch.HasCaught());
8743 CHECK(!value->IsObject());
8744 }
8745}
8746
8747
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008748THREADED_TEST(FunctionDescriptorException) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008749 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008750 v8::HandleScope handle_scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008751 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
8752 templ->SetClassName(v8_str("Fun"));
8753 Local<Function> cons = templ->GetFunction();
8754 context->Global()->Set(v8_str("Fun"), cons);
8755 Local<Value> value = CompileRun(
8756 "function test() {"
8757 " try {"
8758 " (new Fun()).blah()"
8759 " } catch (e) {"
8760 " var str = String(e);"
8761 " if (str.indexOf('TypeError') == -1) return 1;"
8762 " if (str.indexOf('[object Fun]') != -1) return 2;"
whesse@chromium.org7a392b32011-01-31 11:30:36 +00008763 " if (str.indexOf('#<Fun>') == -1) return 3;"
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008764 " return 0;"
8765 " }"
8766 " return 4;"
8767 "}"
8768 "test();");
8769 CHECK_EQ(0, value->Int32Value());
8770}
8771
8772
ager@chromium.orga74f0da2008-12-03 16:05:52 +00008773THREADED_TEST(EvalAliasedDynamic) {
ager@chromium.orga74f0da2008-12-03 16:05:52 +00008774 LocalContext current;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008775 v8::HandleScope scope(current->GetIsolate());
ager@chromium.orga74f0da2008-12-03 16:05:52 +00008776
ager@chromium.orga74f0da2008-12-03 16:05:52 +00008777 // Tests where aliased eval can only be resolved dynamically.
8778 Local<Script> script =
8779 Script::Compile(v8_str("function f(x) { "
8780 " var foo = 2;"
8781 " with (x) { return eval('foo'); }"
8782 "}"
8783 "foo = 0;"
8784 "result1 = f(new Object());"
ager@chromium.orge2902be2009-06-08 12:21:35 +00008785 "result2 = f(this);"
ager@chromium.orga74f0da2008-12-03 16:05:52 +00008786 "var x = new Object();"
8787 "x.eval = function(x) { return 1; };"
8788 "result3 = f(x);"));
8789 script->Run();
8790 CHECK_EQ(2, current->Global()->Get(v8_str("result1"))->Int32Value());
8791 CHECK_EQ(0, current->Global()->Get(v8_str("result2"))->Int32Value());
8792 CHECK_EQ(1, current->Global()->Get(v8_str("result3"))->Int32Value());
8793
8794 v8::TryCatch try_catch;
8795 script =
8796 Script::Compile(v8_str("function f(x) { "
8797 " var bar = 2;"
8798 " with (x) { return eval('bar'); }"
8799 "}"
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00008800 "result4 = f(this)"));
ager@chromium.orga74f0da2008-12-03 16:05:52 +00008801 script->Run();
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00008802 CHECK(!try_catch.HasCaught());
8803 CHECK_EQ(2, current->Global()->Get(v8_str("result4"))->Int32Value());
8804
ager@chromium.orga74f0da2008-12-03 16:05:52 +00008805 try_catch.Reset();
8806}
8807
8808
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008809THREADED_TEST(CrossEval) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008810 v8::HandleScope scope(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008811 LocalContext other;
8812 LocalContext current;
8813
8814 Local<String> token = v8_str("<security token>");
8815 other->SetSecurityToken(token);
8816 current->SetSecurityToken(token);
8817
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00008818 // Set up reference from current to other.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008819 current->Global()->Set(v8_str("other"), other->Global());
8820
8821 // Check that new variables are introduced in other context.
8822 Local<Script> script =
8823 Script::Compile(v8_str("other.eval('var foo = 1234')"));
8824 script->Run();
8825 Local<Value> foo = other->Global()->Get(v8_str("foo"));
8826 CHECK_EQ(1234, foo->Int32Value());
8827 CHECK(!current->Global()->Has(v8_str("foo")));
8828
8829 // Check that writing to non-existing properties introduces them in
ager@chromium.orga74f0da2008-12-03 16:05:52 +00008830 // the other context.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008831 script =
8832 Script::Compile(v8_str("other.eval('na = 1234')"));
8833 script->Run();
ager@chromium.orga74f0da2008-12-03 16:05:52 +00008834 CHECK_EQ(1234, other->Global()->Get(v8_str("na"))->Int32Value());
8835 CHECK(!current->Global()->Has(v8_str("na")));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008836
ager@chromium.orga74f0da2008-12-03 16:05:52 +00008837 // Check that global variables in current context are not visible in other
8838 // context.
8839 v8::TryCatch try_catch;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008840 script =
ager@chromium.orga74f0da2008-12-03 16:05:52 +00008841 Script::Compile(v8_str("var bar = 42; other.eval('bar');"));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008842 Local<Value> result = script->Run();
ager@chromium.orga74f0da2008-12-03 16:05:52 +00008843 CHECK(try_catch.HasCaught());
8844 try_catch.Reset();
8845
8846 // Check that local variables in current context are not visible in other
8847 // context.
8848 script =
8849 Script::Compile(v8_str("(function() { "
8850 " var baz = 87;"
8851 " return other.eval('baz');"
8852 "})();"));
8853 result = script->Run();
8854 CHECK(try_catch.HasCaught());
8855 try_catch.Reset();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008856
8857 // Check that global variables in the other environment are visible
8858 // when evaluting code.
8859 other->Global()->Set(v8_str("bis"), v8_num(1234));
8860 script = Script::Compile(v8_str("other.eval('bis')"));
8861 CHECK_EQ(1234, script->Run()->Int32Value());
ager@chromium.orga74f0da2008-12-03 16:05:52 +00008862 CHECK(!try_catch.HasCaught());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008863
ager@chromium.orga74f0da2008-12-03 16:05:52 +00008864 // Check that the 'this' pointer points to the global object evaluating
8865 // code.
8866 other->Global()->Set(v8_str("t"), other->Global());
8867 script = Script::Compile(v8_str("other.eval('this == t')"));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008868 result = script->Run();
ager@chromium.orga74f0da2008-12-03 16:05:52 +00008869 CHECK(result->IsTrue());
8870 CHECK(!try_catch.HasCaught());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008871
ager@chromium.orga74f0da2008-12-03 16:05:52 +00008872 // Check that variables introduced in with-statement are not visible in
8873 // other context.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008874 script =
ager@chromium.orga74f0da2008-12-03 16:05:52 +00008875 Script::Compile(v8_str("with({x:2}){other.eval('x')}"));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008876 result = script->Run();
ager@chromium.orga74f0da2008-12-03 16:05:52 +00008877 CHECK(try_catch.HasCaught());
8878 try_catch.Reset();
ager@chromium.org3bf7b912008-11-17 09:09:45 +00008879
8880 // Check that you cannot use 'eval.call' with another object than the
8881 // current global object.
ager@chromium.org3bf7b912008-11-17 09:09:45 +00008882 script =
8883 Script::Compile(v8_str("other.y = 1; eval.call(other, 'y')"));
8884 result = script->Run();
8885 CHECK(try_catch.HasCaught());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008886}
8887
8888
ager@chromium.orge2902be2009-06-08 12:21:35 +00008889// Test that calling eval in a context which has been detached from
8890// its global throws an exception. This behavior is consistent with
8891// other JavaScript implementations.
8892THREADED_TEST(EvalInDetachedGlobal) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008893 v8::HandleScope scope(v8::Isolate::GetCurrent());
ager@chromium.orge2902be2009-06-08 12:21:35 +00008894
8895 v8::Persistent<Context> context0 = Context::New();
8896 v8::Persistent<Context> context1 = Context::New();
8897
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00008898 // Set up function in context0 that uses eval from context0.
ager@chromium.orge2902be2009-06-08 12:21:35 +00008899 context0->Enter();
8900 v8::Handle<v8::Value> fun =
8901 CompileRun("var x = 42;"
8902 "(function() {"
8903 " var e = eval;"
8904 " return function(s) { return e(s); }"
8905 "})()");
8906 context0->Exit();
8907
8908 // Put the function into context1 and call it before and after
8909 // detaching the global. Before detaching, the call succeeds and
8910 // after detaching and exception is thrown.
8911 context1->Enter();
8912 context1->Global()->Set(v8_str("fun"), fun);
8913 v8::Handle<v8::Value> x_value = CompileRun("fun('x')");
8914 CHECK_EQ(42, x_value->Int32Value());
8915 context0->DetachGlobal();
8916 v8::TryCatch catcher;
8917 x_value = CompileRun("fun('x')");
8918 CHECK(x_value.IsEmpty());
8919 CHECK(catcher.HasCaught());
8920 context1->Exit();
8921
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00008922 context1.Dispose(context1->GetIsolate());
8923 context0.Dispose(context0->GetIsolate());
ager@chromium.orge2902be2009-06-08 12:21:35 +00008924}
8925
8926
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008927THREADED_TEST(CrossLazyLoad) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008928 v8::HandleScope scope(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008929 LocalContext other;
8930 LocalContext current;
8931
8932 Local<String> token = v8_str("<security token>");
8933 other->SetSecurityToken(token);
8934 current->SetSecurityToken(token);
8935
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00008936 // Set up reference from current to other.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008937 current->Global()->Set(v8_str("other"), other->Global());
8938
8939 // Trigger lazy loading in other context.
8940 Local<Script> script =
8941 Script::Compile(v8_str("other.eval('new Date(42)')"));
8942 Local<Value> value = script->Run();
8943 CHECK_EQ(42.0, value->NumberValue());
8944}
8945
8946
8947static v8::Handle<Value> call_as_function(const v8::Arguments& args) {
8948 ApiTestFuzzer::Fuzz();
sgjesse@chromium.org05521fc2009-05-21 07:37:44 +00008949 if (args.IsConstructCall()) {
8950 if (args[0]->IsInt32()) {
8951 return v8_num(-args[0]->Int32Value());
8952 }
8953 }
8954
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008955 return args[0];
8956}
8957
8958
8959// Test that a call handler can be set for objects which will allow
8960// non-function objects created through the API to be called as
8961// functions.
8962THREADED_TEST(CallAsFunction) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008963 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008964 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008965
lrn@chromium.org1c092762011-05-09 09:42:16 +00008966 { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
8967 Local<ObjectTemplate> instance_template = t->InstanceTemplate();
8968 instance_template->SetCallAsFunctionHandler(call_as_function);
8969 Local<v8::Object> instance = t->GetFunction()->NewInstance();
8970 context->Global()->Set(v8_str("obj"), instance);
8971 v8::TryCatch try_catch;
8972 Local<Value> value;
8973 CHECK(!try_catch.HasCaught());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008974
lrn@chromium.org1c092762011-05-09 09:42:16 +00008975 value = CompileRun("obj(42)");
8976 CHECK(!try_catch.HasCaught());
8977 CHECK_EQ(42, value->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008978
lrn@chromium.org1c092762011-05-09 09:42:16 +00008979 value = CompileRun("(function(o){return o(49)})(obj)");
8980 CHECK(!try_catch.HasCaught());
8981 CHECK_EQ(49, value->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008982
lrn@chromium.org1c092762011-05-09 09:42:16 +00008983 // test special case of call as function
8984 value = CompileRun("[obj]['0'](45)");
8985 CHECK(!try_catch.HasCaught());
8986 CHECK_EQ(45, value->Int32Value());
ager@chromium.org9258b6b2008-09-11 09:11:10 +00008987
lrn@chromium.org1c092762011-05-09 09:42:16 +00008988 value = CompileRun("obj.call = Function.prototype.call;"
8989 "obj.call(null, 87)");
8990 CHECK(!try_catch.HasCaught());
8991 CHECK_EQ(87, value->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008992
lrn@chromium.org1c092762011-05-09 09:42:16 +00008993 // Regression tests for bug #1116356: Calling call through call/apply
8994 // must work for non-function receivers.
8995 const char* apply_99 = "Function.prototype.call.apply(obj, [this, 99])";
8996 value = CompileRun(apply_99);
8997 CHECK(!try_catch.HasCaught());
8998 CHECK_EQ(99, value->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008999
lrn@chromium.org1c092762011-05-09 09:42:16 +00009000 const char* call_17 = "Function.prototype.call.call(obj, this, 17)";
9001 value = CompileRun(call_17);
9002 CHECK(!try_catch.HasCaught());
9003 CHECK_EQ(17, value->Int32Value());
ager@chromium.org9085a012009-05-11 19:22:57 +00009004
lrn@chromium.org1c092762011-05-09 09:42:16 +00009005 // Check that the call-as-function handler can be called through
9006 // new.
9007 value = CompileRun("new obj(43)");
9008 CHECK(!try_catch.HasCaught());
9009 CHECK_EQ(-43, value->Int32Value());
9010
9011 // Check that the call-as-function handler can be called through
9012 // the API.
9013 v8::Handle<Value> args[] = { v8_num(28) };
9014 value = instance->CallAsFunction(instance, 1, args);
9015 CHECK(!try_catch.HasCaught());
9016 CHECK_EQ(28, value->Int32Value());
9017 }
9018
9019 { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00009020 Local<ObjectTemplate> instance_template(t->InstanceTemplate());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00009021 USE(instance_template);
lrn@chromium.org1c092762011-05-09 09:42:16 +00009022 Local<v8::Object> instance = t->GetFunction()->NewInstance();
9023 context->Global()->Set(v8_str("obj2"), instance);
9024 v8::TryCatch try_catch;
9025 Local<Value> value;
9026 CHECK(!try_catch.HasCaught());
9027
9028 // Call an object without call-as-function handler through the JS
9029 value = CompileRun("obj2(28)");
9030 CHECK(value.IsEmpty());
9031 CHECK(try_catch.HasCaught());
9032 String::AsciiValue exception_value1(try_catch.Exception());
9033 CHECK_EQ("TypeError: Property 'obj2' of object #<Object> is not a function",
9034 *exception_value1);
9035 try_catch.Reset();
9036
9037 // Call an object without call-as-function handler through the API
9038 value = CompileRun("obj2(28)");
9039 v8::Handle<Value> args[] = { v8_num(28) };
9040 value = instance->CallAsFunction(instance, 1, args);
9041 CHECK(value.IsEmpty());
9042 CHECK(try_catch.HasCaught());
9043 String::AsciiValue exception_value2(try_catch.Exception());
9044 CHECK_EQ("TypeError: [object Object] is not a function", *exception_value2);
9045 try_catch.Reset();
9046 }
9047
9048 { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
9049 Local<ObjectTemplate> instance_template = t->InstanceTemplate();
9050 instance_template->SetCallAsFunctionHandler(ThrowValue);
9051 Local<v8::Object> instance = t->GetFunction()->NewInstance();
9052 context->Global()->Set(v8_str("obj3"), instance);
9053 v8::TryCatch try_catch;
9054 Local<Value> value;
9055 CHECK(!try_catch.HasCaught());
9056
9057 // Catch the exception which is thrown by call-as-function handler
9058 value = CompileRun("obj3(22)");
9059 CHECK(try_catch.HasCaught());
9060 String::AsciiValue exception_value1(try_catch.Exception());
9061 CHECK_EQ("22", *exception_value1);
9062 try_catch.Reset();
9063
9064 v8::Handle<Value> args[] = { v8_num(23) };
9065 value = instance->CallAsFunction(instance, 1, args);
9066 CHECK(try_catch.HasCaught());
9067 String::AsciiValue exception_value2(try_catch.Exception());
9068 CHECK_EQ("23", *exception_value2);
9069 try_catch.Reset();
9070 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009071}
9072
9073
karlklose@chromium.org83a47282011-05-11 11:54:09 +00009074// Check whether a non-function object is callable.
9075THREADED_TEST(CallableObject) {
karlklose@chromium.org83a47282011-05-11 11:54:09 +00009076 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00009077 v8::HandleScope scope(context->GetIsolate());
karlklose@chromium.org83a47282011-05-11 11:54:09 +00009078
9079 { Local<ObjectTemplate> instance_template = ObjectTemplate::New();
9080 instance_template->SetCallAsFunctionHandler(call_as_function);
9081 Local<Object> instance = instance_template->NewInstance();
9082 v8::TryCatch try_catch;
9083
9084 CHECK(instance->IsCallable());
9085 CHECK(!try_catch.HasCaught());
9086 }
9087
9088 { Local<ObjectTemplate> instance_template = ObjectTemplate::New();
9089 Local<Object> instance = instance_template->NewInstance();
9090 v8::TryCatch try_catch;
9091
9092 CHECK(!instance->IsCallable());
9093 CHECK(!try_catch.HasCaught());
9094 }
9095
9096 { Local<FunctionTemplate> function_template =
9097 FunctionTemplate::New(call_as_function);
9098 Local<Function> function = function_template->GetFunction();
9099 Local<Object> instance = function;
9100 v8::TryCatch try_catch;
9101
9102 CHECK(instance->IsCallable());
9103 CHECK(!try_catch.HasCaught());
9104 }
9105
9106 { Local<FunctionTemplate> function_template = FunctionTemplate::New();
9107 Local<Function> function = function_template->GetFunction();
9108 Local<Object> instance = function;
9109 v8::TryCatch try_catch;
9110
9111 CHECK(instance->IsCallable());
9112 CHECK(!try_catch.HasCaught());
9113 }
9114}
9115
9116
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009117static int CountHandles() {
9118 return v8::HandleScope::NumberOfHandles();
9119}
9120
9121
9122static int Recurse(int depth, int iterations) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00009123 v8::HandleScope scope(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009124 if (depth == 0) return CountHandles();
9125 for (int i = 0; i < iterations; i++) {
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00009126 Local<v8::Number> n(v8::Integer::New(42));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009127 }
9128 return Recurse(depth - 1, iterations);
9129}
9130
9131
9132THREADED_TEST(HandleIteration) {
9133 static const int kIterations = 500;
9134 static const int kNesting = 200;
9135 CHECK_EQ(0, CountHandles());
9136 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00009137 v8::HandleScope scope1(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009138 CHECK_EQ(0, CountHandles());
9139 for (int i = 0; i < kIterations; i++) {
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00009140 Local<v8::Number> n(v8::Integer::New(42));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009141 CHECK_EQ(i + 1, CountHandles());
9142 }
9143
9144 CHECK_EQ(kIterations, CountHandles());
9145 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00009146 v8::HandleScope scope2(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009147 for (int j = 0; j < kIterations; j++) {
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00009148 Local<v8::Number> n(v8::Integer::New(42));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009149 CHECK_EQ(j + 1 + kIterations, CountHandles());
9150 }
9151 }
9152 CHECK_EQ(kIterations, CountHandles());
9153 }
9154 CHECK_EQ(0, CountHandles());
9155 CHECK_EQ(kNesting * kIterations, Recurse(kNesting, kIterations));
9156}
9157
9158
9159static v8::Handle<Value> InterceptorHasOwnPropertyGetter(
9160 Local<String> name,
9161 const AccessorInfo& info) {
9162 ApiTestFuzzer::Fuzz();
9163 return v8::Handle<Value>();
9164}
9165
9166
9167THREADED_TEST(InterceptorHasOwnProperty) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009168 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00009169 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009170 Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
9171 Local<v8::ObjectTemplate> instance_templ = fun_templ->InstanceTemplate();
9172 instance_templ->SetNamedPropertyHandler(InterceptorHasOwnPropertyGetter);
9173 Local<Function> function = fun_templ->GetFunction();
9174 context->Global()->Set(v8_str("constructor"), function);
9175 v8::Handle<Value> value = CompileRun(
9176 "var o = new constructor();"
9177 "o.hasOwnProperty('ostehaps');");
9178 CHECK_EQ(false, value->BooleanValue());
9179 value = CompileRun(
9180 "o.ostehaps = 42;"
9181 "o.hasOwnProperty('ostehaps');");
9182 CHECK_EQ(true, value->BooleanValue());
9183 value = CompileRun(
9184 "var p = new constructor();"
9185 "p.hasOwnProperty('ostehaps');");
9186 CHECK_EQ(false, value->BooleanValue());
9187}
9188
9189
ager@chromium.org9085a012009-05-11 19:22:57 +00009190static v8::Handle<Value> InterceptorHasOwnPropertyGetterGC(
9191 Local<String> name,
9192 const AccessorInfo& info) {
9193 ApiTestFuzzer::Fuzz();
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00009194 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org9085a012009-05-11 19:22:57 +00009195 return v8::Handle<Value>();
9196}
9197
9198
9199THREADED_TEST(InterceptorHasOwnPropertyCausingGC) {
ager@chromium.org9085a012009-05-11 19:22:57 +00009200 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00009201 v8::HandleScope scope(context->GetIsolate());
ager@chromium.org9085a012009-05-11 19:22:57 +00009202 Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
9203 Local<v8::ObjectTemplate> instance_templ = fun_templ->InstanceTemplate();
9204 instance_templ->SetNamedPropertyHandler(InterceptorHasOwnPropertyGetterGC);
9205 Local<Function> function = fun_templ->GetFunction();
9206 context->Global()->Set(v8_str("constructor"), function);
9207 // Let's first make some stuff so we can be sure to get a good GC.
9208 CompileRun(
9209 "function makestr(size) {"
9210 " switch (size) {"
9211 " case 1: return 'f';"
9212 " case 2: return 'fo';"
9213 " case 3: return 'foo';"
9214 " }"
9215 " return makestr(size >> 1) + makestr((size + 1) >> 1);"
9216 "}"
9217 "var x = makestr(12345);"
9218 "x = makestr(31415);"
9219 "x = makestr(23456);");
9220 v8::Handle<Value> value = CompileRun(
9221 "var o = new constructor();"
9222 "o.__proto__ = new String(x);"
9223 "o.hasOwnProperty('ostehaps');");
9224 CHECK_EQ(false, value->BooleanValue());
9225}
9226
9227
ager@chromium.orge2902be2009-06-08 12:21:35 +00009228typedef v8::Handle<Value> (*NamedPropertyGetter)(Local<String> property,
9229 const AccessorInfo& info);
9230
9231
9232static void CheckInterceptorLoadIC(NamedPropertyGetter getter,
9233 const char* source,
9234 int expected) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00009235 v8::HandleScope scope(v8::Isolate::GetCurrent());
ager@chromium.orge2902be2009-06-08 12:21:35 +00009236 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
vegorov@chromium.org21b5e952010-11-23 10:24:40 +00009237 templ->SetNamedPropertyHandler(getter, 0, 0, 0, 0, v8_str("data"));
ager@chromium.orge2902be2009-06-08 12:21:35 +00009238 LocalContext context;
9239 context->Global()->Set(v8_str("o"), templ->NewInstance());
9240 v8::Handle<Value> value = CompileRun(source);
9241 CHECK_EQ(expected, value->Int32Value());
9242}
9243
9244
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009245static v8::Handle<Value> InterceptorLoadICGetter(Local<String> name,
9246 const AccessorInfo& info) {
9247 ApiTestFuzzer::Fuzz();
jkummerow@chromium.org28faa982012-04-13 09:58:30 +00009248 v8::Isolate* isolate = v8::Isolate::GetCurrent();
9249 CHECK_EQ(isolate, info.GetIsolate());
vegorov@chromium.org21b5e952010-11-23 10:24:40 +00009250 CHECK_EQ(v8_str("data"), info.Data());
9251 CHECK_EQ(v8_str("x"), name);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009252 return v8::Integer::New(42);
9253}
9254
9255
9256// This test should hit the load IC for the interceptor case.
9257THREADED_TEST(InterceptorLoadIC) {
ager@chromium.orge2902be2009-06-08 12:21:35 +00009258 CheckInterceptorLoadIC(InterceptorLoadICGetter,
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009259 "var result = 0;"
9260 "for (var i = 0; i < 1000; i++) {"
9261 " result = o.x;"
ager@chromium.orge2902be2009-06-08 12:21:35 +00009262 "}",
9263 42);
9264}
9265
9266
9267// Below go several tests which verify that JITing for various
9268// configurations of interceptor and explicit fields works fine
9269// (those cases are special cased to get better performance).
9270
9271static v8::Handle<Value> InterceptorLoadXICGetter(Local<String> name,
9272 const AccessorInfo& info) {
9273 ApiTestFuzzer::Fuzz();
9274 return v8_str("x")->Equals(name)
9275 ? v8::Integer::New(42) : v8::Handle<v8::Value>();
9276}
9277
9278
9279THREADED_TEST(InterceptorLoadICWithFieldOnHolder) {
9280 CheckInterceptorLoadIC(InterceptorLoadXICGetter,
9281 "var result = 0;"
9282 "o.y = 239;"
9283 "for (var i = 0; i < 1000; i++) {"
9284 " result = o.y;"
9285 "}",
9286 239);
9287}
9288
9289
9290THREADED_TEST(InterceptorLoadICWithSubstitutedProto) {
9291 CheckInterceptorLoadIC(InterceptorLoadXICGetter,
9292 "var result = 0;"
9293 "o.__proto__ = { 'y': 239 };"
9294 "for (var i = 0; i < 1000; i++) {"
9295 " result = o.y + o.x;"
9296 "}",
9297 239 + 42);
9298}
9299
9300
9301THREADED_TEST(InterceptorLoadICWithPropertyOnProto) {
9302 CheckInterceptorLoadIC(InterceptorLoadXICGetter,
9303 "var result = 0;"
9304 "o.__proto__.y = 239;"
9305 "for (var i = 0; i < 1000; i++) {"
9306 " result = o.y + o.x;"
9307 "}",
9308 239 + 42);
9309}
9310
9311
9312THREADED_TEST(InterceptorLoadICUndefined) {
9313 CheckInterceptorLoadIC(InterceptorLoadXICGetter,
9314 "var result = 0;"
9315 "for (var i = 0; i < 1000; i++) {"
9316 " result = (o.y == undefined) ? 239 : 42;"
9317 "}",
9318 239);
9319}
9320
9321
9322THREADED_TEST(InterceptorLoadICWithOverride) {
9323 CheckInterceptorLoadIC(InterceptorLoadXICGetter,
9324 "fst = new Object(); fst.__proto__ = o;"
9325 "snd = new Object(); snd.__proto__ = fst;"
9326 "var result1 = 0;"
9327 "for (var i = 0; i < 1000; i++) {"
9328 " result1 = snd.x;"
9329 "}"
9330 "fst.x = 239;"
9331 "var result = 0;"
9332 "for (var i = 0; i < 1000; i++) {"
9333 " result = snd.x;"
9334 "}"
9335 "result + result1",
9336 239 + 42);
9337}
9338
9339
kasperl@chromium.orge959c182009-07-27 08:59:04 +00009340// Test the case when we stored field into
9341// a stub, but interceptor produced value on its own.
9342THREADED_TEST(InterceptorLoadICFieldNotNeeded) {
9343 CheckInterceptorLoadIC(InterceptorLoadXICGetter,
9344 "proto = new Object();"
9345 "o.__proto__ = proto;"
9346 "proto.x = 239;"
9347 "for (var i = 0; i < 1000; i++) {"
9348 " o.x;"
9349 // Now it should be ICed and keep a reference to x defined on proto
9350 "}"
9351 "var result = 0;"
9352 "for (var i = 0; i < 1000; i++) {"
9353 " result += o.x;"
9354 "}"
9355 "result;",
9356 42 * 1000);
9357}
9358
9359
9360// Test the case when we stored field into
9361// a stub, but it got invalidated later on.
9362THREADED_TEST(InterceptorLoadICInvalidatedField) {
9363 CheckInterceptorLoadIC(InterceptorLoadXICGetter,
9364 "proto1 = new Object();"
9365 "proto2 = new Object();"
9366 "o.__proto__ = proto1;"
9367 "proto1.__proto__ = proto2;"
9368 "proto2.y = 239;"
9369 "for (var i = 0; i < 1000; i++) {"
9370 " o.y;"
9371 // Now it should be ICed and keep a reference to y defined on proto2
9372 "}"
9373 "proto1.y = 42;"
9374 "var result = 0;"
9375 "for (var i = 0; i < 1000; i++) {"
9376 " result += o.y;"
9377 "}"
9378 "result;",
9379 42 * 1000);
9380}
9381
9382
ager@chromium.orgb26c50a2010-03-26 09:27:16 +00009383static int interceptor_load_not_handled_calls = 0;
9384static v8::Handle<Value> InterceptorLoadNotHandled(Local<String> name,
9385 const AccessorInfo& info) {
9386 ++interceptor_load_not_handled_calls;
9387 return v8::Handle<v8::Value>();
9388}
9389
9390
9391// Test how post-interceptor lookups are done in the non-cacheable
9392// case: the interceptor should not be invoked during this lookup.
9393THREADED_TEST(InterceptorLoadICPostInterceptor) {
9394 interceptor_load_not_handled_calls = 0;
9395 CheckInterceptorLoadIC(InterceptorLoadNotHandled,
9396 "receiver = new Object();"
9397 "receiver.__proto__ = o;"
9398 "proto = new Object();"
9399 "/* Make proto a slow-case object. */"
9400 "for (var i = 0; i < 1000; i++) {"
9401 " proto[\"xxxxxxxx\" + i] = [];"
9402 "}"
9403 "proto.x = 17;"
9404 "o.__proto__ = proto;"
9405 "var result = 0;"
9406 "for (var i = 0; i < 1000; i++) {"
9407 " result += receiver.x;"
9408 "}"
9409 "result;",
9410 17 * 1000);
9411 CHECK_EQ(1000, interceptor_load_not_handled_calls);
9412}
9413
9414
kasperl@chromium.orge959c182009-07-27 08:59:04 +00009415// Test the case when we stored field into
9416// a stub, but it got invalidated later on due to override on
9417// global object which is between interceptor and fields' holders.
9418THREADED_TEST(InterceptorLoadICInvalidatedFieldViaGlobal) {
9419 CheckInterceptorLoadIC(InterceptorLoadXICGetter,
9420 "o.__proto__ = this;" // set a global to be a proto of o.
9421 "this.__proto__.y = 239;"
9422 "for (var i = 0; i < 10; i++) {"
9423 " if (o.y != 239) throw 'oops: ' + o.y;"
9424 // Now it should be ICed and keep a reference to y defined on field_holder.
9425 "}"
9426 "this.y = 42;" // Assign on a global.
9427 "var result = 0;"
9428 "for (var i = 0; i < 10; i++) {"
9429 " result += o.y;"
9430 "}"
9431 "result;",
9432 42 * 10);
9433}
9434
9435
kasperl@chromium.orge959c182009-07-27 08:59:04 +00009436static void SetOnThis(Local<String> name,
9437 Local<Value> value,
9438 const AccessorInfo& info) {
9439 info.This()->ForceSet(name, value);
9440}
9441
9442
9443THREADED_TEST(InterceptorLoadICWithCallbackOnHolder) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00009444 v8::HandleScope scope(v8::Isolate::GetCurrent());
kasperl@chromium.orge959c182009-07-27 08:59:04 +00009445 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
9446 templ->SetNamedPropertyHandler(InterceptorLoadXICGetter);
9447 templ->SetAccessor(v8_str("y"), Return239);
9448 LocalContext context;
9449 context->Global()->Set(v8_str("o"), templ->NewInstance());
ricow@chromium.org30ce4112010-05-31 10:38:25 +00009450
9451 // Check the case when receiver and interceptor's holder
9452 // are the same objects.
kasperl@chromium.orge959c182009-07-27 08:59:04 +00009453 v8::Handle<Value> value = CompileRun(
9454 "var result = 0;"
9455 "for (var i = 0; i < 7; i++) {"
9456 " result = o.y;"
9457 "}");
9458 CHECK_EQ(239, value->Int32Value());
ricow@chromium.org30ce4112010-05-31 10:38:25 +00009459
9460 // Check the case when interceptor's holder is in proto chain
9461 // of receiver.
9462 value = CompileRun(
9463 "r = { __proto__: o };"
9464 "var result = 0;"
9465 "for (var i = 0; i < 7; i++) {"
9466 " result = r.y;"
9467 "}");
9468 CHECK_EQ(239, value->Int32Value());
kasperl@chromium.orge959c182009-07-27 08:59:04 +00009469}
9470
9471
9472THREADED_TEST(InterceptorLoadICWithCallbackOnProto) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00009473 v8::HandleScope scope(v8::Isolate::GetCurrent());
kasperl@chromium.orge959c182009-07-27 08:59:04 +00009474 v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
9475 templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
9476 v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New();
9477 templ_p->SetAccessor(v8_str("y"), Return239);
9478
9479 LocalContext context;
9480 context->Global()->Set(v8_str("o"), templ_o->NewInstance());
9481 context->Global()->Set(v8_str("p"), templ_p->NewInstance());
9482
ricow@chromium.org30ce4112010-05-31 10:38:25 +00009483 // Check the case when receiver and interceptor's holder
9484 // are the same objects.
kasperl@chromium.orge959c182009-07-27 08:59:04 +00009485 v8::Handle<Value> value = CompileRun(
9486 "o.__proto__ = p;"
9487 "var result = 0;"
9488 "for (var i = 0; i < 7; i++) {"
9489 " result = o.x + o.y;"
9490 "}");
9491 CHECK_EQ(239 + 42, value->Int32Value());
ricow@chromium.org30ce4112010-05-31 10:38:25 +00009492
9493 // Check the case when interceptor's holder is in proto chain
9494 // of receiver.
9495 value = CompileRun(
9496 "r = { __proto__: o };"
9497 "var result = 0;"
9498 "for (var i = 0; i < 7; i++) {"
9499 " result = r.x + r.y;"
9500 "}");
9501 CHECK_EQ(239 + 42, value->Int32Value());
kasperl@chromium.orge959c182009-07-27 08:59:04 +00009502}
9503
9504
9505THREADED_TEST(InterceptorLoadICForCallbackWithOverride) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00009506 v8::HandleScope scope(v8::Isolate::GetCurrent());
kasperl@chromium.orge959c182009-07-27 08:59:04 +00009507 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
9508 templ->SetNamedPropertyHandler(InterceptorLoadXICGetter);
9509 templ->SetAccessor(v8_str("y"), Return239);
9510
9511 LocalContext context;
9512 context->Global()->Set(v8_str("o"), templ->NewInstance());
9513
9514 v8::Handle<Value> value = CompileRun(
9515 "fst = new Object(); fst.__proto__ = o;"
9516 "snd = new Object(); snd.__proto__ = fst;"
9517 "var result1 = 0;"
9518 "for (var i = 0; i < 7; i++) {"
9519 " result1 = snd.x;"
9520 "}"
9521 "fst.x = 239;"
9522 "var result = 0;"
9523 "for (var i = 0; i < 7; i++) {"
9524 " result = snd.x;"
9525 "}"
9526 "result + result1");
9527 CHECK_EQ(239 + 42, value->Int32Value());
9528}
9529
9530
9531// Test the case when we stored callback into
9532// a stub, but interceptor produced value on its own.
9533THREADED_TEST(InterceptorLoadICCallbackNotNeeded) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00009534 v8::HandleScope scope(v8::Isolate::GetCurrent());
kasperl@chromium.orge959c182009-07-27 08:59:04 +00009535 v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
9536 templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
9537 v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New();
9538 templ_p->SetAccessor(v8_str("y"), Return239);
9539
9540 LocalContext context;
9541 context->Global()->Set(v8_str("o"), templ_o->NewInstance());
9542 context->Global()->Set(v8_str("p"), templ_p->NewInstance());
9543
9544 v8::Handle<Value> value = CompileRun(
9545 "o.__proto__ = p;"
9546 "for (var i = 0; i < 7; i++) {"
9547 " o.x;"
9548 // Now it should be ICed and keep a reference to x defined on p
9549 "}"
9550 "var result = 0;"
9551 "for (var i = 0; i < 7; i++) {"
9552 " result += o.x;"
9553 "}"
9554 "result");
9555 CHECK_EQ(42 * 7, value->Int32Value());
9556}
9557
9558
9559// Test the case when we stored callback into
9560// a stub, but it got invalidated later on.
9561THREADED_TEST(InterceptorLoadICInvalidatedCallback) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00009562 v8::HandleScope scope(v8::Isolate::GetCurrent());
kasperl@chromium.orge959c182009-07-27 08:59:04 +00009563 v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
9564 templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
9565 v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New();
9566 templ_p->SetAccessor(v8_str("y"), Return239, SetOnThis);
9567
9568 LocalContext context;
9569 context->Global()->Set(v8_str("o"), templ_o->NewInstance());
9570 context->Global()->Set(v8_str("p"), templ_p->NewInstance());
9571
9572 v8::Handle<Value> value = CompileRun(
9573 "inbetween = new Object();"
9574 "o.__proto__ = inbetween;"
9575 "inbetween.__proto__ = p;"
9576 "for (var i = 0; i < 10; i++) {"
9577 " o.y;"
9578 // Now it should be ICed and keep a reference to y defined on p
9579 "}"
9580 "inbetween.y = 42;"
9581 "var result = 0;"
9582 "for (var i = 0; i < 10; i++) {"
9583 " result += o.y;"
9584 "}"
9585 "result");
9586 CHECK_EQ(42 * 10, value->Int32Value());
9587}
9588
9589
9590// Test the case when we stored callback into
9591// a stub, but it got invalidated later on due to override on
9592// global object which is between interceptor and callbacks' holders.
9593THREADED_TEST(InterceptorLoadICInvalidatedCallbackViaGlobal) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00009594 v8::HandleScope scope(v8::Isolate::GetCurrent());
kasperl@chromium.orge959c182009-07-27 08:59:04 +00009595 v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
9596 templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
9597 v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New();
9598 templ_p->SetAccessor(v8_str("y"), Return239, SetOnThis);
9599
9600 LocalContext context;
9601 context->Global()->Set(v8_str("o"), templ_o->NewInstance());
9602 context->Global()->Set(v8_str("p"), templ_p->NewInstance());
9603
9604 v8::Handle<Value> value = CompileRun(
9605 "o.__proto__ = this;"
9606 "this.__proto__ = p;"
9607 "for (var i = 0; i < 10; i++) {"
9608 " if (o.y != 239) throw 'oops: ' + o.y;"
9609 // Now it should be ICed and keep a reference to y defined on p
9610 "}"
9611 "this.y = 42;"
9612 "var result = 0;"
9613 "for (var i = 0; i < 10; i++) {"
9614 " result += o.y;"
9615 "}"
9616 "result");
9617 CHECK_EQ(42 * 10, value->Int32Value());
9618}
9619
9620
ager@chromium.orge2902be2009-06-08 12:21:35 +00009621static v8::Handle<Value> InterceptorLoadICGetter0(Local<String> name,
9622 const AccessorInfo& info) {
9623 ApiTestFuzzer::Fuzz();
9624 CHECK(v8_str("x")->Equals(name));
9625 return v8::Integer::New(0);
9626}
9627
9628
9629THREADED_TEST(InterceptorReturningZero) {
9630 CheckInterceptorLoadIC(InterceptorLoadICGetter0,
9631 "o.x == undefined ? 1 : 0",
9632 0);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009633}
9634
9635
9636static v8::Handle<Value> InterceptorStoreICSetter(
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00009637 Local<String> key, Local<Value> value, const AccessorInfo&) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009638 CHECK(v8_str("x")->Equals(key));
9639 CHECK_EQ(42, value->Int32Value());
9640 return value;
9641}
9642
9643
9644// This test should hit the store IC for the interceptor case.
9645THREADED_TEST(InterceptorStoreIC) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00009646 v8::HandleScope scope(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009647 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
9648 templ->SetNamedPropertyHandler(InterceptorLoadICGetter,
vegorov@chromium.org21b5e952010-11-23 10:24:40 +00009649 InterceptorStoreICSetter,
9650 0, 0, 0, v8_str("data"));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009651 LocalContext context;
9652 context->Global()->Set(v8_str("o"), templ->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00009653 CompileRun(
9654 "for (var i = 0; i < 1000; i++) {"
9655 " o.x = 42;"
9656 "}");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009657}
9658
9659
ager@chromium.orgeadaf222009-06-16 09:43:10 +00009660THREADED_TEST(InterceptorStoreICWithNoSetter) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00009661 v8::HandleScope scope(v8::Isolate::GetCurrent());
ager@chromium.orgeadaf222009-06-16 09:43:10 +00009662 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
9663 templ->SetNamedPropertyHandler(InterceptorLoadXICGetter);
9664 LocalContext context;
9665 context->Global()->Set(v8_str("o"), templ->NewInstance());
9666 v8::Handle<Value> value = CompileRun(
9667 "for (var i = 0; i < 1000; i++) {"
9668 " o.y = 239;"
9669 "}"
9670 "42 + o.y");
9671 CHECK_EQ(239 + 42, value->Int32Value());
9672}
9673
9674
9675
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009676
9677v8::Handle<Value> call_ic_function;
9678v8::Handle<Value> call_ic_function2;
9679v8::Handle<Value> call_ic_function3;
9680
9681static v8::Handle<Value> InterceptorCallICGetter(Local<String> name,
9682 const AccessorInfo& info) {
9683 ApiTestFuzzer::Fuzz();
9684 CHECK(v8_str("x")->Equals(name));
9685 return call_ic_function;
9686}
9687
9688
9689// This test should hit the call IC for the interceptor case.
9690THREADED_TEST(InterceptorCallIC) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00009691 v8::HandleScope scope(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009692 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
9693 templ->SetNamedPropertyHandler(InterceptorCallICGetter);
9694 LocalContext context;
9695 context->Global()->Set(v8_str("o"), templ->NewInstance());
9696 call_ic_function =
9697 v8_compile("function f(x) { return x + 1; }; f")->Run();
9698 v8::Handle<Value> value = CompileRun(
9699 "var result = 0;"
9700 "for (var i = 0; i < 1000; i++) {"
9701 " result = o.x(41);"
9702 "}");
9703 CHECK_EQ(42, value->Int32Value());
9704}
9705
kasperl@chromium.orge959c182009-07-27 08:59:04 +00009706
9707// This test checks that if interceptor doesn't provide
9708// a value, we can fetch regular value.
9709THREADED_TEST(InterceptorCallICSeesOthers) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00009710 v8::HandleScope scope(v8::Isolate::GetCurrent());
kasperl@chromium.orge959c182009-07-27 08:59:04 +00009711 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
9712 templ->SetNamedPropertyHandler(NoBlockGetterX);
9713 LocalContext context;
9714 context->Global()->Set(v8_str("o"), templ->NewInstance());
9715 v8::Handle<Value> value = CompileRun(
9716 "o.x = function f(x) { return x + 1; };"
9717 "var result = 0;"
9718 "for (var i = 0; i < 7; i++) {"
9719 " result = o.x(41);"
9720 "}");
9721 CHECK_EQ(42, value->Int32Value());
9722}
9723
9724
9725static v8::Handle<Value> call_ic_function4;
9726static v8::Handle<Value> InterceptorCallICGetter4(Local<String> name,
9727 const AccessorInfo& info) {
9728 ApiTestFuzzer::Fuzz();
9729 CHECK(v8_str("x")->Equals(name));
9730 return call_ic_function4;
9731}
9732
9733
9734// This test checks that if interceptor provides a function,
9735// even if we cached shadowed variant, interceptor's function
9736// is invoked
9737THREADED_TEST(InterceptorCallICCacheableNotNeeded) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00009738 v8::HandleScope scope(v8::Isolate::GetCurrent());
kasperl@chromium.orge959c182009-07-27 08:59:04 +00009739 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
9740 templ->SetNamedPropertyHandler(InterceptorCallICGetter4);
9741 LocalContext context;
9742 context->Global()->Set(v8_str("o"), templ->NewInstance());
9743 call_ic_function4 =
9744 v8_compile("function f(x) { return x - 1; }; f")->Run();
9745 v8::Handle<Value> value = CompileRun(
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +00009746 "Object.getPrototypeOf(o).x = function(x) { return x + 1; };"
kasperl@chromium.orge959c182009-07-27 08:59:04 +00009747 "var result = 0;"
9748 "for (var i = 0; i < 1000; i++) {"
9749 " result = o.x(42);"
9750 "}");
9751 CHECK_EQ(41, value->Int32Value());
9752}
9753
9754
9755// Test the case when we stored cacheable lookup into
9756// a stub, but it got invalidated later on
9757THREADED_TEST(InterceptorCallICInvalidatedCacheable) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00009758 v8::HandleScope scope(v8::Isolate::GetCurrent());
kasperl@chromium.orge959c182009-07-27 08:59:04 +00009759 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
9760 templ->SetNamedPropertyHandler(NoBlockGetterX);
9761 LocalContext context;
9762 context->Global()->Set(v8_str("o"), templ->NewInstance());
9763 v8::Handle<Value> value = CompileRun(
9764 "proto1 = new Object();"
9765 "proto2 = new Object();"
9766 "o.__proto__ = proto1;"
9767 "proto1.__proto__ = proto2;"
9768 "proto2.y = function(x) { return x + 1; };"
9769 // Invoke it many times to compile a stub
9770 "for (var i = 0; i < 7; i++) {"
9771 " o.y(42);"
9772 "}"
9773 "proto1.y = function(x) { return x - 1; };"
9774 "var result = 0;"
9775 "for (var i = 0; i < 7; i++) {"
9776 " result += o.y(42);"
9777 "}");
9778 CHECK_EQ(41 * 7, value->Int32Value());
9779}
9780
9781
kasperl@chromium.orge959c182009-07-27 08:59:04 +00009782// This test checks that if interceptor doesn't provide a function,
9783// cached constant function is used
9784THREADED_TEST(InterceptorCallICConstantFunctionUsed) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00009785 v8::HandleScope scope(v8::Isolate::GetCurrent());
kasperl@chromium.orge959c182009-07-27 08:59:04 +00009786 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
9787 templ->SetNamedPropertyHandler(NoBlockGetterX);
9788 LocalContext context;
9789 context->Global()->Set(v8_str("o"), templ->NewInstance());
9790 v8::Handle<Value> value = CompileRun(
9791 "function inc(x) { return x + 1; };"
9792 "inc(1);"
9793 "o.x = inc;"
9794 "var result = 0;"
9795 "for (var i = 0; i < 1000; i++) {"
9796 " result = o.x(42);"
9797 "}");
9798 CHECK_EQ(43, value->Int32Value());
9799}
9800
9801
ulan@chromium.org2efb9002012-01-19 15:36:35 +00009802static v8::Handle<Value> call_ic_function5;
9803static v8::Handle<Value> InterceptorCallICGetter5(Local<String> name,
9804 const AccessorInfo& info) {
9805 ApiTestFuzzer::Fuzz();
9806 if (v8_str("x")->Equals(name))
9807 return call_ic_function5;
9808 else
9809 return Local<Value>();
9810}
9811
9812
kasperl@chromium.orge959c182009-07-27 08:59:04 +00009813// This test checks that if interceptor provides a function,
9814// even if we cached constant function, interceptor's function
9815// is invoked
9816THREADED_TEST(InterceptorCallICConstantFunctionNotNeeded) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00009817 v8::HandleScope scope(v8::Isolate::GetCurrent());
kasperl@chromium.orge959c182009-07-27 08:59:04 +00009818 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
9819 templ->SetNamedPropertyHandler(InterceptorCallICGetter5);
9820 LocalContext context;
9821 context->Global()->Set(v8_str("o"), templ->NewInstance());
9822 call_ic_function5 =
9823 v8_compile("function f(x) { return x - 1; }; f")->Run();
9824 v8::Handle<Value> value = CompileRun(
9825 "function inc(x) { return x + 1; };"
9826 "inc(1);"
9827 "o.x = inc;"
9828 "var result = 0;"
9829 "for (var i = 0; i < 1000; i++) {"
9830 " result = o.x(42);"
9831 "}");
9832 CHECK_EQ(41, value->Int32Value());
9833}
9834
9835
ulan@chromium.org2efb9002012-01-19 15:36:35 +00009836static v8::Handle<Value> call_ic_function6;
9837static v8::Handle<Value> InterceptorCallICGetter6(Local<String> name,
9838 const AccessorInfo& info) {
9839 ApiTestFuzzer::Fuzz();
9840 if (v8_str("x")->Equals(name))
9841 return call_ic_function6;
9842 else
9843 return Local<Value>();
9844}
9845
9846
9847// Same test as above, except the code is wrapped in a function
9848// to test the optimized compiler.
9849THREADED_TEST(InterceptorCallICConstantFunctionNotNeededWrapped) {
9850 i::FLAG_allow_natives_syntax = true;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00009851 v8::HandleScope scope(v8::Isolate::GetCurrent());
ulan@chromium.org2efb9002012-01-19 15:36:35 +00009852 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
9853 templ->SetNamedPropertyHandler(InterceptorCallICGetter6);
9854 LocalContext context;
9855 context->Global()->Set(v8_str("o"), templ->NewInstance());
9856 call_ic_function6 =
9857 v8_compile("function f(x) { return x - 1; }; f")->Run();
9858 v8::Handle<Value> value = CompileRun(
9859 "function inc(x) { return x + 1; };"
9860 "inc(1);"
9861 "o.x = inc;"
9862 "function test() {"
9863 " var result = 0;"
9864 " for (var i = 0; i < 1000; i++) {"
9865 " result = o.x(42);"
9866 " }"
9867 " return result;"
9868 "};"
9869 "test();"
9870 "test();"
9871 "test();"
9872 "%OptimizeFunctionOnNextCall(test);"
9873 "test()");
9874 CHECK_EQ(41, value->Int32Value());
9875}
9876
9877
kasperl@chromium.orge959c182009-07-27 08:59:04 +00009878// Test the case when we stored constant function into
9879// a stub, but it got invalidated later on
9880THREADED_TEST(InterceptorCallICInvalidatedConstantFunction) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00009881 v8::HandleScope scope(v8::Isolate::GetCurrent());
kasperl@chromium.orge959c182009-07-27 08:59:04 +00009882 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
9883 templ->SetNamedPropertyHandler(NoBlockGetterX);
9884 LocalContext context;
9885 context->Global()->Set(v8_str("o"), templ->NewInstance());
9886 v8::Handle<Value> value = CompileRun(
9887 "function inc(x) { return x + 1; };"
9888 "inc(1);"
9889 "proto1 = new Object();"
9890 "proto2 = new Object();"
9891 "o.__proto__ = proto1;"
9892 "proto1.__proto__ = proto2;"
9893 "proto2.y = inc;"
9894 // Invoke it many times to compile a stub
9895 "for (var i = 0; i < 7; i++) {"
9896 " o.y(42);"
9897 "}"
9898 "proto1.y = function(x) { return x - 1; };"
9899 "var result = 0;"
9900 "for (var i = 0; i < 7; i++) {"
9901 " result += o.y(42);"
9902 "}");
9903 CHECK_EQ(41 * 7, value->Int32Value());
9904}
9905
9906
9907// Test the case when we stored constant function into
9908// a stub, but it got invalidated later on due to override on
9909// global object which is between interceptor and constant function' holders.
9910THREADED_TEST(InterceptorCallICInvalidatedConstantFunctionViaGlobal) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00009911 v8::HandleScope scope(v8::Isolate::GetCurrent());
kasperl@chromium.orge959c182009-07-27 08:59:04 +00009912 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
9913 templ->SetNamedPropertyHandler(NoBlockGetterX);
9914 LocalContext context;
9915 context->Global()->Set(v8_str("o"), templ->NewInstance());
9916 v8::Handle<Value> value = CompileRun(
9917 "function inc(x) { return x + 1; };"
9918 "inc(1);"
9919 "o.__proto__ = this;"
9920 "this.__proto__.y = inc;"
9921 // Invoke it many times to compile a stub
9922 "for (var i = 0; i < 7; i++) {"
9923 " if (o.y(42) != 43) throw 'oops: ' + o.y(42);"
9924 "}"
9925 "this.y = function(x) { return x - 1; };"
9926 "var result = 0;"
9927 "for (var i = 0; i < 7; i++) {"
9928 " result += o.y(42);"
9929 "}");
9930 CHECK_EQ(41 * 7, value->Int32Value());
9931}
9932
9933
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00009934// Test the case when actual function to call sits on global object.
9935THREADED_TEST(InterceptorCallICCachedFromGlobal) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00009936 v8::HandleScope scope(v8::Isolate::GetCurrent());
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00009937 v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
9938 templ_o->SetNamedPropertyHandler(NoBlockGetterX);
9939
9940 LocalContext context;
9941 context->Global()->Set(v8_str("o"), templ_o->NewInstance());
9942
9943 v8::Handle<Value> value = CompileRun(
9944 "try {"
9945 " o.__proto__ = this;"
9946 " for (var i = 0; i < 10; i++) {"
9947 " var v = o.parseFloat('239');"
9948 " if (v != 239) throw v;"
9949 // Now it should be ICed and keep a reference to parseFloat.
9950 " }"
9951 " var result = 0;"
9952 " for (var i = 0; i < 10; i++) {"
9953 " result += o.parseFloat('239');"
9954 " }"
9955 " result"
9956 "} catch(e) {"
9957 " e"
9958 "};");
9959 CHECK_EQ(239 * 10, value->Int32Value());
9960}
9961
ager@chromium.org5c838252010-02-19 08:53:10 +00009962static v8::Handle<Value> InterceptorCallICFastApi(Local<String> name,
9963 const AccessorInfo& info) {
9964 ApiTestFuzzer::Fuzz();
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00009965 int* call_count =
9966 reinterpret_cast<int*>(v8::External::Cast(*info.Data())->Value());
ager@chromium.org5c838252010-02-19 08:53:10 +00009967 ++(*call_count);
9968 if ((*call_count) % 20 == 0) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00009969 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org5c838252010-02-19 08:53:10 +00009970 }
9971 return v8::Handle<Value>();
9972}
9973
9974static v8::Handle<Value> FastApiCallback_TrivialSignature(
9975 const v8::Arguments& args) {
9976 ApiTestFuzzer::Fuzz();
jkummerow@chromium.org28faa982012-04-13 09:58:30 +00009977 v8::Isolate* isolate = v8::Isolate::GetCurrent();
9978 CHECK_EQ(isolate, args.GetIsolate());
ager@chromium.org5c838252010-02-19 08:53:10 +00009979 CHECK_EQ(args.This(), args.Holder());
9980 CHECK(args.Data()->Equals(v8_str("method_data")));
9981 return v8::Integer::New(args[0]->Int32Value() + 1);
9982}
9983
9984static v8::Handle<Value> FastApiCallback_SimpleSignature(
9985 const v8::Arguments& args) {
9986 ApiTestFuzzer::Fuzz();
jkummerow@chromium.org28faa982012-04-13 09:58:30 +00009987 v8::Isolate* isolate = v8::Isolate::GetCurrent();
9988 CHECK_EQ(isolate, args.GetIsolate());
ager@chromium.org5c838252010-02-19 08:53:10 +00009989 CHECK_EQ(args.This()->GetPrototype(), args.Holder());
9990 CHECK(args.Data()->Equals(v8_str("method_data")));
9991 // Note, we're using HasRealNamedProperty instead of Has to avoid
9992 // invoking the interceptor again.
9993 CHECK(args.Holder()->HasRealNamedProperty(v8_str("foo")));
9994 return v8::Integer::New(args[0]->Int32Value() + 1);
9995}
9996
9997// Helper to maximize the odds of object moving.
9998static void GenerateSomeGarbage() {
9999 CompileRun(
10000 "var garbage;"
10001 "for (var i = 0; i < 1000; i++) {"
10002 " garbage = [1/i, \"garbage\" + i, garbage, {foo: garbage}];"
10003 "}"
10004 "garbage = undefined;");
10005}
10006
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000010007
ricow@chromium.org83aa5492011-02-07 12:42:56 +000010008v8::Handle<v8::Value> DirectApiCallback(const v8::Arguments& args) {
10009 static int count = 0;
10010 if (count++ % 3 == 0) {
yangguo@chromium.orgd2899aa2012-06-21 11:16:20 +000010011 HEAP->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
10012 // This should move the stub
ricow@chromium.org83aa5492011-02-07 12:42:56 +000010013 GenerateSomeGarbage(); // This should ensure the old stub memory is flushed
10014 }
10015 return v8::Handle<v8::Value>();
10016}
10017
10018
10019THREADED_TEST(CallICFastApi_DirectCall_GCMoveStub) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +000010020 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000010021 v8::HandleScope scope(context->GetIsolate());
ricow@chromium.org83aa5492011-02-07 12:42:56 +000010022 v8::Handle<v8::ObjectTemplate> nativeobject_templ = v8::ObjectTemplate::New();
10023 nativeobject_templ->Set("callback",
10024 v8::FunctionTemplate::New(DirectApiCallback));
10025 v8::Local<v8::Object> nativeobject_obj = nativeobject_templ->NewInstance();
10026 context->Global()->Set(v8_str("nativeobject"), nativeobject_obj);
10027 // call the api function multiple times to ensure direct call stub creation.
10028 CompileRun(
10029 "function f() {"
10030 " for (var i = 1; i <= 30; i++) {"
10031 " nativeobject.callback();"
10032 " }"
10033 "}"
10034 "f();");
10035}
10036
10037
10038v8::Handle<v8::Value> ThrowingDirectApiCallback(const v8::Arguments& args) {
10039 return v8::ThrowException(v8_str("g"));
10040}
10041
10042
10043THREADED_TEST(CallICFastApi_DirectCall_Throw) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +000010044 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000010045 v8::HandleScope scope(context->GetIsolate());
ricow@chromium.org83aa5492011-02-07 12:42:56 +000010046 v8::Handle<v8::ObjectTemplate> nativeobject_templ = v8::ObjectTemplate::New();
10047 nativeobject_templ->Set("callback",
10048 v8::FunctionTemplate::New(ThrowingDirectApiCallback));
10049 v8::Local<v8::Object> nativeobject_obj = nativeobject_templ->NewInstance();
10050 context->Global()->Set(v8_str("nativeobject"), nativeobject_obj);
10051 // call the api function multiple times to ensure direct call stub creation.
10052 v8::Handle<Value> result = CompileRun(
10053 "var result = '';"
10054 "function f() {"
10055 " for (var i = 1; i <= 5; i++) {"
10056 " try { nativeobject.callback(); } catch (e) { result += e; }"
10057 " }"
10058 "}"
10059 "f(); result;");
10060 CHECK_EQ(v8_str("ggggg"), result);
10061}
10062
10063
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000010064v8::Handle<v8::Value> DirectGetterCallback(Local<String> name,
10065 const v8::AccessorInfo& info) {
10066 if (++p_getter_count % 3 == 0) {
yangguo@chromium.orgd2899aa2012-06-21 11:16:20 +000010067 HEAP->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000010068 GenerateSomeGarbage();
10069 }
10070 return v8::Handle<v8::Value>();
10071}
10072
10073
10074THREADED_TEST(LoadICFastApi_DirectCall_GCMoveStub) {
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000010075 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000010076 v8::HandleScope scope(context->GetIsolate());
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000010077 v8::Handle<v8::ObjectTemplate> obj = v8::ObjectTemplate::New();
10078 obj->SetAccessor(v8_str("p1"), DirectGetterCallback);
10079 context->Global()->Set(v8_str("o1"), obj->NewInstance());
10080 p_getter_count = 0;
10081 CompileRun(
10082 "function f() {"
10083 " for (var i = 0; i < 30; i++) o1.p1;"
10084 "}"
10085 "f();");
10086 CHECK_EQ(30, p_getter_count);
10087}
10088
10089
10090v8::Handle<v8::Value> ThrowingDirectGetterCallback(
10091 Local<String> name, const v8::AccessorInfo& info) {
10092 return v8::ThrowException(v8_str("g"));
10093}
10094
10095
10096THREADED_TEST(LoadICFastApi_DirectCall_Throw) {
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000010097 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000010098 v8::HandleScope scope(context->GetIsolate());
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000010099 v8::Handle<v8::ObjectTemplate> obj = v8::ObjectTemplate::New();
10100 obj->SetAccessor(v8_str("p1"), ThrowingDirectGetterCallback);
10101 context->Global()->Set(v8_str("o1"), obj->NewInstance());
10102 v8::Handle<Value> result = CompileRun(
10103 "var result = '';"
10104 "for (var i = 0; i < 5; i++) {"
10105 " try { o1.p1; } catch (e) { result += e; }"
10106 "}"
10107 "result;");
10108 CHECK_EQ(v8_str("ggggg"), result);
10109}
10110
10111
ager@chromium.org5c838252010-02-19 08:53:10 +000010112THREADED_TEST(InterceptorCallICFastApi_TrivialSignature) {
10113 int interceptor_call_count = 0;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000010114 v8::HandleScope scope(v8::Isolate::GetCurrent());
ager@chromium.org5c838252010-02-19 08:53:10 +000010115 v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
10116 v8::Handle<v8::FunctionTemplate> method_templ =
10117 v8::FunctionTemplate::New(FastApiCallback_TrivialSignature,
10118 v8_str("method_data"),
10119 v8::Handle<v8::Signature>());
10120 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
10121 proto_templ->Set(v8_str("method"), method_templ);
10122 v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
10123 templ->SetNamedPropertyHandler(InterceptorCallICFastApi,
10124 NULL, NULL, NULL, NULL,
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000010125 v8::External::New(&interceptor_call_count));
ager@chromium.org5c838252010-02-19 08:53:10 +000010126 LocalContext context;
10127 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
10128 GenerateSomeGarbage();
10129 context->Global()->Set(v8_str("o"), fun->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000010130 CompileRun(
ager@chromium.org5c838252010-02-19 08:53:10 +000010131 "var result = 0;"
10132 "for (var i = 0; i < 100; i++) {"
10133 " result = o.method(41);"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000010134 "}");
ager@chromium.org5c838252010-02-19 08:53:10 +000010135 CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
10136 CHECK_EQ(100, interceptor_call_count);
10137}
10138
10139THREADED_TEST(InterceptorCallICFastApi_SimpleSignature) {
10140 int interceptor_call_count = 0;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000010141 v8::HandleScope scope(v8::Isolate::GetCurrent());
ager@chromium.org5c838252010-02-19 08:53:10 +000010142 v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
10143 v8::Handle<v8::FunctionTemplate> method_templ =
10144 v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
10145 v8_str("method_data"),
10146 v8::Signature::New(fun_templ));
10147 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
10148 proto_templ->Set(v8_str("method"), method_templ);
mmassi@chromium.org49a44672012-12-04 13:52:03 +000010149 fun_templ->SetHiddenPrototype(true);
ager@chromium.org5c838252010-02-19 08:53:10 +000010150 v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
10151 templ->SetNamedPropertyHandler(InterceptorCallICFastApi,
10152 NULL, NULL, NULL, NULL,
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000010153 v8::External::New(&interceptor_call_count));
ager@chromium.org5c838252010-02-19 08:53:10 +000010154 LocalContext context;
10155 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
10156 GenerateSomeGarbage();
10157 context->Global()->Set(v8_str("o"), fun->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000010158 CompileRun(
ager@chromium.org5c838252010-02-19 08:53:10 +000010159 "o.foo = 17;"
10160 "var receiver = {};"
10161 "receiver.__proto__ = o;"
10162 "var result = 0;"
10163 "for (var i = 0; i < 100; i++) {"
10164 " result = receiver.method(41);"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000010165 "}");
ager@chromium.org5c838252010-02-19 08:53:10 +000010166 CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
10167 CHECK_EQ(100, interceptor_call_count);
10168}
10169
10170THREADED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss1) {
10171 int interceptor_call_count = 0;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000010172 v8::HandleScope scope(v8::Isolate::GetCurrent());
ager@chromium.org5c838252010-02-19 08:53:10 +000010173 v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
10174 v8::Handle<v8::FunctionTemplate> method_templ =
10175 v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
10176 v8_str("method_data"),
10177 v8::Signature::New(fun_templ));
10178 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
10179 proto_templ->Set(v8_str("method"), method_templ);
mmassi@chromium.org49a44672012-12-04 13:52:03 +000010180 fun_templ->SetHiddenPrototype(true);
ager@chromium.org5c838252010-02-19 08:53:10 +000010181 v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
10182 templ->SetNamedPropertyHandler(InterceptorCallICFastApi,
10183 NULL, NULL, NULL, NULL,
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000010184 v8::External::New(&interceptor_call_count));
ager@chromium.org5c838252010-02-19 08:53:10 +000010185 LocalContext context;
10186 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
10187 GenerateSomeGarbage();
10188 context->Global()->Set(v8_str("o"), fun->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000010189 CompileRun(
ager@chromium.org5c838252010-02-19 08:53:10 +000010190 "o.foo = 17;"
10191 "var receiver = {};"
10192 "receiver.__proto__ = o;"
10193 "var result = 0;"
10194 "var saved_result = 0;"
10195 "for (var i = 0; i < 100; i++) {"
10196 " result = receiver.method(41);"
10197 " if (i == 50) {"
10198 " saved_result = result;"
10199 " receiver = {method: function(x) { return x - 1 }};"
10200 " }"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000010201 "}");
ager@chromium.org5c838252010-02-19 08:53:10 +000010202 CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
10203 CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
10204 CHECK_GE(interceptor_call_count, 50);
10205}
10206
10207THREADED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss2) {
10208 int interceptor_call_count = 0;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000010209 v8::HandleScope scope(v8::Isolate::GetCurrent());
ager@chromium.org5c838252010-02-19 08:53:10 +000010210 v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
10211 v8::Handle<v8::FunctionTemplate> method_templ =
10212 v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
10213 v8_str("method_data"),
10214 v8::Signature::New(fun_templ));
10215 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
10216 proto_templ->Set(v8_str("method"), method_templ);
mmassi@chromium.org49a44672012-12-04 13:52:03 +000010217 fun_templ->SetHiddenPrototype(true);
ager@chromium.org5c838252010-02-19 08:53:10 +000010218 v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
10219 templ->SetNamedPropertyHandler(InterceptorCallICFastApi,
10220 NULL, NULL, NULL, NULL,
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000010221 v8::External::New(&interceptor_call_count));
ager@chromium.org5c838252010-02-19 08:53:10 +000010222 LocalContext context;
10223 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
10224 GenerateSomeGarbage();
10225 context->Global()->Set(v8_str("o"), fun->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000010226 CompileRun(
ager@chromium.org5c838252010-02-19 08:53:10 +000010227 "o.foo = 17;"
10228 "var receiver = {};"
10229 "receiver.__proto__ = o;"
10230 "var result = 0;"
10231 "var saved_result = 0;"
10232 "for (var i = 0; i < 100; i++) {"
10233 " result = receiver.method(41);"
10234 " if (i == 50) {"
10235 " saved_result = result;"
10236 " o.method = function(x) { return x - 1 };"
10237 " }"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000010238 "}");
ager@chromium.org5c838252010-02-19 08:53:10 +000010239 CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
10240 CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
10241 CHECK_GE(interceptor_call_count, 50);
10242}
10243
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000010244THREADED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss3) {
10245 int interceptor_call_count = 0;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000010246 v8::HandleScope scope(v8::Isolate::GetCurrent());
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000010247 v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
10248 v8::Handle<v8::FunctionTemplate> method_templ =
10249 v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
10250 v8_str("method_data"),
10251 v8::Signature::New(fun_templ));
10252 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
10253 proto_templ->Set(v8_str("method"), method_templ);
mmassi@chromium.org49a44672012-12-04 13:52:03 +000010254 fun_templ->SetHiddenPrototype(true);
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000010255 v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
10256 templ->SetNamedPropertyHandler(InterceptorCallICFastApi,
10257 NULL, NULL, NULL, NULL,
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000010258 v8::External::New(&interceptor_call_count));
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000010259 LocalContext context;
10260 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
10261 GenerateSomeGarbage();
10262 context->Global()->Set(v8_str("o"), fun->NewInstance());
10263 v8::TryCatch try_catch;
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000010264 CompileRun(
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000010265 "o.foo = 17;"
10266 "var receiver = {};"
10267 "receiver.__proto__ = o;"
10268 "var result = 0;"
10269 "var saved_result = 0;"
10270 "for (var i = 0; i < 100; i++) {"
10271 " result = receiver.method(41);"
10272 " if (i == 50) {"
10273 " saved_result = result;"
10274 " receiver = 333;"
10275 " }"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000010276 "}");
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000010277 CHECK(try_catch.HasCaught());
10278 CHECK_EQ(v8_str("TypeError: Object 333 has no method 'method'"),
10279 try_catch.Exception()->ToString());
10280 CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
10281 CHECK_GE(interceptor_call_count, 50);
10282}
10283
ager@chromium.org5c838252010-02-19 08:53:10 +000010284THREADED_TEST(InterceptorCallICFastApi_SimpleSignature_TypeError) {
10285 int interceptor_call_count = 0;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000010286 v8::HandleScope scope(v8::Isolate::GetCurrent());
ager@chromium.org5c838252010-02-19 08:53:10 +000010287 v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
10288 v8::Handle<v8::FunctionTemplate> method_templ =
10289 v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
10290 v8_str("method_data"),
10291 v8::Signature::New(fun_templ));
10292 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
10293 proto_templ->Set(v8_str("method"), method_templ);
mmassi@chromium.org49a44672012-12-04 13:52:03 +000010294 fun_templ->SetHiddenPrototype(true);
ager@chromium.org5c838252010-02-19 08:53:10 +000010295 v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
10296 templ->SetNamedPropertyHandler(InterceptorCallICFastApi,
10297 NULL, NULL, NULL, NULL,
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000010298 v8::External::New(&interceptor_call_count));
ager@chromium.org5c838252010-02-19 08:53:10 +000010299 LocalContext context;
10300 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
10301 GenerateSomeGarbage();
10302 context->Global()->Set(v8_str("o"), fun->NewInstance());
10303 v8::TryCatch try_catch;
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000010304 CompileRun(
ager@chromium.org5c838252010-02-19 08:53:10 +000010305 "o.foo = 17;"
10306 "var receiver = {};"
10307 "receiver.__proto__ = o;"
10308 "var result = 0;"
10309 "var saved_result = 0;"
10310 "for (var i = 0; i < 100; i++) {"
10311 " result = receiver.method(41);"
10312 " if (i == 50) {"
10313 " saved_result = result;"
10314 " receiver = {method: receiver.method};"
10315 " }"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000010316 "}");
ager@chromium.org5c838252010-02-19 08:53:10 +000010317 CHECK(try_catch.HasCaught());
10318 CHECK_EQ(v8_str("TypeError: Illegal invocation"),
10319 try_catch.Exception()->ToString());
10320 CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
10321 CHECK_GE(interceptor_call_count, 50);
10322}
10323
10324THREADED_TEST(CallICFastApi_TrivialSignature) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000010325 v8::HandleScope scope(v8::Isolate::GetCurrent());
ager@chromium.org5c838252010-02-19 08:53:10 +000010326 v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
10327 v8::Handle<v8::FunctionTemplate> method_templ =
10328 v8::FunctionTemplate::New(FastApiCallback_TrivialSignature,
10329 v8_str("method_data"),
10330 v8::Handle<v8::Signature>());
10331 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
10332 proto_templ->Set(v8_str("method"), method_templ);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000010333 v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000010334 USE(templ);
ager@chromium.org5c838252010-02-19 08:53:10 +000010335 LocalContext context;
10336 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
10337 GenerateSomeGarbage();
10338 context->Global()->Set(v8_str("o"), fun->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000010339 CompileRun(
ager@chromium.org5c838252010-02-19 08:53:10 +000010340 "var result = 0;"
10341 "for (var i = 0; i < 100; i++) {"
10342 " result = o.method(41);"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000010343 "}");
ager@chromium.org5c838252010-02-19 08:53:10 +000010344
10345 CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
10346}
10347
10348THREADED_TEST(CallICFastApi_SimpleSignature) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000010349 v8::HandleScope scope(v8::Isolate::GetCurrent());
ager@chromium.org5c838252010-02-19 08:53:10 +000010350 v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
10351 v8::Handle<v8::FunctionTemplate> method_templ =
10352 v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
10353 v8_str("method_data"),
10354 v8::Signature::New(fun_templ));
10355 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
10356 proto_templ->Set(v8_str("method"), method_templ);
mmassi@chromium.org49a44672012-12-04 13:52:03 +000010357 fun_templ->SetHiddenPrototype(true);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000010358 v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000010359 CHECK(!templ.IsEmpty());
ager@chromium.org5c838252010-02-19 08:53:10 +000010360 LocalContext context;
10361 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
10362 GenerateSomeGarbage();
10363 context->Global()->Set(v8_str("o"), fun->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000010364 CompileRun(
ager@chromium.org5c838252010-02-19 08:53:10 +000010365 "o.foo = 17;"
10366 "var receiver = {};"
10367 "receiver.__proto__ = o;"
10368 "var result = 0;"
10369 "for (var i = 0; i < 100; i++) {"
10370 " result = receiver.method(41);"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000010371 "}");
ager@chromium.org5c838252010-02-19 08:53:10 +000010372
10373 CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
10374}
10375
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000010376THREADED_TEST(CallICFastApi_SimpleSignature_Miss1) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000010377 v8::HandleScope scope(v8::Isolate::GetCurrent());
ager@chromium.org5c838252010-02-19 08:53:10 +000010378 v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
10379 v8::Handle<v8::FunctionTemplate> method_templ =
10380 v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
10381 v8_str("method_data"),
10382 v8::Signature::New(fun_templ));
10383 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
10384 proto_templ->Set(v8_str("method"), method_templ);
mmassi@chromium.org49a44672012-12-04 13:52:03 +000010385 fun_templ->SetHiddenPrototype(true);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000010386 v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000010387 CHECK(!templ.IsEmpty());
ager@chromium.org5c838252010-02-19 08:53:10 +000010388 LocalContext context;
10389 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
10390 GenerateSomeGarbage();
10391 context->Global()->Set(v8_str("o"), fun->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000010392 CompileRun(
ager@chromium.org5c838252010-02-19 08:53:10 +000010393 "o.foo = 17;"
10394 "var receiver = {};"
10395 "receiver.__proto__ = o;"
10396 "var result = 0;"
10397 "var saved_result = 0;"
10398 "for (var i = 0; i < 100; i++) {"
10399 " result = receiver.method(41);"
10400 " if (i == 50) {"
10401 " saved_result = result;"
10402 " receiver = {method: function(x) { return x - 1 }};"
10403 " }"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000010404 "}");
ager@chromium.org5c838252010-02-19 08:53:10 +000010405 CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
10406 CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
10407}
10408
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000010409THREADED_TEST(CallICFastApi_SimpleSignature_Miss2) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000010410 v8::HandleScope scope(v8::Isolate::GetCurrent());
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000010411 v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
10412 v8::Handle<v8::FunctionTemplate> method_templ =
10413 v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
10414 v8_str("method_data"),
10415 v8::Signature::New(fun_templ));
10416 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
10417 proto_templ->Set(v8_str("method"), method_templ);
mmassi@chromium.org49a44672012-12-04 13:52:03 +000010418 fun_templ->SetHiddenPrototype(true);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000010419 v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000010420 CHECK(!templ.IsEmpty());
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000010421 LocalContext context;
10422 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
10423 GenerateSomeGarbage();
10424 context->Global()->Set(v8_str("o"), fun->NewInstance());
10425 v8::TryCatch try_catch;
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000010426 CompileRun(
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000010427 "o.foo = 17;"
10428 "var receiver = {};"
10429 "receiver.__proto__ = o;"
10430 "var result = 0;"
10431 "var saved_result = 0;"
10432 "for (var i = 0; i < 100; i++) {"
10433 " result = receiver.method(41);"
10434 " if (i == 50) {"
10435 " saved_result = result;"
10436 " receiver = 333;"
10437 " }"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000010438 "}");
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000010439 CHECK(try_catch.HasCaught());
10440 CHECK_EQ(v8_str("TypeError: Object 333 has no method 'method'"),
10441 try_catch.Exception()->ToString());
10442 CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
10443}
10444
mmassi@chromium.org49a44672012-12-04 13:52:03 +000010445THREADED_TEST(CallICFastApi_SimpleSignature_TypeError) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000010446 v8::HandleScope scope(v8::Isolate::GetCurrent());
mmassi@chromium.org49a44672012-12-04 13:52:03 +000010447 v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
10448 v8::Handle<v8::FunctionTemplate> method_templ =
10449 v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
10450 v8_str("method_data"),
10451 v8::Signature::New(fun_templ));
10452 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
10453 proto_templ->Set(v8_str("method"), method_templ);
10454 fun_templ->SetHiddenPrototype(true);
10455 v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
10456 CHECK(!templ.IsEmpty());
10457 LocalContext context;
10458 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
10459 GenerateSomeGarbage();
10460 context->Global()->Set(v8_str("o"), fun->NewInstance());
10461 v8::TryCatch try_catch;
10462 CompileRun(
10463 "o.foo = 17;"
10464 "var receiver = {};"
10465 "receiver.__proto__ = o;"
10466 "var result = 0;"
10467 "var saved_result = 0;"
10468 "for (var i = 0; i < 100; i++) {"
10469 " result = receiver.method(41);"
10470 " if (i == 50) {"
10471 " saved_result = result;"
10472 " receiver = Object.create(receiver);"
10473 " }"
10474 "}");
10475 CHECK(try_catch.HasCaught());
10476 CHECK_EQ(v8_str("TypeError: Illegal invocation"),
10477 try_catch.Exception()->ToString());
10478 CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
10479}
10480
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000010481
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000010482v8::Handle<Value> keyed_call_ic_function;
10483
10484static v8::Handle<Value> InterceptorKeyedCallICGetter(
10485 Local<String> name, const AccessorInfo& info) {
10486 ApiTestFuzzer::Fuzz();
10487 if (v8_str("x")->Equals(name)) {
10488 return keyed_call_ic_function;
10489 }
10490 return v8::Handle<Value>();
10491}
10492
10493
10494// Test the case when we stored cacheable lookup into
10495// a stub, but the function name changed (to another cacheable function).
10496THREADED_TEST(InterceptorKeyedCallICKeyChange1) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000010497 v8::HandleScope scope(v8::Isolate::GetCurrent());
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000010498 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
10499 templ->SetNamedPropertyHandler(NoBlockGetterX);
10500 LocalContext context;
10501 context->Global()->Set(v8_str("o"), templ->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000010502 CompileRun(
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000010503 "proto = new Object();"
10504 "proto.y = function(x) { return x + 1; };"
10505 "proto.z = function(x) { return x - 1; };"
10506 "o.__proto__ = proto;"
10507 "var result = 0;"
10508 "var method = 'y';"
10509 "for (var i = 0; i < 10; i++) {"
10510 " if (i == 5) { method = 'z'; };"
10511 " result += o[method](41);"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000010512 "}");
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000010513 CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
10514}
10515
10516
10517// Test the case when we stored cacheable lookup into
10518// a stub, but the function name changed (and the new function is present
10519// both before and after the interceptor in the prototype chain).
10520THREADED_TEST(InterceptorKeyedCallICKeyChange2) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000010521 v8::HandleScope scope(v8::Isolate::GetCurrent());
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000010522 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
10523 templ->SetNamedPropertyHandler(InterceptorKeyedCallICGetter);
10524 LocalContext context;
10525 context->Global()->Set(v8_str("proto1"), templ->NewInstance());
10526 keyed_call_ic_function =
10527 v8_compile("function f(x) { return x - 1; }; f")->Run();
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000010528 CompileRun(
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000010529 "o = new Object();"
10530 "proto2 = new Object();"
10531 "o.y = function(x) { return x + 1; };"
10532 "proto2.y = function(x) { return x + 2; };"
10533 "o.__proto__ = proto1;"
10534 "proto1.__proto__ = proto2;"
10535 "var result = 0;"
10536 "var method = 'x';"
10537 "for (var i = 0; i < 10; i++) {"
10538 " if (i == 5) { method = 'y'; };"
10539 " result += o[method](41);"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000010540 "}");
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000010541 CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
10542}
10543
10544
10545// Same as InterceptorKeyedCallICKeyChange1 only the cacheable function sit
10546// on the global object.
10547THREADED_TEST(InterceptorKeyedCallICKeyChangeOnGlobal) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000010548 v8::HandleScope scope(v8::Isolate::GetCurrent());
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000010549 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
10550 templ->SetNamedPropertyHandler(NoBlockGetterX);
10551 LocalContext context;
10552 context->Global()->Set(v8_str("o"), templ->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000010553 CompileRun(
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000010554 "function inc(x) { return x + 1; };"
10555 "inc(1);"
10556 "function dec(x) { return x - 1; };"
10557 "dec(1);"
10558 "o.__proto__ = this;"
10559 "this.__proto__.x = inc;"
10560 "this.__proto__.y = dec;"
10561 "var result = 0;"
10562 "var method = 'x';"
10563 "for (var i = 0; i < 10; i++) {"
10564 " if (i == 5) { method = 'y'; };"
10565 " result += o[method](41);"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000010566 "}");
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000010567 CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
10568}
10569
10570
10571// Test the case when actual function to call sits on global object.
10572THREADED_TEST(InterceptorKeyedCallICFromGlobal) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000010573 v8::HandleScope scope(v8::Isolate::GetCurrent());
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000010574 v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
10575 templ_o->SetNamedPropertyHandler(NoBlockGetterX);
10576 LocalContext context;
10577 context->Global()->Set(v8_str("o"), templ_o->NewInstance());
10578
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000010579 CompileRun(
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000010580 "function len(x) { return x.length; };"
10581 "o.__proto__ = this;"
10582 "var m = 'parseFloat';"
10583 "var result = 0;"
10584 "for (var i = 0; i < 10; i++) {"
10585 " if (i == 5) {"
10586 " m = 'len';"
10587 " saved_result = result;"
10588 " };"
10589 " result = o[m]('239');"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000010590 "}");
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000010591 CHECK_EQ(3, context->Global()->Get(v8_str("result"))->Int32Value());
10592 CHECK_EQ(239, context->Global()->Get(v8_str("saved_result"))->Int32Value());
10593}
10594
10595// Test the map transition before the interceptor.
10596THREADED_TEST(InterceptorKeyedCallICMapChangeBefore) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000010597 v8::HandleScope scope(v8::Isolate::GetCurrent());
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000010598 v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
10599 templ_o->SetNamedPropertyHandler(NoBlockGetterX);
10600 LocalContext context;
10601 context->Global()->Set(v8_str("proto"), templ_o->NewInstance());
10602
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000010603 CompileRun(
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000010604 "var o = new Object();"
10605 "o.__proto__ = proto;"
10606 "o.method = function(x) { return x + 1; };"
10607 "var m = 'method';"
10608 "var result = 0;"
10609 "for (var i = 0; i < 10; i++) {"
10610 " if (i == 5) { o.method = function(x) { return x - 1; }; };"
10611 " result += o[m](41);"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000010612 "}");
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000010613 CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
10614}
10615
10616
10617// Test the map transition after the interceptor.
10618THREADED_TEST(InterceptorKeyedCallICMapChangeAfter) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000010619 v8::HandleScope scope(v8::Isolate::GetCurrent());
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000010620 v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New();
10621 templ_o->SetNamedPropertyHandler(NoBlockGetterX);
10622 LocalContext context;
10623 context->Global()->Set(v8_str("o"), templ_o->NewInstance());
10624
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000010625 CompileRun(
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000010626 "var proto = new Object();"
10627 "o.__proto__ = proto;"
10628 "proto.method = function(x) { return x + 1; };"
10629 "var m = 'method';"
10630 "var result = 0;"
10631 "for (var i = 0; i < 10; i++) {"
10632 " if (i == 5) { proto.method = function(x) { return x - 1; }; };"
10633 " result += o[m](41);"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000010634 "}");
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000010635 CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
10636}
10637
10638
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010639static int interceptor_call_count = 0;
10640
10641static v8::Handle<Value> InterceptorICRefErrorGetter(Local<String> name,
10642 const AccessorInfo& info) {
10643 ApiTestFuzzer::Fuzz();
10644 if (v8_str("x")->Equals(name) && interceptor_call_count++ < 20) {
10645 return call_ic_function2;
10646 }
10647 return v8::Handle<Value>();
10648}
10649
10650
10651// This test should hit load and call ICs for the interceptor case.
10652// Once in a while, the interceptor will reply that a property was not
10653// found in which case we should get a reference error.
10654THREADED_TEST(InterceptorICReferenceErrors) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000010655 v8::HandleScope scope(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010656 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
10657 templ->SetNamedPropertyHandler(InterceptorICRefErrorGetter);
10658 LocalContext context(0, templ, v8::Handle<Value>());
10659 call_ic_function2 = v8_compile("function h(x) { return x; }; h")->Run();
10660 v8::Handle<Value> value = CompileRun(
10661 "function f() {"
10662 " for (var i = 0; i < 1000; i++) {"
10663 " try { x; } catch(e) { return true; }"
10664 " }"
10665 " return false;"
10666 "};"
10667 "f();");
10668 CHECK_EQ(true, value->BooleanValue());
10669 interceptor_call_count = 0;
10670 value = CompileRun(
10671 "function g() {"
10672 " for (var i = 0; i < 1000; i++) {"
10673 " try { x(42); } catch(e) { return true; }"
10674 " }"
10675 " return false;"
10676 "};"
10677 "g();");
10678 CHECK_EQ(true, value->BooleanValue());
10679}
10680
10681
10682static int interceptor_ic_exception_get_count = 0;
10683
10684static v8::Handle<Value> InterceptorICExceptionGetter(
10685 Local<String> name,
10686 const AccessorInfo& info) {
10687 ApiTestFuzzer::Fuzz();
10688 if (v8_str("x")->Equals(name) && ++interceptor_ic_exception_get_count < 20) {
10689 return call_ic_function3;
10690 }
10691 if (interceptor_ic_exception_get_count == 20) {
10692 return v8::ThrowException(v8_num(42));
10693 }
10694 // Do not handle get for properties other than x.
10695 return v8::Handle<Value>();
10696}
10697
10698// Test interceptor load/call IC where the interceptor throws an
10699// exception once in a while.
10700THREADED_TEST(InterceptorICGetterExceptions) {
10701 interceptor_ic_exception_get_count = 0;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000010702 v8::HandleScope scope(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010703 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
10704 templ->SetNamedPropertyHandler(InterceptorICExceptionGetter);
10705 LocalContext context(0, templ, v8::Handle<Value>());
10706 call_ic_function3 = v8_compile("function h(x) { return x; }; h")->Run();
10707 v8::Handle<Value> value = CompileRun(
10708 "function f() {"
10709 " for (var i = 0; i < 100; i++) {"
10710 " try { x; } catch(e) { return true; }"
10711 " }"
10712 " return false;"
10713 "};"
10714 "f();");
10715 CHECK_EQ(true, value->BooleanValue());
10716 interceptor_ic_exception_get_count = 0;
10717 value = CompileRun(
10718 "function f() {"
10719 " for (var i = 0; i < 100; i++) {"
10720 " try { x(42); } catch(e) { return true; }"
10721 " }"
10722 " return false;"
10723 "};"
10724 "f();");
10725 CHECK_EQ(true, value->BooleanValue());
10726}
10727
10728
10729static int interceptor_ic_exception_set_count = 0;
10730
10731static v8::Handle<Value> InterceptorICExceptionSetter(
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000010732 Local<String> key, Local<Value> value, const AccessorInfo&) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010733 ApiTestFuzzer::Fuzz();
10734 if (++interceptor_ic_exception_set_count > 20) {
10735 return v8::ThrowException(v8_num(42));
10736 }
10737 // Do not actually handle setting.
10738 return v8::Handle<Value>();
10739}
10740
10741// Test interceptor store IC where the interceptor throws an exception
10742// once in a while.
10743THREADED_TEST(InterceptorICSetterExceptions) {
10744 interceptor_ic_exception_set_count = 0;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000010745 v8::HandleScope scope(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010746 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
10747 templ->SetNamedPropertyHandler(0, InterceptorICExceptionSetter);
10748 LocalContext context(0, templ, v8::Handle<Value>());
10749 v8::Handle<Value> value = CompileRun(
10750 "function f() {"
10751 " for (var i = 0; i < 100; i++) {"
10752 " try { x = 42; } catch(e) { return true; }"
10753 " }"
10754 " return false;"
10755 "};"
10756 "f();");
10757 CHECK_EQ(true, value->BooleanValue());
10758}
10759
10760
10761// Test that we ignore null interceptors.
10762THREADED_TEST(NullNamedInterceptor) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000010763 v8::HandleScope scope(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010764 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
10765 templ->SetNamedPropertyHandler(0);
10766 LocalContext context;
10767 templ->Set("x", v8_num(42));
10768 v8::Handle<v8::Object> obj = templ->NewInstance();
10769 context->Global()->Set(v8_str("obj"), obj);
10770 v8::Handle<Value> value = CompileRun("obj.x");
10771 CHECK(value->IsInt32());
10772 CHECK_EQ(42, value->Int32Value());
10773}
10774
10775
10776// Test that we ignore null interceptors.
10777THREADED_TEST(NullIndexedInterceptor) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000010778 v8::HandleScope scope(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010779 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
10780 templ->SetIndexedPropertyHandler(0);
10781 LocalContext context;
10782 templ->Set("42", v8_num(42));
10783 v8::Handle<v8::Object> obj = templ->NewInstance();
10784 context->Global()->Set(v8_str("obj"), obj);
10785 v8::Handle<Value> value = CompileRun("obj[42]");
10786 CHECK(value->IsInt32());
10787 CHECK_EQ(42, value->Int32Value());
10788}
10789
10790
ricow@chromium.org30ce4112010-05-31 10:38:25 +000010791THREADED_TEST(NamedPropertyHandlerGetterAttributes) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000010792 v8::HandleScope scope(v8::Isolate::GetCurrent());
ricow@chromium.org30ce4112010-05-31 10:38:25 +000010793 v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
10794 templ->InstanceTemplate()->SetNamedPropertyHandler(InterceptorLoadXICGetter);
10795 LocalContext env;
10796 env->Global()->Set(v8_str("obj"),
10797 templ->GetFunction()->NewInstance());
10798 ExpectTrue("obj.x === 42");
10799 ExpectTrue("!obj.propertyIsEnumerable('x')");
10800}
10801
10802
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000010803static Handle<Value> ThrowingGetter(Local<String> name,
10804 const AccessorInfo& info) {
10805 ApiTestFuzzer::Fuzz();
10806 ThrowException(Handle<Value>());
10807 return Undefined();
10808}
10809
10810
10811THREADED_TEST(VariousGetPropertiesAndThrowingCallbacks) {
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000010812 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000010813 HandleScope scope(context->GetIsolate());
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000010814
10815 Local<FunctionTemplate> templ = FunctionTemplate::New();
10816 Local<ObjectTemplate> instance_templ = templ->InstanceTemplate();
10817 instance_templ->SetAccessor(v8_str("f"), ThrowingGetter);
10818
10819 Local<Object> instance = templ->GetFunction()->NewInstance();
10820
10821 Local<Object> another = Object::New();
10822 another->SetPrototype(instance);
10823
10824 Local<Object> with_js_getter = CompileRun(
10825 "o = {};\n"
10826 "o.__defineGetter__('f', function() { throw undefined; });\n"
10827 "o\n").As<Object>();
10828 CHECK(!with_js_getter.IsEmpty());
10829
10830 TryCatch try_catch;
10831
10832 Local<Value> result = instance->GetRealNamedProperty(v8_str("f"));
10833 CHECK(try_catch.HasCaught());
10834 try_catch.Reset();
10835 CHECK(result.IsEmpty());
10836
10837 result = another->GetRealNamedProperty(v8_str("f"));
10838 CHECK(try_catch.HasCaught());
10839 try_catch.Reset();
10840 CHECK(result.IsEmpty());
10841
10842 result = another->GetRealNamedPropertyInPrototypeChain(v8_str("f"));
10843 CHECK(try_catch.HasCaught());
10844 try_catch.Reset();
10845 CHECK(result.IsEmpty());
10846
10847 result = another->Get(v8_str("f"));
10848 CHECK(try_catch.HasCaught());
10849 try_catch.Reset();
10850 CHECK(result.IsEmpty());
10851
10852 result = with_js_getter->GetRealNamedProperty(v8_str("f"));
10853 CHECK(try_catch.HasCaught());
10854 try_catch.Reset();
10855 CHECK(result.IsEmpty());
10856
10857 result = with_js_getter->Get(v8_str("f"));
10858 CHECK(try_catch.HasCaught());
10859 try_catch.Reset();
10860 CHECK(result.IsEmpty());
10861}
10862
10863
10864static Handle<Value> ThrowingCallbackWithTryCatch(const Arguments& args) {
10865 TryCatch try_catch;
10866 // Verboseness is important: it triggers message delivery which can call into
10867 // external code.
10868 try_catch.SetVerbose(true);
10869 CompileRun("throw 'from JS';");
10870 CHECK(try_catch.HasCaught());
10871 CHECK(!i::Isolate::Current()->has_pending_exception());
10872 CHECK(!i::Isolate::Current()->has_scheduled_exception());
10873 return Undefined();
10874}
10875
10876
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +000010877static int call_depth;
10878
10879
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000010880static void WithTryCatch(Handle<Message> message, Handle<Value> data) {
10881 TryCatch try_catch;
10882}
10883
10884
10885static void ThrowFromJS(Handle<Message> message, Handle<Value> data) {
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +000010886 if (--call_depth) CompileRun("throw 'ThrowInJS';");
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000010887}
10888
10889
10890static void ThrowViaApi(Handle<Message> message, Handle<Value> data) {
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +000010891 if (--call_depth) ThrowException(v8_str("ThrowViaApi"));
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000010892}
10893
10894
10895static void WebKitLike(Handle<Message> message, Handle<Value> data) {
10896 Handle<String> errorMessageString = message->Get();
10897 CHECK(!errorMessageString.IsEmpty());
10898 message->GetStackTrace();
10899 message->GetScriptResourceName();
10900}
10901
10902THREADED_TEST(ExceptionsDoNotPropagatePastTryCatch) {
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000010903 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000010904 HandleScope scope(context->GetIsolate());
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000010905
10906 Local<Function> func =
10907 FunctionTemplate::New(ThrowingCallbackWithTryCatch)->GetFunction();
10908 context->Global()->Set(v8_str("func"), func);
10909
10910 MessageCallback callbacks[] =
10911 { NULL, WebKitLike, ThrowViaApi, ThrowFromJS, WithTryCatch };
10912 for (unsigned i = 0; i < sizeof(callbacks)/sizeof(callbacks[0]); i++) {
10913 MessageCallback callback = callbacks[i];
10914 if (callback != NULL) {
10915 V8::AddMessageListener(callback);
10916 }
ricow@chromium.orgdcebac02011-04-20 09:44:50 +000010917 // Some small number to control number of times message handler should
10918 // throw an exception.
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +000010919 call_depth = 5;
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000010920 ExpectFalse(
10921 "var thrown = false;\n"
10922 "try { func(); } catch(e) { thrown = true; }\n"
10923 "thrown\n");
10924 if (callback != NULL) {
10925 V8::RemoveMessageListeners(callback);
10926 }
10927 }
10928}
10929
10930
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010931static v8::Handle<Value> ParentGetter(Local<String> name,
10932 const AccessorInfo& info) {
10933 ApiTestFuzzer::Fuzz();
10934 return v8_num(1);
10935}
10936
10937
10938static v8::Handle<Value> ChildGetter(Local<String> name,
10939 const AccessorInfo& info) {
10940 ApiTestFuzzer::Fuzz();
10941 return v8_num(42);
10942}
10943
10944
10945THREADED_TEST(Overriding) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +000010946 i::FLAG_es5_readonly = true;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010947 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000010948 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010949
10950 // Parent template.
10951 Local<v8::FunctionTemplate> parent_templ = v8::FunctionTemplate::New();
10952 Local<ObjectTemplate> parent_instance_templ =
10953 parent_templ->InstanceTemplate();
10954 parent_instance_templ->SetAccessor(v8_str("f"), ParentGetter);
10955
10956 // Template that inherits from the parent template.
10957 Local<v8::FunctionTemplate> child_templ = v8::FunctionTemplate::New();
10958 Local<ObjectTemplate> child_instance_templ =
10959 child_templ->InstanceTemplate();
10960 child_templ->Inherit(parent_templ);
10961 // Override 'f'. The child version of 'f' should get called for child
10962 // instances.
10963 child_instance_templ->SetAccessor(v8_str("f"), ChildGetter);
10964 // Add 'g' twice. The 'g' added last should get called for instances.
10965 child_instance_templ->SetAccessor(v8_str("g"), ParentGetter);
10966 child_instance_templ->SetAccessor(v8_str("g"), ChildGetter);
10967
10968 // Add 'h' as an accessor to the proto template with ReadOnly attributes
10969 // so 'h' can be shadowed on the instance object.
10970 Local<ObjectTemplate> child_proto_templ = child_templ->PrototypeTemplate();
10971 child_proto_templ->SetAccessor(v8_str("h"), ParentGetter, 0,
10972 v8::Handle<Value>(), v8::DEFAULT, v8::ReadOnly);
10973
10974 // Add 'i' as an accessor to the instance template with ReadOnly attributes
10975 // but the attribute does not have effect because it is duplicated with
10976 // NULL setter.
10977 child_instance_templ->SetAccessor(v8_str("i"), ChildGetter, 0,
10978 v8::Handle<Value>(), v8::DEFAULT, v8::ReadOnly);
10979
10980
10981
10982 // Instantiate the child template.
10983 Local<v8::Object> instance = child_templ->GetFunction()->NewInstance();
10984
10985 // Check that the child function overrides the parent one.
10986 context->Global()->Set(v8_str("o"), instance);
10987 Local<Value> value = v8_compile("o.f")->Run();
10988 // Check that the 'g' that was added last is hit.
10989 CHECK_EQ(42, value->Int32Value());
10990 value = v8_compile("o.g")->Run();
10991 CHECK_EQ(42, value->Int32Value());
10992
mmassi@chromium.org7028c052012-06-13 11:51:58 +000010993 // Check that 'h' cannot be shadowed.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010994 value = v8_compile("o.h = 3; o.h")->Run();
mmassi@chromium.org7028c052012-06-13 11:51:58 +000010995 CHECK_EQ(1, value->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010996
mmassi@chromium.org7028c052012-06-13 11:51:58 +000010997 // Check that 'i' cannot be shadowed or changed.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010998 value = v8_compile("o.i = 3; o.i")->Run();
10999 CHECK_EQ(42, value->Int32Value());
11000}
11001
11002
11003static v8::Handle<Value> IsConstructHandler(const v8::Arguments& args) {
11004 ApiTestFuzzer::Fuzz();
yangguo@chromium.org80c42ed2011-08-31 09:03:56 +000011005 return v8::Boolean::New(args.IsConstructCall());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011006}
11007
11008
11009THREADED_TEST(IsConstructCall) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000011010 v8::HandleScope scope(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011011
11012 // Function template with call handler.
11013 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
11014 templ->SetCallHandler(IsConstructHandler);
11015
11016 LocalContext context;
11017
11018 context->Global()->Set(v8_str("f"), templ->GetFunction());
11019 Local<Value> value = v8_compile("f()")->Run();
11020 CHECK(!value->BooleanValue());
11021 value = v8_compile("new f()")->Run();
11022 CHECK(value->BooleanValue());
11023}
11024
11025
11026THREADED_TEST(ObjectProtoToString) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000011027 v8::HandleScope scope(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011028 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
11029 templ->SetClassName(v8_str("MyClass"));
11030
11031 LocalContext context;
11032
11033 Local<String> customized_tostring = v8_str("customized toString");
11034
11035 // Replace Object.prototype.toString
11036 v8_compile("Object.prototype.toString = function() {"
11037 " return 'customized toString';"
11038 "}")->Run();
11039
11040 // Normal ToString call should call replaced Object.prototype.toString
11041 Local<v8::Object> instance = templ->GetFunction()->NewInstance();
11042 Local<String> value = instance->ToString();
11043 CHECK(value->IsString() && value->Equals(customized_tostring));
11044
11045 // ObjectProtoToString should not call replace toString function.
11046 value = instance->ObjectProtoToString();
11047 CHECK(value->IsString() && value->Equals(v8_str("[object MyClass]")));
11048
11049 // Check global
11050 value = context->Global()->ObjectProtoToString();
11051 CHECK(value->IsString() && value->Equals(v8_str("[object global]")));
11052
11053 // Check ordinary object
11054 Local<Value> object = v8_compile("new Object()")->Run();
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000011055 value = object.As<v8::Object>()->ObjectProtoToString();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011056 CHECK(value->IsString() && value->Equals(v8_str("[object Object]")));
11057}
11058
11059
ager@chromium.orgbeb25712010-11-29 08:02:25 +000011060THREADED_TEST(ObjectGetConstructorName) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +000011061 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000011062 v8::HandleScope scope(context->GetIsolate());
ager@chromium.orgbeb25712010-11-29 08:02:25 +000011063 v8_compile("function Parent() {};"
11064 "function Child() {};"
11065 "Child.prototype = new Parent();"
11066 "var outer = { inner: function() { } };"
11067 "var p = new Parent();"
11068 "var c = new Child();"
11069 "var x = new outer.inner();")->Run();
11070
11071 Local<v8::Value> p = context->Global()->Get(v8_str("p"));
11072 CHECK(p->IsObject() && p->ToObject()->GetConstructorName()->Equals(
11073 v8_str("Parent")));
11074
11075 Local<v8::Value> c = context->Global()->Get(v8_str("c"));
11076 CHECK(c->IsObject() && c->ToObject()->GetConstructorName()->Equals(
11077 v8_str("Child")));
11078
11079 Local<v8::Value> x = context->Global()->Get(v8_str("x"));
11080 CHECK(x->IsObject() && x->ToObject()->GetConstructorName()->Equals(
11081 v8_str("outer.inner")));
11082}
11083
11084
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011085bool ApiTestFuzzer::fuzzing_ = false;
lrn@chromium.org32d961d2010-06-30 09:09:34 +000011086i::Semaphore* ApiTestFuzzer::all_tests_done_=
11087 i::OS::CreateSemaphore(0);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011088int ApiTestFuzzer::active_tests_;
11089int ApiTestFuzzer::tests_being_run_;
11090int ApiTestFuzzer::current_;
11091
11092
11093// We are in a callback and want to switch to another thread (if we
11094// are currently running the thread fuzzing test).
11095void ApiTestFuzzer::Fuzz() {
11096 if (!fuzzing_) return;
11097 ApiTestFuzzer* test = RegisterThreadedTest::nth(current_)->fuzzer_;
11098 test->ContextSwitch();
11099}
11100
11101
11102// Let the next thread go. Since it is also waiting on the V8 lock it may
11103// not start immediately.
11104bool ApiTestFuzzer::NextThread() {
11105 int test_position = GetNextTestNumber();
ager@chromium.orgc4c92722009-11-18 14:12:51 +000011106 const char* test_name = RegisterThreadedTest::nth(current_)->name();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011107 if (test_position == current_) {
ager@chromium.orgc4c92722009-11-18 14:12:51 +000011108 if (kLogThreading)
11109 printf("Stay with %s\n", test_name);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011110 return false;
11111 }
ager@chromium.orgc4c92722009-11-18 14:12:51 +000011112 if (kLogThreading) {
11113 printf("Switch from %s to %s\n",
11114 test_name,
11115 RegisterThreadedTest::nth(test_position)->name());
11116 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011117 current_ = test_position;
11118 RegisterThreadedTest::nth(current_)->fuzzer_->gate_->Signal();
11119 return true;
11120}
11121
11122
11123void ApiTestFuzzer::Run() {
11124 // When it is our turn...
11125 gate_->Wait();
11126 {
11127 // ... get the V8 lock and start running the test.
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000011128 v8::Locker locker(CcTest::default_isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011129 CallTest();
11130 }
11131 // This test finished.
11132 active_ = false;
11133 active_tests_--;
11134 // If it was the last then signal that fact.
11135 if (active_tests_ == 0) {
11136 all_tests_done_->Signal();
11137 } else {
11138 // Otherwise select a new test and start that.
11139 NextThread();
11140 }
11141}
11142
11143
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011144static unsigned linear_congruential_generator;
11145
11146
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000011147void ApiTestFuzzer::SetUp(PartOfTest part) {
kasperl@chromium.orgb9123622008-09-17 14:05:56 +000011148 linear_congruential_generator = i::FLAG_testing_prng_seed;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011149 fuzzing_ = true;
lrn@chromium.org1c092762011-05-09 09:42:16 +000011150 int count = RegisterThreadedTest::count();
11151 int start = count * part / (LAST_PART + 1);
11152 int end = (count * (part + 1) / (LAST_PART + 1)) - 1;
11153 active_tests_ = tests_being_run_ = end - start + 1;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011154 for (int i = 0; i < tests_being_run_; i++) {
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000011155 RegisterThreadedTest::nth(i)->fuzzer_ = new ApiTestFuzzer(i + start);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011156 }
11157 for (int i = 0; i < active_tests_; i++) {
11158 RegisterThreadedTest::nth(i)->fuzzer_->Start();
11159 }
11160}
11161
11162
11163static void CallTestNumber(int test_number) {
11164 (RegisterThreadedTest::nth(test_number)->callback())();
11165}
11166
11167
11168void ApiTestFuzzer::RunAllTests() {
11169 // Set off the first test.
11170 current_ = -1;
11171 NextThread();
11172 // Wait till they are all done.
11173 all_tests_done_->Wait();
11174}
11175
11176
11177int ApiTestFuzzer::GetNextTestNumber() {
11178 int next_test;
11179 do {
11180 next_test = (linear_congruential_generator >> 16) % tests_being_run_;
11181 linear_congruential_generator *= 1664525u;
11182 linear_congruential_generator += 1013904223u;
11183 } while (!RegisterThreadedTest::nth(next_test)->fuzzer_->active_);
11184 return next_test;
11185}
11186
11187
11188void ApiTestFuzzer::ContextSwitch() {
11189 // If the new thread is the same as the current thread there is nothing to do.
11190 if (NextThread()) {
11191 // Now it can start.
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000011192 v8::Unlocker unlocker(CcTest::default_isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011193 // Wait till someone starts us again.
11194 gate_->Wait();
11195 // And we're off.
11196 }
11197}
11198
11199
11200void ApiTestFuzzer::TearDown() {
11201 fuzzing_ = false;
ager@chromium.org41826e72009-03-30 13:30:57 +000011202 for (int i = 0; i < RegisterThreadedTest::count(); i++) {
11203 ApiTestFuzzer *fuzzer = RegisterThreadedTest::nth(i)->fuzzer_;
11204 if (fuzzer != NULL) fuzzer->Join();
11205 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011206}
11207
11208
11209// Lets not be needlessly self-referential.
mmassi@chromium.org2f0efde2013-02-06 14:12:58 +000011210TEST(Threading1) {
11211 // TODO(mstarzinger): Disabled in GC stress mode for now, we should find the
11212 // correct timeout for this an re-enable this test again
11213 if (i::FLAG_stress_compaction) return;
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000011214 ApiTestFuzzer::SetUp(ApiTestFuzzer::FIRST_PART);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011215 ApiTestFuzzer::RunAllTests();
11216 ApiTestFuzzer::TearDown();
11217}
11218
11219TEST(Threading2) {
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000011220 ApiTestFuzzer::SetUp(ApiTestFuzzer::SECOND_PART);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011221 ApiTestFuzzer::RunAllTests();
11222 ApiTestFuzzer::TearDown();
11223}
11224
lrn@chromium.org1c092762011-05-09 09:42:16 +000011225TEST(Threading3) {
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000011226 ApiTestFuzzer::SetUp(ApiTestFuzzer::THIRD_PART);
lrn@chromium.org1c092762011-05-09 09:42:16 +000011227 ApiTestFuzzer::RunAllTests();
11228 ApiTestFuzzer::TearDown();
11229}
11230
11231TEST(Threading4) {
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000011232 ApiTestFuzzer::SetUp(ApiTestFuzzer::FOURTH_PART);
lrn@chromium.org1c092762011-05-09 09:42:16 +000011233 ApiTestFuzzer::RunAllTests();
11234 ApiTestFuzzer::TearDown();
11235}
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011236
11237void ApiTestFuzzer::CallTest() {
ager@chromium.orgc4c92722009-11-18 14:12:51 +000011238 if (kLogThreading)
11239 printf("Start test %d\n", test_number_);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011240 CallTestNumber(test_number_);
ager@chromium.orgc4c92722009-11-18 14:12:51 +000011241 if (kLogThreading)
11242 printf("End test %d\n", test_number_);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011243}
11244
11245
11246static v8::Handle<Value> ThrowInJS(const v8::Arguments& args) {
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000011247 CHECK(v8::Locker::IsLocked(CcTest::default_isolate()));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011248 ApiTestFuzzer::Fuzz();
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000011249 v8::Unlocker unlocker(CcTest::default_isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011250 const char* code = "throw 7;";
11251 {
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000011252 v8::Locker nested_locker(CcTest::default_isolate());
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000011253 v8::HandleScope scope(args.GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011254 v8::Handle<Value> exception;
11255 { v8::TryCatch try_catch;
11256 v8::Handle<Value> value = CompileRun(code);
11257 CHECK(value.IsEmpty());
11258 CHECK(try_catch.HasCaught());
11259 // Make sure to wrap the exception in a new handle because
11260 // the handle returned from the TryCatch is destroyed
11261 // when the TryCatch is destroyed.
11262 exception = Local<Value>::New(try_catch.Exception());
11263 }
11264 return v8::ThrowException(exception);
11265 }
11266}
11267
11268
11269static v8::Handle<Value> ThrowInJSNoCatch(const v8::Arguments& args) {
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000011270 CHECK(v8::Locker::IsLocked(CcTest::default_isolate()));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011271 ApiTestFuzzer::Fuzz();
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000011272 v8::Unlocker unlocker(CcTest::default_isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011273 const char* code = "throw 7;";
11274 {
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000011275 v8::Locker nested_locker(CcTest::default_isolate());
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000011276 v8::HandleScope scope(args.GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011277 v8::Handle<Value> value = CompileRun(code);
11278 CHECK(value.IsEmpty());
11279 return v8_str("foo");
11280 }
11281}
11282
11283
11284// These are locking tests that don't need to be run again
11285// as part of the locking aggregation tests.
11286TEST(NestedLockers) {
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000011287 v8::Locker locker(CcTest::default_isolate());
11288 CHECK(v8::Locker::IsLocked(CcTest::default_isolate()));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011289 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000011290 v8::HandleScope scope(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011291 Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(ThrowInJS);
11292 Local<Function> fun = fun_templ->GetFunction();
11293 env->Global()->Set(v8_str("throw_in_js"), fun);
11294 Local<Script> script = v8_compile("(function () {"
11295 " try {"
11296 " throw_in_js();"
11297 " return 42;"
11298 " } catch (e) {"
11299 " return e * 13;"
11300 " }"
11301 "})();");
11302 CHECK_EQ(91, script->Run()->Int32Value());
11303}
11304
11305
11306// These are locking tests that don't need to be run again
11307// as part of the locking aggregation tests.
11308TEST(NestedLockersNoTryCatch) {
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000011309 v8::Locker locker(CcTest::default_isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011310 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000011311 v8::HandleScope scope(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011312 Local<v8::FunctionTemplate> fun_templ =
11313 v8::FunctionTemplate::New(ThrowInJSNoCatch);
11314 Local<Function> fun = fun_templ->GetFunction();
11315 env->Global()->Set(v8_str("throw_in_js"), fun);
11316 Local<Script> script = v8_compile("(function () {"
11317 " try {"
11318 " throw_in_js();"
11319 " return 42;"
11320 " } catch (e) {"
11321 " return e * 13;"
11322 " }"
11323 "})();");
11324 CHECK_EQ(91, script->Run()->Int32Value());
11325}
11326
11327
11328THREADED_TEST(RecursiveLocking) {
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000011329 v8::Locker locker(CcTest::default_isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011330 {
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000011331 v8::Locker locker2(CcTest::default_isolate());
11332 CHECK(v8::Locker::IsLocked(CcTest::default_isolate()));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011333 }
11334}
11335
11336
11337static v8::Handle<Value> UnlockForAMoment(const v8::Arguments& args) {
11338 ApiTestFuzzer::Fuzz();
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000011339 v8::Unlocker unlocker(CcTest::default_isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011340 return v8::Undefined();
11341}
11342
11343
11344THREADED_TEST(LockUnlockLock) {
11345 {
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000011346 v8::Locker locker(CcTest::default_isolate());
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000011347 v8::HandleScope scope(CcTest::default_isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011348 LocalContext env;
11349 Local<v8::FunctionTemplate> fun_templ =
11350 v8::FunctionTemplate::New(UnlockForAMoment);
11351 Local<Function> fun = fun_templ->GetFunction();
11352 env->Global()->Set(v8_str("unlock_for_a_moment"), fun);
11353 Local<Script> script = v8_compile("(function () {"
11354 " unlock_for_a_moment();"
11355 " return 42;"
11356 "})();");
11357 CHECK_EQ(42, script->Run()->Int32Value());
11358 }
11359 {
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000011360 v8::Locker locker(CcTest::default_isolate());
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000011361 v8::HandleScope scope(CcTest::default_isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011362 LocalContext env;
11363 Local<v8::FunctionTemplate> fun_templ =
11364 v8::FunctionTemplate::New(UnlockForAMoment);
11365 Local<Function> fun = fun_templ->GetFunction();
11366 env->Global()->Set(v8_str("unlock_for_a_moment"), fun);
11367 Local<Script> script = v8_compile("(function () {"
11368 " unlock_for_a_moment();"
11369 " return 42;"
11370 "})();");
11371 CHECK_EQ(42, script->Run()->Int32Value());
11372 }
11373}
11374
11375
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000011376static int GetGlobalObjectsCount() {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000011377 i::Isolate::Current()->heap()->EnsureHeapIsIterable();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011378 int count = 0;
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +000011379 i::HeapIterator it(HEAP);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000011380 for (i::HeapObject* object = it.next(); object != NULL; object = it.next())
11381 if (object->IsJSGlobalObject()) count++;
11382 return count;
11383}
11384
11385
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000011386static void CheckSurvivingGlobalObjectsCount(int expected) {
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +000011387 // We need to collect all garbage twice to be sure that everything
11388 // has been collected. This is because inline caches are cleared in
11389 // the first garbage collection but some of the maps have already
11390 // been marked at that point. Therefore some of the maps are not
11391 // collected until the second garbage collection.
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000011392 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
11393 HEAP->CollectAllGarbage(i::Heap::kMakeHeapIterableMask);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000011394 int count = GetGlobalObjectsCount();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011395#ifdef DEBUG
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000011396 if (count != expected) HEAP->TracePathToGlobal();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011397#endif
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000011398 CHECK_EQ(expected, count);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011399}
11400
11401
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011402TEST(DontLeakGlobalObjects) {
11403 // Regression test for issues 1139850 and 1174891.
11404
kasperl@chromium.orgb9123622008-09-17 14:05:56 +000011405 v8::V8::Initialize();
ager@chromium.org9258b6b2008-09-11 09:11:10 +000011406
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011407 for (int i = 0; i < 5; i++) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000011408 { v8::HandleScope scope(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011409 LocalContext context;
11410 }
svenpanne@chromium.orgc859c4f2012-10-15 11:51:39 +000011411 v8::V8::ContextDisposedNotification();
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000011412 CheckSurvivingGlobalObjectsCount(0);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011413
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000011414 { v8::HandleScope scope(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011415 LocalContext context;
11416 v8_compile("Date")->Run();
11417 }
svenpanne@chromium.orgc859c4f2012-10-15 11:51:39 +000011418 v8::V8::ContextDisposedNotification();
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000011419 CheckSurvivingGlobalObjectsCount(0);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011420
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000011421 { v8::HandleScope scope(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011422 LocalContext context;
11423 v8_compile("/aaa/")->Run();
11424 }
svenpanne@chromium.orgc859c4f2012-10-15 11:51:39 +000011425 v8::V8::ContextDisposedNotification();
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000011426 CheckSurvivingGlobalObjectsCount(0);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011427
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000011428 { v8::HandleScope scope(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011429 const char* extension_list[] = { "v8/gc" };
11430 v8::ExtensionConfiguration extensions(1, extension_list);
11431 LocalContext context(&extensions);
11432 v8_compile("gc();")->Run();
11433 }
svenpanne@chromium.orgc859c4f2012-10-15 11:51:39 +000011434 v8::V8::ContextDisposedNotification();
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000011435 CheckSurvivingGlobalObjectsCount(0);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011436 }
11437}
11438
11439
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000011440v8::Persistent<v8::Object> some_object;
11441v8::Persistent<v8::Object> bad_handle;
11442
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000011443void NewPersistentHandleCallback(v8::Isolate* isolate,
11444 v8::Persistent<v8::Value> handle,
11445 void*) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000011446 v8::HandleScope scope(isolate);
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000011447 bad_handle = v8::Persistent<v8::Object>::New(isolate, some_object);
11448 handle.Dispose(isolate);
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000011449}
11450
11451
11452THREADED_TEST(NewPersistentHandleFromWeakCallback) {
11453 LocalContext context;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000011454 v8::Isolate* isolate = context->GetIsolate();
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000011455
11456 v8::Persistent<v8::Object> handle1, handle2;
11457 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000011458 v8::HandleScope scope(isolate);
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000011459 some_object = v8::Persistent<v8::Object>::New(isolate, v8::Object::New());
11460 handle1 = v8::Persistent<v8::Object>::New(isolate, v8::Object::New());
11461 handle2 = v8::Persistent<v8::Object>::New(isolate, v8::Object::New());
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000011462 }
11463 // Note: order is implementation dependent alas: currently
11464 // global handle nodes are processed by PostGarbageCollectionProcessing
11465 // in reverse allocation order, so if second allocated handle is deleted,
11466 // weak callback of the first handle would be able to 'reallocate' it.
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000011467 handle1.MakeWeak(isolate, NULL, NewPersistentHandleCallback);
11468 handle2.Dispose(isolate);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000011469 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000011470}
11471
11472
11473v8::Persistent<v8::Object> to_be_disposed;
11474
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000011475void DisposeAndForceGcCallback(v8::Isolate* isolate,
11476 v8::Persistent<v8::Value> handle,
11477 void*) {
11478 to_be_disposed.Dispose(isolate);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000011479 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000011480 handle.Dispose(isolate);
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000011481}
11482
11483
11484THREADED_TEST(DoNotUseDeletedNodesInSecondLevelGc) {
11485 LocalContext context;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000011486 v8::Isolate* isolate = context->GetIsolate();
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000011487
11488 v8::Persistent<v8::Object> handle1, handle2;
11489 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000011490 v8::HandleScope scope(isolate);
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000011491 handle1 = v8::Persistent<v8::Object>::New(isolate, v8::Object::New());
11492 handle2 = v8::Persistent<v8::Object>::New(isolate, v8::Object::New());
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000011493 }
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000011494 handle1.MakeWeak(isolate, NULL, DisposeAndForceGcCallback);
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000011495 to_be_disposed = handle2;
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000011496 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000011497}
11498
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000011499void DisposingCallback(v8::Isolate* isolate,
11500 v8::Persistent<v8::Value> handle,
11501 void*) {
11502 handle.Dispose(isolate);
ager@chromium.orgc4c92722009-11-18 14:12:51 +000011503}
11504
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000011505void HandleCreatingCallback(v8::Isolate* isolate,
11506 v8::Persistent<v8::Value> handle,
11507 void*) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000011508 v8::HandleScope scope(isolate);
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000011509 v8::Persistent<v8::Object>::New(isolate, v8::Object::New());
11510 handle.Dispose(isolate);
ager@chromium.orgc4c92722009-11-18 14:12:51 +000011511}
11512
11513
11514THREADED_TEST(NoGlobalHandlesOrphaningDueToWeakCallback) {
11515 LocalContext context;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000011516 v8::Isolate* isolate = context->GetIsolate();
ager@chromium.orgc4c92722009-11-18 14:12:51 +000011517
11518 v8::Persistent<v8::Object> handle1, handle2, handle3;
11519 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000011520 v8::HandleScope scope(isolate);
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000011521 handle3 = v8::Persistent<v8::Object>::New(isolate, v8::Object::New());
11522 handle2 = v8::Persistent<v8::Object>::New(isolate, v8::Object::New());
11523 handle1 = v8::Persistent<v8::Object>::New(isolate, v8::Object::New());
ager@chromium.orgc4c92722009-11-18 14:12:51 +000011524 }
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000011525 handle2.MakeWeak(isolate, NULL, DisposingCallback);
11526 handle3.MakeWeak(isolate, NULL, HandleCreatingCallback);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000011527 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.orgc4c92722009-11-18 14:12:51 +000011528}
11529
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000011530
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011531THREADED_TEST(CheckForCrossContextObjectLiterals) {
kasperl@chromium.orgb9123622008-09-17 14:05:56 +000011532 v8::V8::Initialize();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011533
11534 const int nof = 2;
11535 const char* sources[nof] = {
11536 "try { [ 2, 3, 4 ].forEach(5); } catch(e) { e.toString(); }",
11537 "Object()"
11538 };
11539
11540 for (int i = 0; i < nof; i++) {
11541 const char* source = sources[i];
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000011542 { v8::HandleScope scope(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011543 LocalContext context;
11544 CompileRun(source);
11545 }
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000011546 { v8::HandleScope scope(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011547 LocalContext context;
11548 CompileRun(source);
11549 }
11550 }
11551}
11552
11553
11554static v8::Handle<Value> NestedScope(v8::Persistent<Context> env) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000011555 v8::HandleScope inner(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011556 env->Enter();
11557 v8::Handle<Value> three = v8_num(3);
11558 v8::Handle<Value> value = inner.Close(three);
11559 env->Exit();
11560 return value;
11561}
11562
11563
11564THREADED_TEST(NestedHandleScopeAndContexts) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000011565 v8::HandleScope outer(v8::Isolate::GetCurrent());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011566 v8::Persistent<Context> env = Context::New();
11567 env->Enter();
11568 v8::Handle<Value> value = NestedScope(env);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000011569 v8::Handle<String> str(value->ToString());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000011570 CHECK(!str.IsEmpty());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011571 env->Exit();
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000011572 env.Dispose(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011573}
11574
11575
verwaest@chromium.org753aee42012-07-17 16:15:42 +000011576static i::Handle<i::JSFunction>* foo_ptr = NULL;
11577static int foo_count = 0;
11578static i::Handle<i::JSFunction>* bar_ptr = NULL;
11579static int bar_count = 0;
11580
11581
11582static void entry_hook(uintptr_t function,
11583 uintptr_t return_addr_location) {
11584 i::Code* code = i::Code::GetCodeFromTargetAddress(
11585 reinterpret_cast<i::Address>(function));
11586 CHECK(code != NULL);
11587
11588 if (bar_ptr != NULL && code == (*bar_ptr)->code())
11589 ++bar_count;
11590
11591 if (foo_ptr != NULL && code == (*foo_ptr)->code())
11592 ++foo_count;
11593
11594 // TODO(siggi): Verify return_addr_location.
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000011595 // This can be done by capturing JitCodeEvents, but requires an ordered
11596 // collection.
verwaest@chromium.org753aee42012-07-17 16:15:42 +000011597}
11598
11599
11600static void RunLoopInNewEnv() {
11601 bar_ptr = NULL;
11602 foo_ptr = NULL;
11603
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000011604 v8::HandleScope outer(v8::Isolate::GetCurrent());
verwaest@chromium.org753aee42012-07-17 16:15:42 +000011605 v8::Persistent<Context> env = Context::New();
11606 env->Enter();
11607
11608 const char* script =
11609 "function bar() {"
11610 " var sum = 0;"
11611 " for (i = 0; i < 100; ++i)"
11612 " sum = foo(i);"
11613 " return sum;"
11614 "}"
11615 "function foo(i) { return i * i; }";
11616 CompileRun(script);
11617 i::Handle<i::JSFunction> bar =
11618 i::Handle<i::JSFunction>::cast(
11619 v8::Utils::OpenHandle(*env->Global()->Get(v8_str("bar"))));
11620 ASSERT(*bar);
11621
11622 i::Handle<i::JSFunction> foo =
11623 i::Handle<i::JSFunction>::cast(
11624 v8::Utils::OpenHandle(*env->Global()->Get(v8_str("foo"))));
11625 ASSERT(*foo);
11626
11627 bar_ptr = &bar;
11628 foo_ptr = &foo;
11629
11630 v8::Handle<v8::Value> value = CompileRun("bar();");
11631 CHECK(value->IsNumber());
11632 CHECK_EQ(9801.0, v8::Number::Cast(*value)->Value());
11633
11634 // Test the optimized codegen path.
11635 value = CompileRun("%OptimizeFunctionOnNextCall(foo);"
11636 "bar();");
11637 CHECK(value->IsNumber());
11638 CHECK_EQ(9801.0, v8::Number::Cast(*value)->Value());
11639
11640 env->Exit();
11641}
11642
11643
11644TEST(SetFunctionEntryHook) {
11645 i::FLAG_allow_natives_syntax = true;
yangguo@chromium.orgfb377212012-11-16 14:43:43 +000011646 i::FLAG_use_inlining = false;
verwaest@chromium.org753aee42012-07-17 16:15:42 +000011647
11648 // Test setting and resetting the entry hook.
11649 // Nulling it should always succeed.
11650 CHECK(v8::V8::SetFunctionEntryHook(NULL));
11651
11652 CHECK(v8::V8::SetFunctionEntryHook(entry_hook));
11653 // Setting a hook while one's active should fail.
11654 CHECK_EQ(false, v8::V8::SetFunctionEntryHook(entry_hook));
11655
11656 CHECK(v8::V8::SetFunctionEntryHook(NULL));
11657
11658 // Reset the entry count to zero and set the entry hook.
11659 bar_count = 0;
11660 foo_count = 0;
11661 CHECK(v8::V8::SetFunctionEntryHook(entry_hook));
11662 RunLoopInNewEnv();
11663
11664 CHECK_EQ(2, bar_count);
11665 CHECK_EQ(200, foo_count);
11666
11667 // Clear the entry hook and count.
11668 bar_count = 0;
11669 foo_count = 0;
11670 v8::V8::SetFunctionEntryHook(NULL);
11671
11672 // Clear the compilation cache to make sure we don't reuse the
11673 // functions from the previous invocation.
11674 v8::internal::Isolate::Current()->compilation_cache()->Clear();
11675
11676 // Verify that entry hooking is now disabled.
11677 RunLoopInNewEnv();
11678 CHECK_EQ(0u, bar_count);
11679 CHECK_EQ(0u, foo_count);
11680}
11681
11682
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000011683static i::HashMap* code_map = NULL;
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +000011684static i::HashMap* jitcode_line_info = NULL;
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000011685static int saw_bar = 0;
11686static int move_events = 0;
11687
11688
11689static bool FunctionNameIs(const char* expected,
11690 const v8::JitCodeEvent* event) {
11691 // Log lines for functions are of the general form:
11692 // "LazyCompile:<type><function_name>", where the type is one of
11693 // "*", "~" or "".
11694 static const char kPreamble[] = "LazyCompile:";
11695 static size_t kPreambleLen = sizeof(kPreamble) - 1;
11696
11697 if (event->name.len < sizeof(kPreamble) - 1 ||
11698 strncmp(kPreamble, event->name.str, kPreambleLen) != 0) {
11699 return false;
11700 }
11701
11702 const char* tail = event->name.str + kPreambleLen;
11703 size_t tail_len = event->name.len - kPreambleLen;
11704 size_t expected_len = strlen(expected);
11705 if (tail_len == expected_len + 1) {
11706 if (*tail == '*' || *tail == '~') {
11707 --tail_len;
11708 ++tail;
11709 } else {
11710 return false;
11711 }
11712 }
11713
11714 if (tail_len != expected_len)
11715 return false;
11716
11717 return strncmp(tail, expected, expected_len) == 0;
11718}
11719
11720
11721static void event_handler(const v8::JitCodeEvent* event) {
11722 CHECK(event != NULL);
11723 CHECK(code_map != NULL);
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +000011724 CHECK(jitcode_line_info != NULL);
11725
11726 class DummyJitCodeLineInfo {
11727 };
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000011728
11729 switch (event->type) {
11730 case v8::JitCodeEvent::CODE_ADDED: {
11731 CHECK(event->code_start != NULL);
11732 CHECK_NE(0, static_cast<int>(event->code_len));
11733 CHECK(event->name.str != NULL);
11734 i::HashMap::Entry* entry =
11735 code_map->Lookup(event->code_start,
11736 i::ComputePointerHash(event->code_start),
11737 true);
11738 entry->value = reinterpret_cast<void*>(event->code_len);
11739
11740 if (FunctionNameIs("bar", event)) {
11741 ++saw_bar;
11742 }
11743 }
11744 break;
11745
11746 case v8::JitCodeEvent::CODE_MOVED: {
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000011747 uint32_t hash = i::ComputePointerHash(event->code_start);
jkummerow@chromium.org78502a92012-09-06 13:50:42 +000011748 // We would like to never see code move that we haven't seen before,
11749 // but the code creation event does not happen until the line endings
11750 // have been calculated (this is so that we can report the line in the
11751 // script at which the function source is found, see
11752 // Compiler::RecordFunctionCompilation) and the line endings
11753 // calculations can cause a GC, which can move the newly created code
11754 // before its existence can be logged.
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000011755 i::HashMap::Entry* entry =
11756 code_map->Lookup(event->code_start, hash, false);
jkummerow@chromium.org78502a92012-09-06 13:50:42 +000011757 if (entry != NULL) {
11758 ++move_events;
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000011759
jkummerow@chromium.org78502a92012-09-06 13:50:42 +000011760 CHECK_EQ(reinterpret_cast<void*>(event->code_len), entry->value);
11761 code_map->Remove(event->code_start, hash);
11762
11763 entry = code_map->Lookup(event->new_code_start,
11764 i::ComputePointerHash(event->new_code_start),
11765 true);
11766 CHECK(entry != NULL);
11767 entry->value = reinterpret_cast<void*>(event->code_len);
11768 }
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000011769 }
11770 break;
11771
11772 case v8::JitCodeEvent::CODE_REMOVED:
11773 // Object/code removal events are currently not dispatched from the GC.
11774 CHECK(false);
11775 break;
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +000011776
11777 // For CODE_START_LINE_INFO_RECORDING event, we will create one
11778 // DummyJitCodeLineInfo data structure pointed by event->user_dat. We
11779 // record it in jitcode_line_info.
11780 case v8::JitCodeEvent::CODE_START_LINE_INFO_RECORDING: {
11781 DummyJitCodeLineInfo* line_info = new DummyJitCodeLineInfo();
11782 v8::JitCodeEvent* temp_event = const_cast<v8::JitCodeEvent*>(event);
11783 temp_event->user_data = line_info;
11784 i::HashMap::Entry* entry =
11785 jitcode_line_info->Lookup(line_info,
11786 i::ComputePointerHash(line_info),
11787 true);
11788 entry->value = reinterpret_cast<void*>(line_info);
11789 }
11790 break;
11791 // For these two events, we will check whether the event->user_data
11792 // data structure is created before during CODE_START_LINE_INFO_RECORDING
11793 // event. And delete it in CODE_END_LINE_INFO_RECORDING event handling.
11794 case v8::JitCodeEvent::CODE_END_LINE_INFO_RECORDING: {
11795 CHECK(event->user_data != NULL);
11796 uint32_t hash = i::ComputePointerHash(event->user_data);
11797 i::HashMap::Entry* entry =
11798 jitcode_line_info->Lookup(event->user_data, hash, false);
11799 CHECK(entry != NULL);
11800 delete reinterpret_cast<DummyJitCodeLineInfo*>(event->user_data);
11801 }
11802 break;
11803
11804 case v8::JitCodeEvent::CODE_ADD_LINE_POS_INFO: {
11805 CHECK(event->user_data != NULL);
11806 uint32_t hash = i::ComputePointerHash(event->user_data);
11807 i::HashMap::Entry* entry =
11808 jitcode_line_info->Lookup(event->user_data, hash, false);
11809 CHECK(entry != NULL);
11810 }
11811 break;
11812
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000011813 default:
11814 // Impossible event.
11815 CHECK(false);
11816 break;
11817 }
11818}
11819
11820
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000011821static bool MatchPointers(void* key1, void* key2) {
11822 return key1 == key2;
11823}
11824
11825
11826TEST(SetJitCodeEventHandler) {
ulan@chromium.org6ba1fd02013-02-14 14:56:11 +000011827 i::FLAG_stress_compaction = true;
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000011828 const char* script =
11829 "function bar() {"
11830 " var sum = 0;"
11831 " for (i = 0; i < 100; ++i)"
11832 " sum = foo(i);"
11833 " return sum;"
11834 "}"
11835 "function foo(i) { return i * i; };"
11836 "bar();";
11837
11838 // Run this test in a new isolate to make sure we don't
11839 // have remnants of state from other code.
11840 v8::Isolate* isolate = v8::Isolate::New();
11841 isolate->Enter();
11842
11843 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000011844 v8::HandleScope scope(isolate);
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000011845 i::HashMap code(MatchPointers);
11846 code_map = &code;
11847
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +000011848 i::HashMap lineinfo(MatchPointers);
11849 jitcode_line_info = &lineinfo;
11850
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000011851 saw_bar = 0;
11852 move_events = 0;
11853
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000011854 V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault, event_handler);
11855
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000011856 // Generate new code objects sparsely distributed across several
11857 // different fragmented code-space pages.
11858 const int kIterations = 10;
11859 for (int i = 0; i < kIterations; ++i) {
11860 LocalContext env;
ulan@chromium.org6ba1fd02013-02-14 14:56:11 +000011861 i::AlwaysAllocateScope always_allocate;
11862 SimulateFullSpace(HEAP->code_space());
11863 CompileRun(script);
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000011864
ulan@chromium.org6ba1fd02013-02-14 14:56:11 +000011865 // Keep a strong reference to the code object in the handle scope.
11866 i::Handle<i::Code> bar_code(i::Handle<i::JSFunction>::cast(
11867 v8::Utils::OpenHandle(*env->Global()->Get(v8_str("bar"))))->code());
11868 i::Handle<i::Code> foo_code(i::Handle<i::JSFunction>::cast(
11869 v8::Utils::OpenHandle(*env->Global()->Get(v8_str("foo"))))->code());
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000011870
11871 // Clear the compilation cache to get more wastage.
11872 ISOLATE->compilation_cache()->Clear();
11873 }
11874
11875 // Force code movement.
11876 HEAP->CollectAllAvailableGarbage("TestSetJitCodeEventHandler");
11877
ulan@chromium.org6ba1fd02013-02-14 14:56:11 +000011878 V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault, NULL);
11879
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000011880 CHECK_LE(kIterations, saw_bar);
ulan@chromium.org6ba1fd02013-02-14 14:56:11 +000011881 CHECK_LT(0, move_events);
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000011882
11883 code_map = NULL;
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +000011884 jitcode_line_info = NULL;
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000011885 }
11886
11887 isolate->Exit();
11888 isolate->Dispose();
11889
11890 // Do this in a new isolate.
11891 isolate = v8::Isolate::New();
11892 isolate->Enter();
11893
11894 // Verify that we get callbacks for existing code objects when we
11895 // request enumeration of existing code.
11896 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000011897 v8::HandleScope scope(isolate);
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000011898 LocalContext env;
11899 CompileRun(script);
11900
11901 // Now get code through initial iteration.
11902 i::HashMap code(MatchPointers);
11903 code_map = &code;
11904
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +000011905 i::HashMap lineinfo(MatchPointers);
11906 jitcode_line_info = &lineinfo;
11907
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000011908 V8::SetJitCodeEventHandler(v8::kJitCodeEventEnumExisting, event_handler);
11909 V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault, NULL);
11910
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +000011911 jitcode_line_info = NULL;
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000011912 // We expect that we got some events. Note that if we could get code removal
11913 // notifications, we could compare two collections, one created by listening
11914 // from the time of creation of an isolate, and the other by subscribing
11915 // with EnumExisting.
ulan@chromium.org6ba1fd02013-02-14 14:56:11 +000011916 CHECK_LT(0, code.occupancy());
11917
11918 code_map = NULL;
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000011919 }
11920
11921 isolate->Exit();
11922 isolate->Dispose();
11923}
11924
11925
jkummerow@chromium.org28faa982012-04-13 09:58:30 +000011926static int64_t cast(intptr_t x) { return static_cast<int64_t>(x); }
11927
11928
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011929THREADED_TEST(ExternalAllocatedMemory) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000011930 v8::HandleScope outer(v8::Isolate::GetCurrent());
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000011931 v8::Persistent<Context> env(Context::New());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000011932 CHECK(!env.IsEmpty());
jkummerow@chromium.org28faa982012-04-13 09:58:30 +000011933 const intptr_t kSize = 1024*1024;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000011934 v8::Isolate* isolate = env->GetIsolate();
11935 CHECK_EQ(cast(isolate->AdjustAmountOfExternalAllocatedMemory(kSize)),
jkummerow@chromium.org28faa982012-04-13 09:58:30 +000011936 cast(kSize));
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000011937 CHECK_EQ(cast(isolate->AdjustAmountOfExternalAllocatedMemory(-kSize)),
jkummerow@chromium.org28faa982012-04-13 09:58:30 +000011938 cast(0));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011939}
11940
11941
11942THREADED_TEST(DisposeEnteredContext) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011943 LocalContext outer;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000011944 v8::HandleScope scope(outer->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011945 { v8::Persistent<v8::Context> inner = v8::Context::New();
11946 inner->Enter();
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000011947 inner.Dispose(inner->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011948 inner.Clear();
11949 inner->Exit();
11950 }
11951}
ager@chromium.org9258b6b2008-09-11 09:11:10 +000011952
11953
11954// Regression test for issue 54, object templates with internal fields
11955// but no accessors or interceptors did not get their internal field
11956// count set on instances.
11957THREADED_TEST(Regress54) {
ager@chromium.org9258b6b2008-09-11 09:11:10 +000011958 LocalContext context;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000011959 v8::Isolate* isolate = context->GetIsolate();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000011960 v8::HandleScope outer(isolate);
ager@chromium.org9258b6b2008-09-11 09:11:10 +000011961 static v8::Persistent<v8::ObjectTemplate> templ;
11962 if (templ.IsEmpty()) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000011963 v8::HandleScope inner(isolate);
ager@chromium.org9258b6b2008-09-11 09:11:10 +000011964 v8::Handle<v8::ObjectTemplate> local = v8::ObjectTemplate::New();
11965 local->SetInternalFieldCount(1);
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000011966 templ =
11967 v8::Persistent<v8::ObjectTemplate>::New(isolate, inner.Close(local));
ager@chromium.org9258b6b2008-09-11 09:11:10 +000011968 }
11969 v8::Handle<v8::Object> result = templ->NewInstance();
11970 CHECK_EQ(1, result->InternalFieldCount());
11971}
11972
11973
11974// If part of the threaded tests, this test makes ThreadingTest fail
11975// on mac.
11976TEST(CatchStackOverflow) {
ager@chromium.org9258b6b2008-09-11 09:11:10 +000011977 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000011978 v8::HandleScope scope(context->GetIsolate());
ager@chromium.org9258b6b2008-09-11 09:11:10 +000011979 v8::TryCatch try_catch;
11980 v8::Handle<v8::Script> script = v8::Script::Compile(v8::String::New(
11981 "function f() {"
11982 " return f();"
11983 "}"
11984 ""
11985 "f();"));
11986 v8::Handle<v8::Value> result = script->Run();
11987 CHECK(result.IsEmpty());
11988}
11989
11990
kasperl@chromium.org7be3c992009-03-12 07:19:55 +000011991static void CheckTryCatchSourceInfo(v8::Handle<v8::Script> script,
11992 const char* resource_name,
11993 int line_offset) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000011994 v8::HandleScope scope(v8::Isolate::GetCurrent());
kasperl@chromium.org7be3c992009-03-12 07:19:55 +000011995 v8::TryCatch try_catch;
11996 v8::Handle<v8::Value> result = script->Run();
11997 CHECK(result.IsEmpty());
11998 CHECK(try_catch.HasCaught());
11999 v8::Handle<v8::Message> message = try_catch.Message();
12000 CHECK(!message.IsEmpty());
12001 CHECK_EQ(10 + line_offset, message->GetLineNumber());
12002 CHECK_EQ(91, message->GetStartPosition());
12003 CHECK_EQ(92, message->GetEndPosition());
12004 CHECK_EQ(2, message->GetStartColumn());
12005 CHECK_EQ(3, message->GetEndColumn());
12006 v8::String::AsciiValue line(message->GetSourceLine());
12007 CHECK_EQ(" throw 'nirk';", *line);
12008 v8::String::AsciiValue name(message->GetScriptResourceName());
12009 CHECK_EQ(resource_name, *name);
12010}
12011
12012
ager@chromium.org9258b6b2008-09-11 09:11:10 +000012013THREADED_TEST(TryCatchSourceInfo) {
ager@chromium.org9258b6b2008-09-11 09:11:10 +000012014 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000012015 v8::HandleScope scope(context->GetIsolate());
ager@chromium.org9258b6b2008-09-11 09:11:10 +000012016 v8::Handle<v8::String> source = v8::String::New(
12017 "function Foo() {\n"
12018 " return Bar();\n"
12019 "}\n"
12020 "\n"
12021 "function Bar() {\n"
12022 " return Baz();\n"
12023 "}\n"
12024 "\n"
12025 "function Baz() {\n"
12026 " throw 'nirk';\n"
12027 "}\n"
12028 "\n"
12029 "Foo();\n");
kasperl@chromium.org7be3c992009-03-12 07:19:55 +000012030
12031 const char* resource_name;
12032 v8::Handle<v8::Script> script;
12033 resource_name = "test.js";
12034 script = v8::Script::Compile(source, v8::String::New(resource_name));
12035 CheckTryCatchSourceInfo(script, resource_name, 0);
12036
12037 resource_name = "test1.js";
12038 v8::ScriptOrigin origin1(v8::String::New(resource_name));
12039 script = v8::Script::Compile(source, &origin1);
12040 CheckTryCatchSourceInfo(script, resource_name, 0);
12041
12042 resource_name = "test2.js";
12043 v8::ScriptOrigin origin2(v8::String::New(resource_name), v8::Integer::New(7));
12044 script = v8::Script::Compile(source, &origin2);
12045 CheckTryCatchSourceInfo(script, resource_name, 7);
ager@chromium.org9258b6b2008-09-11 09:11:10 +000012046}
kasperl@chromium.orgb9123622008-09-17 14:05:56 +000012047
12048
12049THREADED_TEST(CompilationCache) {
kasperl@chromium.orgb9123622008-09-17 14:05:56 +000012050 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000012051 v8::HandleScope scope(context->GetIsolate());
kasperl@chromium.orgb9123622008-09-17 14:05:56 +000012052 v8::Handle<v8::String> source0 = v8::String::New("1234");
12053 v8::Handle<v8::String> source1 = v8::String::New("1234");
12054 v8::Handle<v8::Script> script0 =
12055 v8::Script::Compile(source0, v8::String::New("test.js"));
12056 v8::Handle<v8::Script> script1 =
12057 v8::Script::Compile(source1, v8::String::New("test.js"));
12058 v8::Handle<v8::Script> script2 =
12059 v8::Script::Compile(source0); // different origin
12060 CHECK_EQ(1234, script0->Run()->Int32Value());
12061 CHECK_EQ(1234, script1->Run()->Int32Value());
12062 CHECK_EQ(1234, script2->Run()->Int32Value());
12063}
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000012064
12065
12066static v8::Handle<Value> FunctionNameCallback(const v8::Arguments& args) {
12067 ApiTestFuzzer::Fuzz();
12068 return v8_num(42);
12069}
12070
12071
12072THREADED_TEST(CallbackFunctionName) {
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000012073 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000012074 v8::HandleScope scope(context->GetIsolate());
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000012075 Local<ObjectTemplate> t = ObjectTemplate::New();
12076 t->Set(v8_str("asdf"), v8::FunctionTemplate::New(FunctionNameCallback));
12077 context->Global()->Set(v8_str("obj"), t->NewInstance());
12078 v8::Handle<v8::Value> value = CompileRun("obj.asdf.name");
12079 CHECK(value->IsString());
12080 v8::String::AsciiValue name(value);
12081 CHECK_EQ("asdf", *name);
12082}
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000012083
12084
12085THREADED_TEST(DateAccess) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000012086 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000012087 v8::HandleScope scope(context->GetIsolate());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000012088 v8::Handle<v8::Value> date = v8::Date::New(1224744689038.0);
12089 CHECK(date->IsDate());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000012090 CHECK_EQ(1224744689038.0, date.As<v8::Date>()->NumberValue());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000012091}
12092
12093
12094void CheckProperties(v8::Handle<v8::Value> val, int elmc, const char* elmv[]) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000012095 v8::Handle<v8::Object> obj = val.As<v8::Object>();
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000012096 v8::Handle<v8::Array> props = obj->GetPropertyNames();
12097 CHECK_EQ(elmc, props->Length());
12098 for (int i = 0; i < elmc; i++) {
12099 v8::String::Utf8Value elm(props->Get(v8::Integer::New(i)));
12100 CHECK_EQ(elmv[i], *elm);
12101 }
12102}
12103
12104
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000012105void CheckOwnProperties(v8::Handle<v8::Value> val,
12106 int elmc,
12107 const char* elmv[]) {
12108 v8::Handle<v8::Object> obj = val.As<v8::Object>();
12109 v8::Handle<v8::Array> props = obj->GetOwnPropertyNames();
12110 CHECK_EQ(elmc, props->Length());
12111 for (int i = 0; i < elmc; i++) {
12112 v8::String::Utf8Value elm(props->Get(v8::Integer::New(i)));
12113 CHECK_EQ(elmv[i], *elm);
12114 }
12115}
12116
12117
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000012118THREADED_TEST(PropertyEnumeration) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000012119 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000012120 v8::HandleScope scope(context->GetIsolate());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000012121 v8::Handle<v8::Value> obj = v8::Script::Compile(v8::String::New(
12122 "var result = [];"
12123 "result[0] = {};"
12124 "result[1] = {a: 1, b: 2};"
12125 "result[2] = [1, 2, 3];"
12126 "var proto = {x: 1, y: 2, z: 3};"
12127 "var x = { __proto__: proto, w: 0, z: 1 };"
12128 "result[3] = x;"
12129 "result;"))->Run();
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000012130 v8::Handle<v8::Array> elms = obj.As<v8::Array>();
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000012131 CHECK_EQ(4, elms->Length());
12132 int elmc0 = 0;
12133 const char** elmv0 = NULL;
12134 CheckProperties(elms->Get(v8::Integer::New(0)), elmc0, elmv0);
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000012135 CheckOwnProperties(elms->Get(v8::Integer::New(0)), elmc0, elmv0);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000012136 int elmc1 = 2;
12137 const char* elmv1[] = {"a", "b"};
12138 CheckProperties(elms->Get(v8::Integer::New(1)), elmc1, elmv1);
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000012139 CheckOwnProperties(elms->Get(v8::Integer::New(1)), elmc1, elmv1);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000012140 int elmc2 = 3;
12141 const char* elmv2[] = {"0", "1", "2"};
12142 CheckProperties(elms->Get(v8::Integer::New(2)), elmc2, elmv2);
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000012143 CheckOwnProperties(elms->Get(v8::Integer::New(2)), elmc2, elmv2);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000012144 int elmc3 = 4;
12145 const char* elmv3[] = {"w", "z", "x", "y"};
12146 CheckProperties(elms->Get(v8::Integer::New(3)), elmc3, elmv3);
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000012147 int elmc4 = 2;
12148 const char* elmv4[] = {"w", "z"};
12149 CheckOwnProperties(elms->Get(v8::Integer::New(3)), elmc4, elmv4);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000012150}
ager@chromium.org870a0b62008-11-04 11:43:05 +000012151
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000012152THREADED_TEST(PropertyEnumeration2) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000012153 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000012154 v8::HandleScope scope(context->GetIsolate());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000012155 v8::Handle<v8::Value> obj = v8::Script::Compile(v8::String::New(
12156 "var result = [];"
12157 "result[0] = {};"
12158 "result[1] = {a: 1, b: 2};"
12159 "result[2] = [1, 2, 3];"
12160 "var proto = {x: 1, y: 2, z: 3};"
12161 "var x = { __proto__: proto, w: 0, z: 1 };"
12162 "result[3] = x;"
12163 "result;"))->Run();
12164 v8::Handle<v8::Array> elms = obj.As<v8::Array>();
12165 CHECK_EQ(4, elms->Length());
12166 int elmc0 = 0;
12167 const char** elmv0 = NULL;
12168 CheckProperties(elms->Get(v8::Integer::New(0)), elmc0, elmv0);
12169
12170 v8::Handle<v8::Value> val = elms->Get(v8::Integer::New(0));
12171 v8::Handle<v8::Array> props = val.As<v8::Object>()->GetPropertyNames();
12172 CHECK_EQ(0, props->Length());
12173 for (uint32_t i = 0; i < props->Length(); i++) {
12174 printf("p[%d]\n", i);
12175 }
12176}
ager@chromium.org870a0b62008-11-04 11:43:05 +000012177
ager@chromium.org870a0b62008-11-04 11:43:05 +000012178static bool NamedSetAccessBlocker(Local<v8::Object> obj,
12179 Local<Value> name,
12180 v8::AccessType type,
12181 Local<Value> data) {
12182 return type != v8::ACCESS_SET;
12183}
12184
12185
12186static bool IndexedSetAccessBlocker(Local<v8::Object> obj,
12187 uint32_t key,
12188 v8::AccessType type,
12189 Local<Value> data) {
12190 return type != v8::ACCESS_SET;
12191}
12192
12193
12194THREADED_TEST(DisableAccessChecksWhileConfiguring) {
ager@chromium.org870a0b62008-11-04 11:43:05 +000012195 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000012196 v8::HandleScope scope(context->GetIsolate());
ager@chromium.org870a0b62008-11-04 11:43:05 +000012197 Local<ObjectTemplate> templ = ObjectTemplate::New();
12198 templ->SetAccessCheckCallbacks(NamedSetAccessBlocker,
12199 IndexedSetAccessBlocker);
12200 templ->Set(v8_str("x"), v8::True());
12201 Local<v8::Object> instance = templ->NewInstance();
12202 context->Global()->Set(v8_str("obj"), instance);
12203 Local<Value> value = CompileRun("obj.x");
12204 CHECK(value->BooleanValue());
12205}
ager@chromium.orga74f0da2008-12-03 16:05:52 +000012206
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000012207
ager@chromium.org32912102009-01-16 10:38:43 +000012208static bool NamedGetAccessBlocker(Local<v8::Object> obj,
12209 Local<Value> name,
12210 v8::AccessType type,
12211 Local<Value> data) {
12212 return false;
12213}
12214
12215
12216static bool IndexedGetAccessBlocker(Local<v8::Object> obj,
12217 uint32_t key,
12218 v8::AccessType type,
12219 Local<Value> data) {
12220 return false;
12221}
12222
12223
12224
12225THREADED_TEST(AccessChecksReenabledCorrectly) {
ager@chromium.org32912102009-01-16 10:38:43 +000012226 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000012227 v8::HandleScope scope(context->GetIsolate());
ager@chromium.org32912102009-01-16 10:38:43 +000012228 Local<ObjectTemplate> templ = ObjectTemplate::New();
12229 templ->SetAccessCheckCallbacks(NamedGetAccessBlocker,
12230 IndexedGetAccessBlocker);
12231 templ->Set(v8_str("a"), v8_str("a"));
12232 // Add more than 8 (see kMaxFastProperties) properties
12233 // so that the constructor will force copying map.
12234 // Cannot sprintf, gcc complains unsafety.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000012235 char buf[4];
ager@chromium.org32912102009-01-16 10:38:43 +000012236 for (char i = '0'; i <= '9' ; i++) {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000012237 buf[0] = i;
ager@chromium.org32912102009-01-16 10:38:43 +000012238 for (char j = '0'; j <= '9'; j++) {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000012239 buf[1] = j;
ager@chromium.org32912102009-01-16 10:38:43 +000012240 for (char k = '0'; k <= '9'; k++) {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000012241 buf[2] = k;
12242 buf[3] = 0;
ager@chromium.org32912102009-01-16 10:38:43 +000012243 templ->Set(v8_str(buf), v8::Number::New(k));
12244 }
12245 }
12246 }
12247
12248 Local<v8::Object> instance_1 = templ->NewInstance();
12249 context->Global()->Set(v8_str("obj_1"), instance_1);
12250
12251 Local<Value> value_1 = CompileRun("obj_1.a");
12252 CHECK(value_1->IsUndefined());
12253
12254 Local<v8::Object> instance_2 = templ->NewInstance();
12255 context->Global()->Set(v8_str("obj_2"), instance_2);
12256
12257 Local<Value> value_2 = CompileRun("obj_2.a");
12258 CHECK(value_2->IsUndefined());
12259}
ager@chromium.orga74f0da2008-12-03 16:05:52 +000012260
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000012261
ager@chromium.org8bb60582008-12-11 12:02:20 +000012262// This tests that access check information remains on the global
12263// object template when creating contexts.
12264THREADED_TEST(AccessControlRepeatedContextCreation) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000012265 v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
ager@chromium.org8bb60582008-12-11 12:02:20 +000012266 v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
12267 global_template->SetAccessCheckCallbacks(NamedSetAccessBlocker,
12268 IndexedSetAccessBlocker);
12269 i::Handle<i::ObjectTemplateInfo> internal_template =
12270 v8::Utils::OpenHandle(*global_template);
12271 CHECK(!internal_template->constructor()->IsUndefined());
12272 i::Handle<i::FunctionTemplateInfo> constructor(
12273 i::FunctionTemplateInfo::cast(internal_template->constructor()));
12274 CHECK(!constructor->access_check_info()->IsUndefined());
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000012275 v8::Persistent<Context> context0(Context::New(NULL, global_template));
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012276 CHECK(!context0.IsEmpty());
ager@chromium.org8bb60582008-12-11 12:02:20 +000012277 CHECK(!constructor->access_check_info()->IsUndefined());
12278}
12279
12280
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000012281THREADED_TEST(TurnOnAccessCheck) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000012282 v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000012283
12284 // Create an environment with access check to the global object disabled by
12285 // default.
12286 v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
12287 global_template->SetAccessCheckCallbacks(NamedGetAccessBlocker,
12288 IndexedGetAccessBlocker,
12289 v8::Handle<v8::Value>(),
12290 false);
12291 v8::Persistent<Context> context = Context::New(NULL, global_template);
12292 Context::Scope context_scope(context);
12293
12294 // Set up a property and a number of functions.
12295 context->Global()->Set(v8_str("a"), v8_num(1));
12296 CompileRun("function f1() {return a;}"
12297 "function f2() {return a;}"
12298 "function g1() {return h();}"
12299 "function g2() {return h();}"
12300 "function h() {return 1;}");
12301 Local<Function> f1 =
12302 Local<Function>::Cast(context->Global()->Get(v8_str("f1")));
12303 Local<Function> f2 =
12304 Local<Function>::Cast(context->Global()->Get(v8_str("f2")));
12305 Local<Function> g1 =
12306 Local<Function>::Cast(context->Global()->Get(v8_str("g1")));
12307 Local<Function> g2 =
12308 Local<Function>::Cast(context->Global()->Get(v8_str("g2")));
12309 Local<Function> h =
12310 Local<Function>::Cast(context->Global()->Get(v8_str("h")));
12311
12312 // Get the global object.
12313 v8::Handle<v8::Object> global = context->Global();
12314
12315 // Call f1 one time and f2 a number of times. This will ensure that f1 still
12316 // uses the runtime system to retreive property a whereas f2 uses global load
12317 // inline cache.
12318 CHECK(f1->Call(global, 0, NULL)->Equals(v8_num(1)));
12319 for (int i = 0; i < 4; i++) {
12320 CHECK(f2->Call(global, 0, NULL)->Equals(v8_num(1)));
12321 }
12322
12323 // Same for g1 and g2.
12324 CHECK(g1->Call(global, 0, NULL)->Equals(v8_num(1)));
12325 for (int i = 0; i < 4; i++) {
12326 CHECK(g2->Call(global, 0, NULL)->Equals(v8_num(1)));
12327 }
12328
12329 // Detach the global and turn on access check.
12330 context->DetachGlobal();
12331 context->Global()->TurnOnAccessCheck();
12332
12333 // Failing access check to property get results in undefined.
12334 CHECK(f1->Call(global, 0, NULL)->IsUndefined());
12335 CHECK(f2->Call(global, 0, NULL)->IsUndefined());
12336
12337 // Failing access check to function call results in exception.
12338 CHECK(g1->Call(global, 0, NULL).IsEmpty());
12339 CHECK(g2->Call(global, 0, NULL).IsEmpty());
12340
12341 // No failing access check when just returning a constant.
12342 CHECK(h->Call(global, 0, NULL)->Equals(v8_num(1)));
12343}
12344
12345
jkummerow@chromium.orgf7a58842012-02-21 10:08:21 +000012346static const char* kPropertyA = "a";
12347static const char* kPropertyH = "h";
kasperl@chromium.orga5551262010-12-07 12:49:48 +000012348
12349static bool NamedGetAccessBlockAandH(Local<v8::Object> obj,
12350 Local<Value> name,
12351 v8::AccessType type,
12352 Local<Value> data) {
jkummerow@chromium.orgf7a58842012-02-21 10:08:21 +000012353 if (!name->IsString()) return false;
12354 i::Handle<i::String> name_handle =
12355 v8::Utils::OpenHandle(String::Cast(*name));
jkummerow@chromium.org59297c72013-01-09 16:32:23 +000012356 return !name_handle->IsUtf8EqualTo(i::CStrVector(kPropertyA))
12357 && !name_handle->IsUtf8EqualTo(i::CStrVector(kPropertyH));
kasperl@chromium.orga5551262010-12-07 12:49:48 +000012358}
12359
12360
jkummerow@chromium.orgf7a58842012-02-21 10:08:21 +000012361THREADED_TEST(TurnOnAccessCheckAndRecompile) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000012362 v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
kasperl@chromium.orga5551262010-12-07 12:49:48 +000012363
12364 // Create an environment with access check to the global object disabled by
12365 // default. When the registered access checker will block access to properties
jkummerow@chromium.orgf7a58842012-02-21 10:08:21 +000012366 // a and h.
kasperl@chromium.orga5551262010-12-07 12:49:48 +000012367 v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
12368 global_template->SetAccessCheckCallbacks(NamedGetAccessBlockAandH,
12369 IndexedGetAccessBlocker,
12370 v8::Handle<v8::Value>(),
12371 false);
12372 v8::Persistent<Context> context = Context::New(NULL, global_template);
12373 Context::Scope context_scope(context);
12374
12375 // Set up a property and a number of functions.
12376 context->Global()->Set(v8_str("a"), v8_num(1));
12377 static const char* source = "function f1() {return a;}"
12378 "function f2() {return a;}"
12379 "function g1() {return h();}"
12380 "function g2() {return h();}"
12381 "function h() {return 1;}";
12382
12383 CompileRun(source);
12384 Local<Function> f1;
12385 Local<Function> f2;
12386 Local<Function> g1;
12387 Local<Function> g2;
12388 Local<Function> h;
12389 f1 = Local<Function>::Cast(context->Global()->Get(v8_str("f1")));
12390 f2 = Local<Function>::Cast(context->Global()->Get(v8_str("f2")));
12391 g1 = Local<Function>::Cast(context->Global()->Get(v8_str("g1")));
12392 g2 = Local<Function>::Cast(context->Global()->Get(v8_str("g2")));
12393 h = Local<Function>::Cast(context->Global()->Get(v8_str("h")));
12394
12395 // Get the global object.
12396 v8::Handle<v8::Object> global = context->Global();
12397
12398 // Call f1 one time and f2 a number of times. This will ensure that f1 still
12399 // uses the runtime system to retreive property a whereas f2 uses global load
12400 // inline cache.
12401 CHECK(f1->Call(global, 0, NULL)->Equals(v8_num(1)));
12402 for (int i = 0; i < 4; i++) {
12403 CHECK(f2->Call(global, 0, NULL)->Equals(v8_num(1)));
12404 }
12405
12406 // Same for g1 and g2.
12407 CHECK(g1->Call(global, 0, NULL)->Equals(v8_num(1)));
12408 for (int i = 0; i < 4; i++) {
12409 CHECK(g2->Call(global, 0, NULL)->Equals(v8_num(1)));
12410 }
12411
12412 // Detach the global and turn on access check now blocking access to property
12413 // a and function h.
12414 context->DetachGlobal();
12415 context->Global()->TurnOnAccessCheck();
12416
12417 // Failing access check to property get results in undefined.
12418 CHECK(f1->Call(global, 0, NULL)->IsUndefined());
12419 CHECK(f2->Call(global, 0, NULL)->IsUndefined());
12420
12421 // Failing access check to function call results in exception.
12422 CHECK(g1->Call(global, 0, NULL).IsEmpty());
12423 CHECK(g2->Call(global, 0, NULL).IsEmpty());
12424
12425 // No failing access check when just returning a constant.
12426 CHECK(h->Call(global, 0, NULL)->Equals(v8_num(1)));
12427
12428 // Now compile the source again. And get the newly compiled functions, except
12429 // for h for which access is blocked.
12430 CompileRun(source);
12431 f1 = Local<Function>::Cast(context->Global()->Get(v8_str("f1")));
12432 f2 = Local<Function>::Cast(context->Global()->Get(v8_str("f2")));
12433 g1 = Local<Function>::Cast(context->Global()->Get(v8_str("g1")));
12434 g2 = Local<Function>::Cast(context->Global()->Get(v8_str("g2")));
12435 CHECK(context->Global()->Get(v8_str("h"))->IsUndefined());
12436
12437 // Failing access check to property get results in undefined.
12438 CHECK(f1->Call(global, 0, NULL)->IsUndefined());
12439 CHECK(f2->Call(global, 0, NULL)->IsUndefined());
12440
12441 // Failing access check to function call results in exception.
12442 CHECK(g1->Call(global, 0, NULL).IsEmpty());
12443 CHECK(g2->Call(global, 0, NULL).IsEmpty());
12444}
12445
12446
ager@chromium.orga74f0da2008-12-03 16:05:52 +000012447// This test verifies that pre-compilation (aka preparsing) can be called
12448// without initializing the whole VM. Thus we cannot run this test in a
12449// multi-threaded setup.
12450TEST(PreCompile) {
12451 // TODO(155): This test would break without the initialization of V8. This is
12452 // a workaround for now to make this test not fail.
12453 v8::V8::Initialize();
kmillikin@chromium.org9155e252010-05-26 13:27:57 +000012454 const char* script = "function foo(a) { return a+1; }";
12455 v8::ScriptData* sd =
ager@chromium.orgc4c92722009-11-18 14:12:51 +000012456 v8::ScriptData::PreCompile(script, i::StrLength(script));
ager@chromium.orga74f0da2008-12-03 16:05:52 +000012457 CHECK_NE(sd->Length(), 0);
12458 CHECK_NE(sd->Data(), NULL);
fschneider@chromium.org0c20e672010-01-14 15:28:53 +000012459 CHECK(!sd->HasError());
12460 delete sd;
12461}
12462
12463
12464TEST(PreCompileWithError) {
12465 v8::V8::Initialize();
kmillikin@chromium.org9155e252010-05-26 13:27:57 +000012466 const char* script = "function foo(a) { return 1 * * 2; }";
12467 v8::ScriptData* sd =
fschneider@chromium.org0c20e672010-01-14 15:28:53 +000012468 v8::ScriptData::PreCompile(script, i::StrLength(script));
12469 CHECK(sd->HasError());
12470 delete sd;
12471}
12472
12473
12474TEST(Regress31661) {
12475 v8::V8::Initialize();
kmillikin@chromium.org9155e252010-05-26 13:27:57 +000012476 const char* script = " The Definintive Guide";
12477 v8::ScriptData* sd =
fschneider@chromium.org0c20e672010-01-14 15:28:53 +000012478 v8::ScriptData::PreCompile(script, i::StrLength(script));
12479 CHECK(sd->HasError());
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000012480 delete sd;
ager@chromium.orga74f0da2008-12-03 16:05:52 +000012481}
12482
12483
kmillikin@chromium.org9155e252010-05-26 13:27:57 +000012484// Tests that ScriptData can be serialized and deserialized.
12485TEST(PreCompileSerialization) {
12486 v8::V8::Initialize();
12487 const char* script = "function foo(a) { return a+1; }";
12488 v8::ScriptData* sd =
12489 v8::ScriptData::PreCompile(script, i::StrLength(script));
12490
12491 // Serialize.
12492 int serialized_data_length = sd->Length();
12493 char* serialized_data = i::NewArray<char>(serialized_data_length);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +000012494 i::OS::MemCopy(serialized_data, sd->Data(), serialized_data_length);
kmillikin@chromium.org9155e252010-05-26 13:27:57 +000012495
12496 // Deserialize.
12497 v8::ScriptData* deserialized_sd =
12498 v8::ScriptData::New(serialized_data, serialized_data_length);
12499
12500 // Verify that the original is the same as the deserialized.
12501 CHECK_EQ(sd->Length(), deserialized_sd->Length());
12502 CHECK_EQ(0, memcmp(sd->Data(), deserialized_sd->Data(), sd->Length()));
12503 CHECK_EQ(sd->HasError(), deserialized_sd->HasError());
12504
12505 delete sd;
12506 delete deserialized_sd;
12507}
12508
12509
12510// Attempts to deserialize bad data.
12511TEST(PreCompileDeserializationError) {
12512 v8::V8::Initialize();
12513 const char* data = "DONT CARE";
12514 int invalid_size = 3;
12515 v8::ScriptData* sd = v8::ScriptData::New(data, invalid_size);
12516
12517 CHECK_EQ(0, sd->Length());
12518
12519 delete sd;
12520}
12521
12522
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000012523// Attempts to deserialize bad data.
12524TEST(PreCompileInvalidPreparseDataError) {
12525 v8::V8::Initialize();
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000012526 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000012527 v8::HandleScope scope(context->GetIsolate());
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000012528
12529 const char* script = "function foo(){ return 5;}\n"
12530 "function bar(){ return 6 + 7;} foo();";
12531 v8::ScriptData* sd =
12532 v8::ScriptData::PreCompile(script, i::StrLength(script));
12533 CHECK(!sd->HasError());
12534 // ScriptDataImpl private implementation details
ager@chromium.orgbeb25712010-11-29 08:02:25 +000012535 const int kHeaderSize = i::PreparseDataConstants::kHeaderSize;
ager@chromium.org5b2fbee2010-09-08 06:38:15 +000012536 const int kFunctionEntrySize = i::FunctionEntry::kSize;
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000012537 const int kFunctionEntryStartOffset = 0;
12538 const int kFunctionEntryEndOffset = 1;
12539 unsigned* sd_data =
12540 reinterpret_cast<unsigned*>(const_cast<char*>(sd->Data()));
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000012541
12542 // Overwrite function bar's end position with 0.
12543 sd_data[kHeaderSize + 1 * kFunctionEntrySize + kFunctionEntryEndOffset] = 0;
12544 v8::TryCatch try_catch;
12545
12546 Local<String> source = String::New(script);
12547 Local<Script> compiled_script = Script::New(source, NULL, sd);
12548 CHECK(try_catch.HasCaught());
12549 String::AsciiValue exception_value(try_catch.Message()->Get());
12550 CHECK_EQ("Uncaught SyntaxError: Invalid preparser data for function bar",
12551 *exception_value);
12552
12553 try_catch.Reset();
lrn@chromium.orgd4e9e222011-08-03 12:01:58 +000012554
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000012555 // Overwrite function bar's start position with 200. The function entry
lrn@chromium.orgd4e9e222011-08-03 12:01:58 +000012556 // will not be found when searching for it by position and we should fall
12557 // back on eager compilation.
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +000012558 sd = v8::ScriptData::PreCompile(script, i::StrLength(script));
12559 sd_data = reinterpret_cast<unsigned*>(const_cast<char*>(sd->Data()));
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000012560 sd_data[kHeaderSize + 1 * kFunctionEntrySize + kFunctionEntryStartOffset] =
12561 200;
12562 compiled_script = Script::New(source, NULL, sd);
lrn@chromium.orgd4e9e222011-08-03 12:01:58 +000012563 CHECK(!try_catch.HasCaught());
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000012564
12565 delete sd;
12566}
12567
12568
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +000012569// Verifies that the Handle<String> and const char* versions of the API produce
12570// the same results (at least for one trivial case).
12571TEST(PreCompileAPIVariationsAreSame) {
12572 v8::V8::Initialize();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000012573 v8::HandleScope scope(v8::Isolate::GetCurrent());
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +000012574
12575 const char* cstring = "function foo(a) { return a+1; }";
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000012576
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +000012577 v8::ScriptData* sd_from_cstring =
12578 v8::ScriptData::PreCompile(cstring, i::StrLength(cstring));
12579
12580 TestAsciiResource* resource = new TestAsciiResource(cstring);
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000012581 v8::ScriptData* sd_from_external_string = v8::ScriptData::PreCompile(
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +000012582 v8::String::NewExternal(resource));
12583
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000012584 v8::ScriptData* sd_from_string = v8::ScriptData::PreCompile(
12585 v8::String::New(cstring));
12586
12587 CHECK_EQ(sd_from_cstring->Length(), sd_from_external_string->Length());
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +000012588 CHECK_EQ(0, memcmp(sd_from_cstring->Data(),
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000012589 sd_from_external_string->Data(),
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +000012590 sd_from_cstring->Length()));
12591
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000012592 CHECK_EQ(sd_from_cstring->Length(), sd_from_string->Length());
12593 CHECK_EQ(0, memcmp(sd_from_cstring->Data(),
12594 sd_from_string->Data(),
12595 sd_from_cstring->Length()));
12596
12597
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +000012598 delete sd_from_cstring;
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000012599 delete sd_from_external_string;
12600 delete sd_from_string;
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +000012601}
12602
12603
ager@chromium.orga74f0da2008-12-03 16:05:52 +000012604// This tests that we do not allow dictionary load/call inline caches
12605// to use functions that have not yet been compiled. The potential
12606// problem of loading a function that has not yet been compiled can
12607// arise because we share code between contexts via the compilation
12608// cache.
12609THREADED_TEST(DictionaryICLoadedFunction) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000012610 v8::HandleScope scope(v8::Isolate::GetCurrent());
ager@chromium.orga74f0da2008-12-03 16:05:52 +000012611 // Test LoadIC.
12612 for (int i = 0; i < 2; i++) {
12613 LocalContext context;
12614 context->Global()->Set(v8_str("tmp"), v8::True());
12615 context->Global()->Delete(v8_str("tmp"));
12616 CompileRun("for (var j = 0; j < 10; j++) new RegExp('');");
12617 }
12618 // Test CallIC.
12619 for (int i = 0; i < 2; i++) {
12620 LocalContext context;
12621 context->Global()->Set(v8_str("tmp"), v8::True());
12622 context->Global()->Delete(v8_str("tmp"));
12623 CompileRun("for (var j = 0; j < 10; j++) RegExp('')");
12624 }
12625}
ager@chromium.orgddb913d2009-01-27 10:01:48 +000012626
12627
12628// Test that cross-context new calls use the context of the callee to
12629// create the new JavaScript object.
12630THREADED_TEST(CrossContextNew) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000012631 v8::HandleScope scope(v8::Isolate::GetCurrent());
ager@chromium.orgddb913d2009-01-27 10:01:48 +000012632 v8::Persistent<Context> context0 = Context::New();
12633 v8::Persistent<Context> context1 = Context::New();
12634
12635 // Allow cross-domain access.
12636 Local<String> token = v8_str("<security token>");
12637 context0->SetSecurityToken(token);
12638 context1->SetSecurityToken(token);
12639
12640 // Set an 'x' property on the Object prototype and define a
12641 // constructor function in context0.
12642 context0->Enter();
12643 CompileRun("Object.prototype.x = 42; function C() {};");
12644 context0->Exit();
12645
12646 // Call the constructor function from context0 and check that the
12647 // result has the 'x' property.
12648 context1->Enter();
12649 context1->Global()->Set(v8_str("other"), context0->Global());
12650 Local<Value> value = CompileRun("var instance = new other.C(); instance.x");
12651 CHECK(value->IsInt32());
12652 CHECK_EQ(42, value->Int32Value());
12653 context1->Exit();
12654
12655 // Dispose the contexts to allow them to be garbage collected.
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000012656 context0.Dispose(context0->GetIsolate());
12657 context1.Dispose(context1->GetIsolate());
ager@chromium.orgddb913d2009-01-27 10:01:48 +000012658}
ager@chromium.org381abbb2009-02-25 13:23:22 +000012659
12660
12661class RegExpInterruptTest {
12662 public:
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000012663 RegExpInterruptTest() : block_(NULL) {}
12664 ~RegExpInterruptTest() { delete block_; }
ager@chromium.org381abbb2009-02-25 13:23:22 +000012665 void RunTest() {
12666 block_ = i::OS::CreateSemaphore(0);
12667 gc_count_ = 0;
12668 gc_during_regexp_ = 0;
12669 regexp_success_ = false;
12670 gc_success_ = false;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000012671 GCThread gc_thread(this);
ager@chromium.org381abbb2009-02-25 13:23:22 +000012672 gc_thread.Start();
12673 v8::Locker::StartPreemption(1);
12674
12675 LongRunningRegExp();
12676 {
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000012677 v8::Unlocker unlock(CcTest::default_isolate());
ager@chromium.org381abbb2009-02-25 13:23:22 +000012678 gc_thread.Join();
12679 }
12680 v8::Locker::StopPreemption();
12681 CHECK(regexp_success_);
12682 CHECK(gc_success_);
12683 }
jkummerow@chromium.orge297f592011-06-08 10:05:15 +000012684
ager@chromium.org381abbb2009-02-25 13:23:22 +000012685 private:
12686 // Number of garbage collections required.
12687 static const int kRequiredGCs = 5;
12688
12689 class GCThread : public i::Thread {
12690 public:
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000012691 explicit GCThread(RegExpInterruptTest* test)
12692 : Thread("GCThread"), test_(test) {}
ager@chromium.org381abbb2009-02-25 13:23:22 +000012693 virtual void Run() {
12694 test_->CollectGarbage();
12695 }
12696 private:
12697 RegExpInterruptTest* test_;
12698 };
12699
12700 void CollectGarbage() {
12701 block_->Wait();
12702 while (gc_during_regexp_ < kRequiredGCs) {
12703 {
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000012704 v8::Locker lock(CcTest::default_isolate());
ager@chromium.org381abbb2009-02-25 13:23:22 +000012705 // TODO(lrn): Perhaps create some garbage before collecting.
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000012706 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org381abbb2009-02-25 13:23:22 +000012707 gc_count_++;
12708 }
12709 i::OS::Sleep(1);
12710 }
12711 gc_success_ = true;
12712 }
12713
12714 void LongRunningRegExp() {
12715 block_->Signal(); // Enable garbage collection thread on next preemption.
12716 int rounds = 0;
12717 while (gc_during_regexp_ < kRequiredGCs) {
12718 int gc_before = gc_count_;
12719 {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000012720 // Match 15-30 "a"'s against 14 and a "b".
ager@chromium.org381abbb2009-02-25 13:23:22 +000012721 const char* c_source =
12722 "/a?a?a?a?a?a?a?a?a?a?a?a?a?a?aaaaaaaaaaaaaaaa/"
12723 ".exec('aaaaaaaaaaaaaaab') === null";
12724 Local<String> source = String::New(c_source);
12725 Local<Script> script = Script::Compile(source);
12726 Local<Value> result = script->Run();
12727 if (!result->BooleanValue()) {
12728 gc_during_regexp_ = kRequiredGCs; // Allow gc thread to exit.
12729 return;
12730 }
12731 }
12732 {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000012733 // Match 15-30 "a"'s against 15 and a "b".
ager@chromium.org381abbb2009-02-25 13:23:22 +000012734 const char* c_source =
12735 "/a?a?a?a?a?a?a?a?a?a?a?a?a?a?aaaaaaaaaaaaaaaa/"
12736 ".exec('aaaaaaaaaaaaaaaab')[0] === 'aaaaaaaaaaaaaaaa'";
12737 Local<String> source = String::New(c_source);
12738 Local<Script> script = Script::Compile(source);
12739 Local<Value> result = script->Run();
12740 if (!result->BooleanValue()) {
12741 gc_during_regexp_ = kRequiredGCs;
12742 return;
12743 }
12744 }
12745 int gc_after = gc_count_;
12746 gc_during_regexp_ += gc_after - gc_before;
12747 rounds++;
12748 i::OS::Sleep(1);
12749 }
12750 regexp_success_ = true;
12751 }
12752
12753 i::Semaphore* block_;
12754 int gc_count_;
12755 int gc_during_regexp_;
12756 bool regexp_success_;
12757 bool gc_success_;
12758};
12759
12760
12761// Test that a regular expression execution can be interrupted and
12762// survive a garbage collection.
12763TEST(RegExpInterruption) {
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000012764 v8::Locker lock(CcTest::default_isolate());
ager@chromium.org381abbb2009-02-25 13:23:22 +000012765 v8::V8::Initialize();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000012766 v8::HandleScope scope(CcTest::default_isolate());
ager@chromium.org381abbb2009-02-25 13:23:22 +000012767 Local<Context> local_env;
12768 {
12769 LocalContext env;
12770 local_env = env.local();
12771 }
12772
12773 // Local context should still be live.
12774 CHECK(!local_env.IsEmpty());
12775 local_env->Enter();
12776
12777 // Should complete without problems.
12778 RegExpInterruptTest().RunTest();
12779
12780 local_env->Exit();
12781}
ager@chromium.org3b45ab52009-03-19 22:21:34 +000012782
12783
ager@chromium.org65dad4b2009-04-23 08:48:43 +000012784class ApplyInterruptTest {
12785 public:
12786 ApplyInterruptTest() : block_(NULL) {}
12787 ~ApplyInterruptTest() { delete block_; }
12788 void RunTest() {
12789 block_ = i::OS::CreateSemaphore(0);
12790 gc_count_ = 0;
12791 gc_during_apply_ = 0;
12792 apply_success_ = false;
12793 gc_success_ = false;
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000012794 GCThread gc_thread(this);
ager@chromium.org65dad4b2009-04-23 08:48:43 +000012795 gc_thread.Start();
12796 v8::Locker::StartPreemption(1);
12797
12798 LongRunningApply();
12799 {
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000012800 v8::Unlocker unlock(CcTest::default_isolate());
ager@chromium.org65dad4b2009-04-23 08:48:43 +000012801 gc_thread.Join();
12802 }
12803 v8::Locker::StopPreemption();
12804 CHECK(apply_success_);
12805 CHECK(gc_success_);
12806 }
jkummerow@chromium.orge297f592011-06-08 10:05:15 +000012807
ager@chromium.org65dad4b2009-04-23 08:48:43 +000012808 private:
12809 // Number of garbage collections required.
12810 static const int kRequiredGCs = 2;
12811
12812 class GCThread : public i::Thread {
12813 public:
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000012814 explicit GCThread(ApplyInterruptTest* test)
12815 : Thread("GCThread"), test_(test) {}
ager@chromium.org65dad4b2009-04-23 08:48:43 +000012816 virtual void Run() {
12817 test_->CollectGarbage();
12818 }
12819 private:
12820 ApplyInterruptTest* test_;
12821 };
12822
12823 void CollectGarbage() {
12824 block_->Wait();
12825 while (gc_during_apply_ < kRequiredGCs) {
12826 {
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000012827 v8::Locker lock(CcTest::default_isolate());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000012828 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org65dad4b2009-04-23 08:48:43 +000012829 gc_count_++;
12830 }
12831 i::OS::Sleep(1);
12832 }
12833 gc_success_ = true;
12834 }
12835
12836 void LongRunningApply() {
12837 block_->Signal();
12838 int rounds = 0;
12839 while (gc_during_apply_ < kRequiredGCs) {
12840 int gc_before = gc_count_;
12841 {
12842 const char* c_source =
12843 "function do_very_little(bar) {"
12844 " this.foo = bar;"
12845 "}"
12846 "for (var i = 0; i < 100000; i++) {"
12847 " do_very_little.apply(this, ['bar']);"
12848 "}";
12849 Local<String> source = String::New(c_source);
12850 Local<Script> script = Script::Compile(source);
12851 Local<Value> result = script->Run();
ager@chromium.org3a37e9b2009-04-27 09:26:21 +000012852 // Check that no exception was thrown.
12853 CHECK(!result.IsEmpty());
ager@chromium.org65dad4b2009-04-23 08:48:43 +000012854 }
12855 int gc_after = gc_count_;
12856 gc_during_apply_ += gc_after - gc_before;
12857 rounds++;
12858 }
12859 apply_success_ = true;
12860 }
12861
12862 i::Semaphore* block_;
12863 int gc_count_;
12864 int gc_during_apply_;
12865 bool apply_success_;
12866 bool gc_success_;
12867};
12868
12869
12870// Test that nothing bad happens if we get a preemption just when we were
12871// about to do an apply().
12872TEST(ApplyInterruption) {
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000012873 v8::Locker lock(CcTest::default_isolate());
ager@chromium.org65dad4b2009-04-23 08:48:43 +000012874 v8::V8::Initialize();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000012875 v8::HandleScope scope(CcTest::default_isolate());
ager@chromium.org65dad4b2009-04-23 08:48:43 +000012876 Local<Context> local_env;
12877 {
12878 LocalContext env;
12879 local_env = env.local();
12880 }
12881
12882 // Local context should still be live.
12883 CHECK(!local_env.IsEmpty());
12884 local_env->Enter();
12885
12886 // Should complete without problems.
12887 ApplyInterruptTest().RunTest();
12888
12889 local_env->Exit();
12890}
12891
12892
ager@chromium.org3b45ab52009-03-19 22:21:34 +000012893// Verify that we can clone an object
12894TEST(ObjectClone) {
ager@chromium.org3b45ab52009-03-19 22:21:34 +000012895 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000012896 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org3b45ab52009-03-19 22:21:34 +000012897
12898 const char* sample =
12899 "var rv = {};" \
12900 "rv.alpha = 'hello';" \
12901 "rv.beta = 123;" \
12902 "rv;";
12903
12904 // Create an object, verify basics.
12905 Local<Value> val = CompileRun(sample);
12906 CHECK(val->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000012907 Local<v8::Object> obj = val.As<v8::Object>();
ager@chromium.org3b45ab52009-03-19 22:21:34 +000012908 obj->Set(v8_str("gamma"), v8_str("cloneme"));
12909
12910 CHECK_EQ(v8_str("hello"), obj->Get(v8_str("alpha")));
12911 CHECK_EQ(v8::Integer::New(123), obj->Get(v8_str("beta")));
12912 CHECK_EQ(v8_str("cloneme"), obj->Get(v8_str("gamma")));
12913
12914 // Clone it.
12915 Local<v8::Object> clone = obj->Clone();
12916 CHECK_EQ(v8_str("hello"), clone->Get(v8_str("alpha")));
12917 CHECK_EQ(v8::Integer::New(123), clone->Get(v8_str("beta")));
12918 CHECK_EQ(v8_str("cloneme"), clone->Get(v8_str("gamma")));
12919
12920 // Set a property on the clone, verify each object.
12921 clone->Set(v8_str("beta"), v8::Integer::New(456));
12922 CHECK_EQ(v8::Integer::New(123), obj->Get(v8_str("beta")));
12923 CHECK_EQ(v8::Integer::New(456), clone->Get(v8_str("beta")));
12924}
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000012925
12926
ager@chromium.org5ec48922009-05-05 07:25:34 +000012927class AsciiVectorResource : public v8::String::ExternalAsciiStringResource {
12928 public:
12929 explicit AsciiVectorResource(i::Vector<const char> vector)
12930 : data_(vector) {}
12931 virtual ~AsciiVectorResource() {}
12932 virtual size_t length() const { return data_.length(); }
12933 virtual const char* data() const { return data_.start(); }
12934 private:
12935 i::Vector<const char> data_;
12936};
12937
12938
12939class UC16VectorResource : public v8::String::ExternalStringResource {
12940 public:
12941 explicit UC16VectorResource(i::Vector<const i::uc16> vector)
12942 : data_(vector) {}
12943 virtual ~UC16VectorResource() {}
12944 virtual size_t length() const { return data_.length(); }
12945 virtual const i::uc16* data() const { return data_.start(); }
12946 private:
12947 i::Vector<const i::uc16> data_;
12948};
12949
12950
12951static void MorphAString(i::String* string,
12952 AsciiVectorResource* ascii_resource,
12953 UC16VectorResource* uc16_resource) {
12954 CHECK(i::StringShape(string).IsExternal());
ulan@chromium.org8e8d8822012-11-23 14:36:46 +000012955 if (string->IsOneByteRepresentation()) {
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +000012956 // Check old map is not internalized or long.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000012957 CHECK(string->map() == HEAP->external_ascii_string_map());
ager@chromium.org5ec48922009-05-05 07:25:34 +000012958 // Morph external string to be TwoByte string.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000012959 string->set_map(HEAP->external_string_map());
ager@chromium.org5ec48922009-05-05 07:25:34 +000012960 i::ExternalTwoByteString* morphed =
12961 i::ExternalTwoByteString::cast(string);
12962 morphed->set_resource(uc16_resource);
12963 } else {
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +000012964 // Check old map is not internalized or long.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000012965 CHECK(string->map() == HEAP->external_string_map());
ager@chromium.org5ec48922009-05-05 07:25:34 +000012966 // Morph external string to be ASCII string.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000012967 string->set_map(HEAP->external_ascii_string_map());
ager@chromium.org5ec48922009-05-05 07:25:34 +000012968 i::ExternalAsciiString* morphed =
12969 i::ExternalAsciiString::cast(string);
12970 morphed->set_resource(ascii_resource);
12971 }
12972}
12973
12974
12975// Test that we can still flatten a string if the components it is built up
12976// from have been turned into 16 bit strings in the mean time.
12977THREADED_TEST(MorphCompositeStringTest) {
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +000012978 char utf_buffer[129];
ager@chromium.org5ec48922009-05-05 07:25:34 +000012979 const char* c_string = "Now is the time for all good men"
12980 " to come to the aid of the party";
12981 uint16_t* two_byte_string = AsciiToTwoByteString(c_string);
12982 {
ager@chromium.org5ec48922009-05-05 07:25:34 +000012983 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000012984 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org5ec48922009-05-05 07:25:34 +000012985 AsciiVectorResource ascii_resource(
ager@chromium.orgc4c92722009-11-18 14:12:51 +000012986 i::Vector<const char>(c_string, i::StrLength(c_string)));
ager@chromium.org5ec48922009-05-05 07:25:34 +000012987 UC16VectorResource uc16_resource(
ager@chromium.orgc4c92722009-11-18 14:12:51 +000012988 i::Vector<const uint16_t>(two_byte_string,
12989 i::StrLength(c_string)));
ager@chromium.org5ec48922009-05-05 07:25:34 +000012990
12991 Local<String> lhs(v8::Utils::ToLocal(
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000012992 FACTORY->NewExternalStringFromAscii(&ascii_resource)));
ager@chromium.org5ec48922009-05-05 07:25:34 +000012993 Local<String> rhs(v8::Utils::ToLocal(
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000012994 FACTORY->NewExternalStringFromAscii(&ascii_resource)));
ager@chromium.org5ec48922009-05-05 07:25:34 +000012995
12996 env->Global()->Set(v8_str("lhs"), lhs);
12997 env->Global()->Set(v8_str("rhs"), rhs);
12998
12999 CompileRun(
13000 "var cons = lhs + rhs;"
13001 "var slice = lhs.substring(1, lhs.length - 1);"
13002 "var slice_on_cons = (lhs + rhs).substring(1, lhs.length *2 - 1);");
13003
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013004 CHECK(lhs->IsOneByte());
13005 CHECK(rhs->IsOneByte());
rossberg@chromium.org2c067b12012-03-19 11:01:52 +000013006
ager@chromium.org5ec48922009-05-05 07:25:34 +000013007 MorphAString(*v8::Utils::OpenHandle(*lhs), &ascii_resource, &uc16_resource);
13008 MorphAString(*v8::Utils::OpenHandle(*rhs), &ascii_resource, &uc16_resource);
13009
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +000013010 // This should UTF-8 without flattening, since everything is ASCII.
13011 Handle<String> cons = v8_compile("cons")->Run().As<String>();
13012 CHECK_EQ(128, cons->Utf8Length());
13013 int nchars = -1;
13014 CHECK_EQ(129, cons->WriteUtf8(utf_buffer, -1, &nchars));
13015 CHECK_EQ(128, nchars);
13016 CHECK_EQ(0, strcmp(
13017 utf_buffer,
13018 "Now is the time for all good men to come to the aid of the party"
13019 "Now is the time for all good men to come to the aid of the party"));
13020
ager@chromium.org5ec48922009-05-05 07:25:34 +000013021 // Now do some stuff to make sure the strings are flattened, etc.
13022 CompileRun(
13023 "/[^a-z]/.test(cons);"
13024 "/[^a-z]/.test(slice);"
13025 "/[^a-z]/.test(slice_on_cons);");
13026 const char* expected_cons =
13027 "Now is the time for all good men to come to the aid of the party"
13028 "Now is the time for all good men to come to the aid of the party";
13029 const char* expected_slice =
13030 "ow is the time for all good men to come to the aid of the part";
13031 const char* expected_slice_on_cons =
13032 "ow is the time for all good men to come to the aid of the party"
13033 "Now is the time for all good men to come to the aid of the part";
13034 CHECK_EQ(String::New(expected_cons),
13035 env->Global()->Get(v8_str("cons")));
13036 CHECK_EQ(String::New(expected_slice),
13037 env->Global()->Get(v8_str("slice")));
13038 CHECK_EQ(String::New(expected_slice_on_cons),
13039 env->Global()->Get(v8_str("slice_on_cons")));
13040 }
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000013041 i::DeleteArray(two_byte_string);
ager@chromium.org5ec48922009-05-05 07:25:34 +000013042}
13043
13044
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000013045TEST(CompileExternalTwoByteSource) {
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000013046 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013047 v8::HandleScope scope(context->GetIsolate());
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000013048
13049 // This is a very short list of sources, which currently is to check for a
13050 // regression caused by r2703.
13051 const char* ascii_sources[] = {
13052 "0.5",
13053 "-0.5", // This mainly testes PushBack in the Scanner.
13054 "--0.5", // This mainly testes PushBack in the Scanner.
13055 NULL
13056 };
13057
13058 // Compile the sources as external two byte strings.
13059 for (int i = 0; ascii_sources[i] != NULL; i++) {
13060 uint16_t* two_byte_string = AsciiToTwoByteString(ascii_sources[i]);
13061 UC16VectorResource uc16_resource(
ager@chromium.orgc4c92722009-11-18 14:12:51 +000013062 i::Vector<const uint16_t>(two_byte_string,
13063 i::StrLength(ascii_sources[i])));
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000013064 v8::Local<v8::String> source = v8::String::NewExternal(&uc16_resource);
13065 v8::Script::Compile(source);
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000013066 i::DeleteArray(two_byte_string);
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000013067 }
13068}
13069
13070
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000013071class RegExpStringModificationTest {
13072 public:
13073 RegExpStringModificationTest()
13074 : block_(i::OS::CreateSemaphore(0)),
13075 morphs_(0),
13076 morphs_during_regexp_(0),
13077 ascii_resource_(i::Vector<const char>("aaaaaaaaaaaaaab", 15)),
13078 uc16_resource_(i::Vector<const uint16_t>(two_byte_content_, 15)) {}
13079 ~RegExpStringModificationTest() { delete block_; }
13080 void RunTest() {
13081 regexp_success_ = false;
13082 morph_success_ = false;
13083
13084 // Initialize the contents of two_byte_content_ to be a uc16 representation
13085 // of "aaaaaaaaaaaaaab".
13086 for (int i = 0; i < 14; i++) {
13087 two_byte_content_[i] = 'a';
13088 }
13089 two_byte_content_[14] = 'b';
13090
13091 // Create the input string for the regexp - the one we are going to change
13092 // properties of.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000013093 input_ = FACTORY->NewExternalStringFromAscii(&ascii_resource_);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000013094
13095 // Inject the input as a global variable.
13096 i::Handle<i::String> input_name =
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000013097 FACTORY->NewStringFromAscii(i::Vector<const char>("input", 5));
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000013098 i::Isolate::Current()->native_context()->global_object()->SetProperty(
ager@chromium.org9ee27ae2011-03-02 13:43:26 +000013099 *input_name,
13100 *input_,
13101 NONE,
13102 i::kNonStrictMode)->ToObjectChecked();
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000013103
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000013104 MorphThread morph_thread(this);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000013105 morph_thread.Start();
13106 v8::Locker::StartPreemption(1);
13107 LongRunningRegExp();
13108 {
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000013109 v8::Unlocker unlock(CcTest::default_isolate());
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000013110 morph_thread.Join();
13111 }
13112 v8::Locker::StopPreemption();
13113 CHECK(regexp_success_);
13114 CHECK(morph_success_);
13115 }
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000013116
jkummerow@chromium.orge297f592011-06-08 10:05:15 +000013117 private:
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000013118 // Number of string modifications required.
13119 static const int kRequiredModifications = 5;
13120 static const int kMaxModifications = 100;
13121
13122 class MorphThread : public i::Thread {
13123 public:
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000013124 explicit MorphThread(RegExpStringModificationTest* test)
13125 : Thread("MorphThread"), test_(test) {}
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000013126 virtual void Run() {
13127 test_->MorphString();
13128 }
13129 private:
13130 RegExpStringModificationTest* test_;
13131 };
13132
13133 void MorphString() {
13134 block_->Wait();
13135 while (morphs_during_regexp_ < kRequiredModifications &&
13136 morphs_ < kMaxModifications) {
13137 {
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000013138 v8::Locker lock(CcTest::default_isolate());
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000013139 // Swap string between ascii and two-byte representation.
13140 i::String* string = *input_;
ager@chromium.org5ec48922009-05-05 07:25:34 +000013141 MorphAString(string, &ascii_resource_, &uc16_resource_);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000013142 morphs_++;
13143 }
13144 i::OS::Sleep(1);
13145 }
13146 morph_success_ = true;
13147 }
13148
13149 void LongRunningRegExp() {
13150 block_->Signal(); // Enable morphing thread on next preemption.
13151 while (morphs_during_regexp_ < kRequiredModifications &&
13152 morphs_ < kMaxModifications) {
13153 int morphs_before = morphs_;
13154 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013155 v8::HandleScope scope(v8::Isolate::GetCurrent());
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000013156 // Match 15-30 "a"'s against 14 and a "b".
13157 const char* c_source =
13158 "/a?a?a?a?a?a?a?a?a?a?a?a?a?a?aaaaaaaaaaaaaaaa/"
13159 ".exec(input) === null";
13160 Local<String> source = String::New(c_source);
13161 Local<Script> script = Script::Compile(source);
13162 Local<Value> result = script->Run();
13163 CHECK(result->IsTrue());
13164 }
13165 int morphs_after = morphs_;
13166 morphs_during_regexp_ += morphs_after - morphs_before;
13167 }
13168 regexp_success_ = true;
13169 }
13170
13171 i::uc16 two_byte_content_[15];
13172 i::Semaphore* block_;
13173 int morphs_;
13174 int morphs_during_regexp_;
13175 bool regexp_success_;
13176 bool morph_success_;
13177 i::Handle<i::String> input_;
13178 AsciiVectorResource ascii_resource_;
13179 UC16VectorResource uc16_resource_;
13180};
13181
13182
13183// Test that a regular expression execution can be interrupted and
13184// the string changed without failing.
13185TEST(RegExpStringModification) {
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000013186 v8::Locker lock(CcTest::default_isolate());
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000013187 v8::V8::Initialize();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013188 v8::HandleScope scope(CcTest::default_isolate());
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000013189 Local<Context> local_env;
13190 {
13191 LocalContext env;
13192 local_env = env.local();
13193 }
13194
13195 // Local context should still be live.
13196 CHECK(!local_env.IsEmpty());
13197 local_env->Enter();
13198
13199 // Should complete without problems.
13200 RegExpStringModificationTest().RunTest();
13201
13202 local_env->Exit();
13203}
13204
13205
mmassi@chromium.org7028c052012-06-13 11:51:58 +000013206// Test that we cannot set a property on the global object if there
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000013207// is a read-only property in the prototype chain.
13208TEST(ReadOnlyPropertyInGlobalProto) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +000013209 i::FLAG_es5_readonly = true;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013210 v8::HandleScope scope(v8::Isolate::GetCurrent());
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000013211 v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
13212 LocalContext context(0, templ);
13213 v8::Handle<v8::Object> global = context->Global();
13214 v8::Handle<v8::Object> global_proto =
13215 v8::Handle<v8::Object>::Cast(global->Get(v8_str("__proto__")));
13216 global_proto->Set(v8_str("x"), v8::Integer::New(0), v8::ReadOnly);
13217 global_proto->Set(v8_str("y"), v8::Integer::New(0), v8::ReadOnly);
13218 // Check without 'eval' or 'with'.
13219 v8::Handle<v8::Value> res =
13220 CompileRun("function f() { x = 42; return x; }; f()");
mmassi@chromium.org7028c052012-06-13 11:51:58 +000013221 CHECK_EQ(v8::Integer::New(0), res);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000013222 // Check with 'eval'.
mmassi@chromium.org7028c052012-06-13 11:51:58 +000013223 res = CompileRun("function f() { eval('1'); y = 43; return y; }; f()");
13224 CHECK_EQ(v8::Integer::New(0), res);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000013225 // Check with 'with'.
mmassi@chromium.org7028c052012-06-13 11:51:58 +000013226 res = CompileRun("function f() { with (this) { y = 44 }; return y; }; f()");
13227 CHECK_EQ(v8::Integer::New(0), res);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000013228}
ager@chromium.org65dad4b2009-04-23 08:48:43 +000013229
13230static int force_set_set_count = 0;
13231static int force_set_get_count = 0;
13232bool pass_on_get = false;
13233
13234static v8::Handle<v8::Value> ForceSetGetter(v8::Local<v8::String> name,
13235 const v8::AccessorInfo& info) {
13236 force_set_get_count++;
13237 if (pass_on_get) {
13238 return v8::Handle<v8::Value>();
13239 } else {
13240 return v8::Int32::New(3);
13241 }
13242}
13243
13244static void ForceSetSetter(v8::Local<v8::String> name,
13245 v8::Local<v8::Value> value,
13246 const v8::AccessorInfo& info) {
13247 force_set_set_count++;
13248}
13249
13250static v8::Handle<v8::Value> ForceSetInterceptSetter(
13251 v8::Local<v8::String> name,
13252 v8::Local<v8::Value> value,
13253 const v8::AccessorInfo& info) {
13254 force_set_set_count++;
13255 return v8::Undefined();
13256}
13257
13258TEST(ForceSet) {
13259 force_set_get_count = 0;
13260 force_set_set_count = 0;
13261 pass_on_get = false;
13262
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013263 v8::HandleScope scope(v8::Isolate::GetCurrent());
ager@chromium.org65dad4b2009-04-23 08:48:43 +000013264 v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
13265 v8::Handle<v8::String> access_property = v8::String::New("a");
13266 templ->SetAccessor(access_property, ForceSetGetter, ForceSetSetter);
13267 LocalContext context(NULL, templ);
13268 v8::Handle<v8::Object> global = context->Global();
13269
13270 // Ordinary properties
13271 v8::Handle<v8::String> simple_property = v8::String::New("p");
13272 global->Set(simple_property, v8::Int32::New(4), v8::ReadOnly);
13273 CHECK_EQ(4, global->Get(simple_property)->Int32Value());
13274 // This should fail because the property is read-only
13275 global->Set(simple_property, v8::Int32::New(5));
13276 CHECK_EQ(4, global->Get(simple_property)->Int32Value());
13277 // This should succeed even though the property is read-only
13278 global->ForceSet(simple_property, v8::Int32::New(6));
13279 CHECK_EQ(6, global->Get(simple_property)->Int32Value());
13280
13281 // Accessors
13282 CHECK_EQ(0, force_set_set_count);
13283 CHECK_EQ(0, force_set_get_count);
13284 CHECK_EQ(3, global->Get(access_property)->Int32Value());
13285 // CHECK_EQ the property shouldn't override it, just call the setter
13286 // which in this case does nothing.
13287 global->Set(access_property, v8::Int32::New(7));
13288 CHECK_EQ(3, global->Get(access_property)->Int32Value());
13289 CHECK_EQ(1, force_set_set_count);
13290 CHECK_EQ(2, force_set_get_count);
13291 // Forcing the property to be set should override the accessor without
13292 // calling it
13293 global->ForceSet(access_property, v8::Int32::New(8));
13294 CHECK_EQ(8, global->Get(access_property)->Int32Value());
13295 CHECK_EQ(1, force_set_set_count);
13296 CHECK_EQ(2, force_set_get_count);
13297}
13298
13299TEST(ForceSetWithInterceptor) {
13300 force_set_get_count = 0;
13301 force_set_set_count = 0;
13302 pass_on_get = false;
13303
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013304 v8::HandleScope scope(v8::Isolate::GetCurrent());
ager@chromium.org65dad4b2009-04-23 08:48:43 +000013305 v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
13306 templ->SetNamedPropertyHandler(ForceSetGetter, ForceSetInterceptSetter);
13307 LocalContext context(NULL, templ);
13308 v8::Handle<v8::Object> global = context->Global();
13309
13310 v8::Handle<v8::String> some_property = v8::String::New("a");
13311 CHECK_EQ(0, force_set_set_count);
13312 CHECK_EQ(0, force_set_get_count);
13313 CHECK_EQ(3, global->Get(some_property)->Int32Value());
13314 // Setting the property shouldn't override it, just call the setter
13315 // which in this case does nothing.
13316 global->Set(some_property, v8::Int32::New(7));
13317 CHECK_EQ(3, global->Get(some_property)->Int32Value());
13318 CHECK_EQ(1, force_set_set_count);
13319 CHECK_EQ(2, force_set_get_count);
13320 // Getting the property when the interceptor returns an empty handle
13321 // should yield undefined, since the property isn't present on the
13322 // object itself yet.
13323 pass_on_get = true;
13324 CHECK(global->Get(some_property)->IsUndefined());
13325 CHECK_EQ(1, force_set_set_count);
13326 CHECK_EQ(3, force_set_get_count);
13327 // Forcing the property to be set should cause the value to be
13328 // set locally without calling the interceptor.
13329 global->ForceSet(some_property, v8::Int32::New(8));
13330 CHECK_EQ(8, global->Get(some_property)->Int32Value());
13331 CHECK_EQ(1, force_set_set_count);
13332 CHECK_EQ(4, force_set_get_count);
13333 // Reenabling the interceptor should cause it to take precedence over
13334 // the property
13335 pass_on_get = false;
13336 CHECK_EQ(3, global->Get(some_property)->Int32Value());
13337 CHECK_EQ(1, force_set_set_count);
13338 CHECK_EQ(5, force_set_get_count);
13339 // The interceptor should also work for other properties
13340 CHECK_EQ(3, global->Get(v8::String::New("b"))->Int32Value());
13341 CHECK_EQ(1, force_set_set_count);
13342 CHECK_EQ(6, force_set_get_count);
13343}
ager@chromium.org1bf0cd02009-05-20 11:34:19 +000013344
13345
ager@chromium.orge2902be2009-06-08 12:21:35 +000013346THREADED_TEST(ForceDelete) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013347 v8::HandleScope scope(v8::Isolate::GetCurrent());
ager@chromium.orge2902be2009-06-08 12:21:35 +000013348 v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
13349 LocalContext context(NULL, templ);
13350 v8::Handle<v8::Object> global = context->Global();
13351
13352 // Ordinary properties
13353 v8::Handle<v8::String> simple_property = v8::String::New("p");
13354 global->Set(simple_property, v8::Int32::New(4), v8::DontDelete);
13355 CHECK_EQ(4, global->Get(simple_property)->Int32Value());
13356 // This should fail because the property is dont-delete.
13357 CHECK(!global->Delete(simple_property));
13358 CHECK_EQ(4, global->Get(simple_property)->Int32Value());
13359 // This should succeed even though the property is dont-delete.
13360 CHECK(global->ForceDelete(simple_property));
13361 CHECK(global->Get(simple_property)->IsUndefined());
13362}
13363
13364
13365static int force_delete_interceptor_count = 0;
13366static bool pass_on_delete = false;
13367
13368
13369static v8::Handle<v8::Boolean> ForceDeleteDeleter(
13370 v8::Local<v8::String> name,
13371 const v8::AccessorInfo& info) {
13372 force_delete_interceptor_count++;
13373 if (pass_on_delete) {
13374 return v8::Handle<v8::Boolean>();
13375 } else {
13376 return v8::True();
13377 }
13378}
13379
13380
13381THREADED_TEST(ForceDeleteWithInterceptor) {
13382 force_delete_interceptor_count = 0;
13383 pass_on_delete = false;
13384
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013385 v8::HandleScope scope(v8::Isolate::GetCurrent());
ager@chromium.orge2902be2009-06-08 12:21:35 +000013386 v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
13387 templ->SetNamedPropertyHandler(0, 0, 0, ForceDeleteDeleter);
13388 LocalContext context(NULL, templ);
13389 v8::Handle<v8::Object> global = context->Global();
13390
13391 v8::Handle<v8::String> some_property = v8::String::New("a");
13392 global->Set(some_property, v8::Integer::New(42), v8::DontDelete);
13393
13394 // Deleting a property should get intercepted and nothing should
13395 // happen.
13396 CHECK_EQ(0, force_delete_interceptor_count);
13397 CHECK(global->Delete(some_property));
13398 CHECK_EQ(1, force_delete_interceptor_count);
13399 CHECK_EQ(42, global->Get(some_property)->Int32Value());
13400 // Deleting the property when the interceptor returns an empty
13401 // handle should not delete the property since it is DontDelete.
13402 pass_on_delete = true;
13403 CHECK(!global->Delete(some_property));
13404 CHECK_EQ(2, force_delete_interceptor_count);
13405 CHECK_EQ(42, global->Get(some_property)->Int32Value());
13406 // Forcing the property to be deleted should delete the value
13407 // without calling the interceptor.
13408 CHECK(global->ForceDelete(some_property));
13409 CHECK(global->Get(some_property)->IsUndefined());
13410 CHECK_EQ(2, force_delete_interceptor_count);
13411}
13412
13413
kasperl@chromium.org68ac0092009-07-09 06:00:35 +000013414// Make sure that forcing a delete invalidates any IC stubs, so we
13415// don't read the hole value.
13416THREADED_TEST(ForceDeleteIC) {
kasperl@chromium.org68ac0092009-07-09 06:00:35 +000013417 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013418 v8::HandleScope scope(context->GetIsolate());
kasperl@chromium.org68ac0092009-07-09 06:00:35 +000013419 // Create a DontDelete variable on the global object.
13420 CompileRun("this.__proto__ = { foo: 'horse' };"
13421 "var foo = 'fish';"
13422 "function f() { return foo.length; }");
13423 // Initialize the IC for foo in f.
13424 CompileRun("for (var i = 0; i < 4; i++) f();");
13425 // Make sure the value of foo is correct before the deletion.
13426 CHECK_EQ(4, CompileRun("f()")->Int32Value());
13427 // Force the deletion of foo.
13428 CHECK(context->Global()->ForceDelete(v8_str("foo")));
13429 // Make sure the value for foo is read from the prototype, and that
13430 // we don't get in trouble with reading the deleted cell value
13431 // sentinel.
13432 CHECK_EQ(5, CompileRun("f()")->Int32Value());
13433}
13434
13435
mstarzinger@chromium.org88d326b2012-04-23 12:57:22 +000013436TEST(InlinedFunctionAcrossContexts) {
13437 i::FLAG_allow_natives_syntax = true;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013438 v8::HandleScope outer_scope(v8::Isolate::GetCurrent());
mstarzinger@chromium.org88d326b2012-04-23 12:57:22 +000013439 v8::Persistent<v8::Context> ctx1 = v8::Context::New();
13440 v8::Persistent<v8::Context> ctx2 = v8::Context::New();
13441 ctx1->Enter();
13442
13443 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013444 v8::HandleScope inner_scope(v8::Isolate::GetCurrent());
mstarzinger@chromium.org88d326b2012-04-23 12:57:22 +000013445 CompileRun("var G = 42; function foo() { return G; }");
13446 v8::Local<v8::Value> foo = ctx1->Global()->Get(v8_str("foo"));
13447 ctx2->Enter();
13448 ctx2->Global()->Set(v8_str("o"), foo);
13449 v8::Local<v8::Value> res = CompileRun(
13450 "function f() { return o(); }"
13451 "for (var i = 0; i < 10; ++i) f();"
13452 "%OptimizeFunctionOnNextCall(f);"
13453 "f();");
13454 CHECK_EQ(42, res->Int32Value());
13455 ctx2->Exit();
13456 v8::Handle<v8::String> G_property = v8::String::New("G");
13457 CHECK(ctx1->Global()->ForceDelete(G_property));
13458 ctx2->Enter();
13459 ExpectString(
13460 "(function() {"
13461 " try {"
13462 " return f();"
13463 " } catch(e) {"
13464 " return e.toString();"
13465 " }"
13466 " })()",
13467 "ReferenceError: G is not defined");
13468 ctx2->Exit();
13469 ctx1->Exit();
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000013470 ctx1.Dispose(ctx1->GetIsolate());
mstarzinger@chromium.org88d326b2012-04-23 12:57:22 +000013471 }
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000013472 ctx2.Dispose(ctx2->GetIsolate());
mstarzinger@chromium.org88d326b2012-04-23 12:57:22 +000013473}
13474
13475
ager@chromium.org1bf0cd02009-05-20 11:34:19 +000013476v8::Persistent<Context> calling_context0;
13477v8::Persistent<Context> calling_context1;
13478v8::Persistent<Context> calling_context2;
13479
13480
13481// Check that the call to the callback is initiated in
13482// calling_context2, the directly calling context is calling_context1
13483// and the callback itself is in calling_context0.
13484static v8::Handle<Value> GetCallingContextCallback(const v8::Arguments& args) {
13485 ApiTestFuzzer::Fuzz();
13486 CHECK(Context::GetCurrent() == calling_context0);
mvstanton@chromium.org40ce96b2013-04-09 09:52:22 +000013487 CHECK(args.GetIsolate()->GetCurrentContext() == calling_context0);
ager@chromium.org1bf0cd02009-05-20 11:34:19 +000013488 CHECK(Context::GetCalling() == calling_context1);
13489 CHECK(Context::GetEntered() == calling_context2);
13490 return v8::Integer::New(42);
13491}
13492
13493
13494THREADED_TEST(GetCallingContext) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013495 v8::HandleScope scope(v8::Isolate::GetCurrent());
ager@chromium.org1bf0cd02009-05-20 11:34:19 +000013496
13497 calling_context0 = Context::New();
13498 calling_context1 = Context::New();
13499 calling_context2 = Context::New();
13500
13501 // Allow cross-domain access.
13502 Local<String> token = v8_str("<security token>");
13503 calling_context0->SetSecurityToken(token);
13504 calling_context1->SetSecurityToken(token);
13505 calling_context2->SetSecurityToken(token);
13506
13507 // Create an object with a C++ callback in context0.
13508 calling_context0->Enter();
13509 Local<v8::FunctionTemplate> callback_templ =
13510 v8::FunctionTemplate::New(GetCallingContextCallback);
13511 calling_context0->Global()->Set(v8_str("callback"),
13512 callback_templ->GetFunction());
13513 calling_context0->Exit();
13514
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000013515 // Expose context0 in context1 and set up a function that calls the
ager@chromium.org1bf0cd02009-05-20 11:34:19 +000013516 // callback function.
13517 calling_context1->Enter();
13518 calling_context1->Global()->Set(v8_str("context0"),
13519 calling_context0->Global());
13520 CompileRun("function f() { context0.callback() }");
13521 calling_context1->Exit();
13522
13523 // Expose context1 in context2 and call the callback function in
13524 // context0 indirectly through f in context1.
13525 calling_context2->Enter();
13526 calling_context2->Global()->Set(v8_str("context1"),
13527 calling_context1->Global());
13528 CompileRun("context1.f()");
13529 calling_context2->Exit();
13530
13531 // Dispose the contexts to allow them to be garbage collected.
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000013532 calling_context0.Dispose(calling_context0->GetIsolate());
13533 calling_context1.Dispose(calling_context1->GetIsolate());
13534 calling_context2.Dispose(calling_context2->GetIsolate());
ager@chromium.org1bf0cd02009-05-20 11:34:19 +000013535 calling_context0.Clear();
13536 calling_context1.Clear();
13537 calling_context2.Clear();
13538}
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000013539
13540
13541// Check that a variable declaration with no explicit initialization
erik.corry@gmail.comed49e962012-04-17 11:57:53 +000013542// value does shadow an existing property in the prototype chain.
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000013543THREADED_TEST(InitGlobalVarInProtoChain) {
mstarzinger@chromium.org88d326b2012-04-23 12:57:22 +000013544 i::FLAG_es52_globals = true;
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000013545 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013546 v8::HandleScope scope(context->GetIsolate());
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000013547 // Introduce a variable in the prototype chain.
13548 CompileRun("__proto__.x = 42");
erik.corry@gmail.comed49e962012-04-17 11:57:53 +000013549 v8::Handle<v8::Value> result = CompileRun("var x = 43; x");
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000013550 CHECK(!result->IsUndefined());
erik.corry@gmail.comed49e962012-04-17 11:57:53 +000013551 CHECK_EQ(43, result->Int32Value());
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000013552}
kasperl@chromium.org68ac0092009-07-09 06:00:35 +000013553
13554
13555// Regression test for issue 398.
13556// If a function is added to an object, creating a constant function
13557// field, and the result is cloned, replacing the constant function on the
13558// original should not affect the clone.
13559// See http://code.google.com/p/v8/issues/detail?id=398
13560THREADED_TEST(ReplaceConstantFunction) {
kasperl@chromium.org68ac0092009-07-09 06:00:35 +000013561 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013562 v8::HandleScope scope(context->GetIsolate());
kasperl@chromium.org68ac0092009-07-09 06:00:35 +000013563 v8::Handle<v8::Object> obj = v8::Object::New();
13564 v8::Handle<v8::FunctionTemplate> func_templ = v8::FunctionTemplate::New();
13565 v8::Handle<v8::String> foo_string = v8::String::New("foo");
13566 obj->Set(foo_string, func_templ->GetFunction());
13567 v8::Handle<v8::Object> obj_clone = obj->Clone();
13568 obj_clone->Set(foo_string, v8::String::New("Hello"));
13569 CHECK(!obj->Get(foo_string)->IsUndefined());
13570}
kasperl@chromium.orge959c182009-07-27 08:59:04 +000013571
13572
13573// Regression test for http://crbug.com/16276.
13574THREADED_TEST(Regress16276) {
kasperl@chromium.orge959c182009-07-27 08:59:04 +000013575 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013576 v8::HandleScope scope(context->GetIsolate());
kasperl@chromium.orge959c182009-07-27 08:59:04 +000013577 // Force the IC in f to be a dictionary load IC.
13578 CompileRun("function f(obj) { return obj.x; }\n"
13579 "var obj = { x: { foo: 42 }, y: 87 };\n"
13580 "var x = obj.x;\n"
13581 "delete obj.y;\n"
13582 "for (var i = 0; i < 5; i++) f(obj);");
13583 // Detach the global object to make 'this' refer directly to the
13584 // global object (not the proxy), and make sure that the dictionary
13585 // load IC doesn't mess up loading directly from the global object.
13586 context->DetachGlobal();
13587 CHECK_EQ(42, CompileRun("f(this).foo")->Int32Value());
13588}
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000013589
13590
13591THREADED_TEST(PixelArray) {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000013592 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013593 v8::HandleScope scope(context->GetIsolate());
ager@chromium.orgc4c92722009-11-18 14:12:51 +000013594 const int kElementCount = 260;
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000013595 uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(kElementCount));
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000013596 i::Handle<i::ExternalPixelArray> pixels =
13597 i::Handle<i::ExternalPixelArray>::cast(
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000013598 FACTORY->NewExternalArray(kElementCount,
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000013599 v8::kExternalPixelArray,
13600 pixel_data));
13601 // Force GC to trigger verification.
13602 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000013603 for (int i = 0; i < kElementCount; i++) {
ager@chromium.orgc4c92722009-11-18 14:12:51 +000013604 pixels->set(i, i % 256);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000013605 }
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000013606 // Force GC to trigger verification.
13607 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000013608 for (int i = 0; i < kElementCount; i++) {
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +000013609 CHECK_EQ(i % 256, pixels->get_scalar(i));
ager@chromium.orgc4c92722009-11-18 14:12:51 +000013610 CHECK_EQ(i % 256, pixel_data[i]);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000013611 }
13612
13613 v8::Handle<v8::Object> obj = v8::Object::New();
13614 i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
13615 // Set the elements to be the pixels.
13616 // jsobj->set_elements(*pixels);
13617 obj->SetIndexedPropertiesToPixelData(pixel_data, kElementCount);
lrn@chromium.org303ada72010-10-27 09:33:13 +000013618 CHECK_EQ(1, i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value());
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000013619 obj->Set(v8_str("field"), v8::Int32::New(1503));
13620 context->Global()->Set(v8_str("pixels"), obj);
13621 v8::Handle<v8::Value> result = CompileRun("pixels.field");
13622 CHECK_EQ(1503, result->Int32Value());
13623 result = CompileRun("pixels[1]");
13624 CHECK_EQ(1, result->Int32Value());
sgjesse@chromium.org9eceac12009-09-30 07:18:41 +000013625
13626 result = CompileRun("var sum = 0;"
13627 "for (var i = 0; i < 8; i++) {"
13628 " sum += pixels[i] = pixels[i] = -i;"
13629 "}"
13630 "sum;");
13631 CHECK_EQ(-28, result->Int32Value());
13632
13633 result = CompileRun("var sum = 0;"
13634 "for (var i = 0; i < 8; i++) {"
13635 " sum += pixels[i] = pixels[i] = 0;"
13636 "}"
13637 "sum;");
13638 CHECK_EQ(0, result->Int32Value());
13639
13640 result = CompileRun("var sum = 0;"
13641 "for (var i = 0; i < 8; i++) {"
13642 " sum += pixels[i] = pixels[i] = 255;"
13643 "}"
13644 "sum;");
13645 CHECK_EQ(8 * 255, result->Int32Value());
13646
13647 result = CompileRun("var sum = 0;"
13648 "for (var i = 0; i < 8; i++) {"
13649 " sum += pixels[i] = pixels[i] = 256 + i;"
13650 "}"
13651 "sum;");
13652 CHECK_EQ(2076, result->Int32Value());
13653
13654 result = CompileRun("var sum = 0;"
13655 "for (var i = 0; i < 8; i++) {"
13656 " sum += pixels[i] = pixels[i] = i;"
13657 "}"
13658 "sum;");
13659 CHECK_EQ(28, result->Int32Value());
13660
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000013661 result = CompileRun("var sum = 0;"
13662 "for (var i = 0; i < 8; i++) {"
13663 " sum += pixels[i];"
13664 "}"
13665 "sum;");
13666 CHECK_EQ(28, result->Int32Value());
13667
ulan@chromium.org09d7ab52013-02-25 15:50:35 +000013668 i::Handle<i::Smi> value(i::Smi::FromInt(2),
13669 reinterpret_cast<i::Isolate*>(context->GetIsolate()));
jkummerow@chromium.org486075a2011-09-07 12:44:28 +000013670 i::Handle<i::Object> no_failure;
yangguo@chromium.orgab30bb82012-02-24 14:41:46 +000013671 no_failure =
13672 i::JSObject::SetElement(jsobj, 1, value, NONE, i::kNonStrictMode);
jkummerow@chromium.org486075a2011-09-07 12:44:28 +000013673 ASSERT(!no_failure.is_null());
13674 i::USE(no_failure);
lrn@chromium.org303ada72010-10-27 09:33:13 +000013675 CHECK_EQ(2, i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value());
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000013676 *value.location() = i::Smi::FromInt(256);
yangguo@chromium.orgab30bb82012-02-24 14:41:46 +000013677 no_failure =
13678 i::JSObject::SetElement(jsobj, 1, value, NONE, i::kNonStrictMode);
jkummerow@chromium.org486075a2011-09-07 12:44:28 +000013679 ASSERT(!no_failure.is_null());
13680 i::USE(no_failure);
lrn@chromium.org303ada72010-10-27 09:33:13 +000013681 CHECK_EQ(255,
13682 i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value());
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000013683 *value.location() = i::Smi::FromInt(-1);
yangguo@chromium.orgab30bb82012-02-24 14:41:46 +000013684 no_failure =
13685 i::JSObject::SetElement(jsobj, 1, value, NONE, i::kNonStrictMode);
jkummerow@chromium.org486075a2011-09-07 12:44:28 +000013686 ASSERT(!no_failure.is_null());
13687 i::USE(no_failure);
lrn@chromium.org303ada72010-10-27 09:33:13 +000013688 CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value());
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000013689
13690 result = CompileRun("for (var i = 0; i < 8; i++) {"
13691 " pixels[i] = (i * 65) - 109;"
13692 "}"
13693 "pixels[1] + pixels[6];");
13694 CHECK_EQ(255, result->Int32Value());
lrn@chromium.org303ada72010-10-27 09:33:13 +000013695 CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(0)->ToObjectChecked())->value());
13696 CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value());
13697 CHECK_EQ(21,
13698 i::Smi::cast(jsobj->GetElement(2)->ToObjectChecked())->value());
13699 CHECK_EQ(86,
13700 i::Smi::cast(jsobj->GetElement(3)->ToObjectChecked())->value());
13701 CHECK_EQ(151,
13702 i::Smi::cast(jsobj->GetElement(4)->ToObjectChecked())->value());
13703 CHECK_EQ(216,
13704 i::Smi::cast(jsobj->GetElement(5)->ToObjectChecked())->value());
13705 CHECK_EQ(255,
13706 i::Smi::cast(jsobj->GetElement(6)->ToObjectChecked())->value());
13707 CHECK_EQ(255,
13708 i::Smi::cast(jsobj->GetElement(7)->ToObjectChecked())->value());
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000013709 result = CompileRun("var sum = 0;"
13710 "for (var i = 0; i < 8; i++) {"
13711 " sum += pixels[i];"
13712 "}"
13713 "sum;");
13714 CHECK_EQ(984, result->Int32Value());
13715
13716 result = CompileRun("for (var i = 0; i < 8; i++) {"
13717 " pixels[i] = (i * 1.1);"
13718 "}"
13719 "pixels[1] + pixels[6];");
13720 CHECK_EQ(8, result->Int32Value());
lrn@chromium.org303ada72010-10-27 09:33:13 +000013721 CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(0)->ToObjectChecked())->value());
13722 CHECK_EQ(1, i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value());
13723 CHECK_EQ(2, i::Smi::cast(jsobj->GetElement(2)->ToObjectChecked())->value());
13724 CHECK_EQ(3, i::Smi::cast(jsobj->GetElement(3)->ToObjectChecked())->value());
13725 CHECK_EQ(4, i::Smi::cast(jsobj->GetElement(4)->ToObjectChecked())->value());
13726 CHECK_EQ(6, i::Smi::cast(jsobj->GetElement(5)->ToObjectChecked())->value());
13727 CHECK_EQ(7, i::Smi::cast(jsobj->GetElement(6)->ToObjectChecked())->value());
13728 CHECK_EQ(8, i::Smi::cast(jsobj->GetElement(7)->ToObjectChecked())->value());
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000013729
13730 result = CompileRun("for (var i = 0; i < 8; i++) {"
13731 " pixels[7] = undefined;"
13732 "}"
13733 "pixels[7];");
13734 CHECK_EQ(0, result->Int32Value());
lrn@chromium.org303ada72010-10-27 09:33:13 +000013735 CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(7)->ToObjectChecked())->value());
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000013736
13737 result = CompileRun("for (var i = 0; i < 8; i++) {"
13738 " pixels[6] = '2.3';"
13739 "}"
13740 "pixels[6];");
13741 CHECK_EQ(2, result->Int32Value());
lrn@chromium.org303ada72010-10-27 09:33:13 +000013742 CHECK_EQ(2, i::Smi::cast(jsobj->GetElement(6)->ToObjectChecked())->value());
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000013743
13744 result = CompileRun("for (var i = 0; i < 8; i++) {"
13745 " pixels[5] = NaN;"
13746 "}"
13747 "pixels[5];");
13748 CHECK_EQ(0, result->Int32Value());
lrn@chromium.org303ada72010-10-27 09:33:13 +000013749 CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(5)->ToObjectChecked())->value());
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000013750
13751 result = CompileRun("for (var i = 0; i < 8; i++) {"
13752 " pixels[8] = Infinity;"
13753 "}"
13754 "pixels[8];");
13755 CHECK_EQ(255, result->Int32Value());
lrn@chromium.org303ada72010-10-27 09:33:13 +000013756 CHECK_EQ(255,
13757 i::Smi::cast(jsobj->GetElement(8)->ToObjectChecked())->value());
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000013758
13759 result = CompileRun("for (var i = 0; i < 8; i++) {"
13760 " pixels[9] = -Infinity;"
13761 "}"
13762 "pixels[9];");
13763 CHECK_EQ(0, result->Int32Value());
lrn@chromium.org303ada72010-10-27 09:33:13 +000013764 CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(9)->ToObjectChecked())->value());
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000013765
13766 result = CompileRun("pixels[3] = 33;"
13767 "delete pixels[3];"
13768 "pixels[3];");
13769 CHECK_EQ(33, result->Int32Value());
13770
13771 result = CompileRun("pixels[0] = 10; pixels[1] = 11;"
13772 "pixels[2] = 12; pixels[3] = 13;"
13773 "pixels.__defineGetter__('2',"
13774 "function() { return 120; });"
13775 "pixels[2];");
13776 CHECK_EQ(12, result->Int32Value());
13777
13778 result = CompileRun("var js_array = new Array(40);"
13779 "js_array[0] = 77;"
13780 "js_array;");
13781 CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
13782
13783 result = CompileRun("pixels[1] = 23;"
13784 "pixels.__proto__ = [];"
13785 "js_array.__proto__ = pixels;"
13786 "js_array.concat(pixels);");
13787 CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
13788 CHECK_EQ(23, v8::Object::Cast(*result)->Get(v8_str("1"))->Int32Value());
13789
sgjesse@chromium.org9eceac12009-09-30 07:18:41 +000013790 result = CompileRun("pixels[1] = 23;");
13791 CHECK_EQ(23, result->Int32Value());
13792
ager@chromium.orgc4c92722009-11-18 14:12:51 +000013793 // Test for index greater than 255. Regression test for:
13794 // http://code.google.com/p/chromium/issues/detail?id=26337.
13795 result = CompileRun("pixels[256] = 255;");
13796 CHECK_EQ(255, result->Int32Value());
13797 result = CompileRun("var i = 0;"
13798 "for (var j = 0; j < 8; j++) { i = pixels[256]; }"
13799 "i");
13800 CHECK_EQ(255, result->Int32Value());
13801
ricow@chromium.org83aa5492011-02-07 12:42:56 +000013802 // Make sure that pixel array ICs recognize when a non-pixel array
13803 // is passed to it.
13804 result = CompileRun("function pa_load(p) {"
13805 " var sum = 0;"
13806 " for (var j = 0; j < 256; j++) { sum += p[j]; }"
13807 " return sum;"
13808 "}"
13809 "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
13810 "for (var i = 0; i < 10; ++i) { pa_load(pixels); }"
13811 "just_ints = new Object();"
13812 "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
13813 "for (var i = 0; i < 10; ++i) {"
13814 " result = pa_load(just_ints);"
13815 "}"
13816 "result");
13817 CHECK_EQ(32640, result->Int32Value());
13818
13819 // Make sure that pixel array ICs recognize out-of-bound accesses.
13820 result = CompileRun("function pa_load(p, start) {"
13821 " var sum = 0;"
13822 " for (var j = start; j < 256; j++) { sum += p[j]; }"
13823 " return sum;"
13824 "}"
13825 "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
13826 "for (var i = 0; i < 10; ++i) { pa_load(pixels,0); }"
13827 "for (var i = 0; i < 10; ++i) {"
13828 " result = pa_load(pixels,-10);"
13829 "}"
13830 "result");
13831 CHECK_EQ(0, result->Int32Value());
13832
13833 // Make sure that generic ICs properly handles a pixel array.
13834 result = CompileRun("function pa_load(p) {"
13835 " var sum = 0;"
13836 " for (var j = 0; j < 256; j++) { sum += p[j]; }"
13837 " return sum;"
13838 "}"
13839 "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
13840 "just_ints = new Object();"
13841 "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
13842 "for (var i = 0; i < 10; ++i) { pa_load(just_ints); }"
13843 "for (var i = 0; i < 10; ++i) {"
13844 " result = pa_load(pixels);"
13845 "}"
13846 "result");
13847 CHECK_EQ(32640, result->Int32Value());
13848
13849 // Make sure that generic load ICs recognize out-of-bound accesses in
13850 // pixel arrays.
13851 result = CompileRun("function pa_load(p, start) {"
13852 " var sum = 0;"
13853 " for (var j = start; j < 256; j++) { sum += p[j]; }"
13854 " return sum;"
13855 "}"
13856 "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
13857 "just_ints = new Object();"
13858 "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
13859 "for (var i = 0; i < 10; ++i) { pa_load(just_ints,0); }"
13860 "for (var i = 0; i < 10; ++i) { pa_load(pixels,0); }"
13861 "for (var i = 0; i < 10; ++i) {"
13862 " result = pa_load(pixels,-10);"
13863 "}"
13864 "result");
13865 CHECK_EQ(0, result->Int32Value());
13866
13867 // Make sure that generic ICs properly handles other types than pixel
13868 // arrays (that the inlined fast pixel array test leaves the right information
13869 // in the right registers).
13870 result = CompileRun("function pa_load(p) {"
13871 " var sum = 0;"
13872 " for (var j = 0; j < 256; j++) { sum += p[j]; }"
13873 " return sum;"
13874 "}"
13875 "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
13876 "just_ints = new Object();"
13877 "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
13878 "for (var i = 0; i < 10; ++i) { pa_load(just_ints); }"
13879 "for (var i = 0; i < 10; ++i) { pa_load(pixels); }"
13880 "sparse_array = new Object();"
13881 "for (var i = 0; i < 256; ++i) { sparse_array[i] = i; }"
13882 "sparse_array[1000000] = 3;"
13883 "for (var i = 0; i < 10; ++i) {"
13884 " result = pa_load(sparse_array);"
13885 "}"
13886 "result");
13887 CHECK_EQ(32640, result->Int32Value());
13888
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +000013889 // Make sure that pixel array store ICs clamp values correctly.
13890 result = CompileRun("function pa_store(p) {"
13891 " for (var j = 0; j < 256; j++) { p[j] = j * 2; }"
13892 "}"
13893 "pa_store(pixels);"
13894 "var sum = 0;"
13895 "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
13896 "sum");
13897 CHECK_EQ(48896, result->Int32Value());
13898
13899 // Make sure that pixel array stores correctly handle accesses outside
13900 // of the pixel array..
13901 result = CompileRun("function pa_store(p,start) {"
13902 " for (var j = 0; j < 256; j++) {"
13903 " p[j+start] = j * 2;"
13904 " }"
13905 "}"
13906 "pa_store(pixels,0);"
13907 "pa_store(pixels,-128);"
13908 "var sum = 0;"
13909 "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
13910 "sum");
13911 CHECK_EQ(65280, result->Int32Value());
13912
13913 // Make sure that the generic store stub correctly handle accesses outside
13914 // of the pixel array..
13915 result = CompileRun("function pa_store(p,start) {"
13916 " for (var j = 0; j < 256; j++) {"
13917 " p[j+start] = j * 2;"
13918 " }"
13919 "}"
13920 "pa_store(pixels,0);"
13921 "just_ints = new Object();"
13922 "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
13923 "pa_store(just_ints, 0);"
13924 "pa_store(pixels,-128);"
13925 "var sum = 0;"
13926 "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
13927 "sum");
13928 CHECK_EQ(65280, result->Int32Value());
13929
13930 // Make sure that the generic keyed store stub clamps pixel array values
13931 // correctly.
13932 result = CompileRun("function pa_store(p) {"
13933 " for (var j = 0; j < 256; j++) { p[j] = j * 2; }"
13934 "}"
13935 "pa_store(pixels);"
13936 "just_ints = new Object();"
13937 "pa_store(just_ints);"
13938 "pa_store(pixels);"
13939 "var sum = 0;"
13940 "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
13941 "sum");
13942 CHECK_EQ(48896, result->Int32Value());
13943
13944 // Make sure that pixel array loads are optimized by crankshaft.
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000013945 result = CompileRun("function pa_load(p) {"
13946 " var sum = 0;"
13947 " for (var i=0; i<256; ++i) {"
13948 " sum += p[i];"
13949 " }"
13950 " return sum; "
13951 "}"
13952 "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000013953 "for (var i = 0; i < 5000; ++i) {"
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000013954 " result = pa_load(pixels);"
13955 "}"
13956 "result");
13957 CHECK_EQ(32640, result->Int32Value());
13958
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000013959 // Make sure that pixel array stores are optimized by crankshaft.
13960 result = CompileRun("function pa_init(p) {"
13961 "for (var i = 0; i < 256; ++i) { p[i] = i; }"
13962 "}"
13963 "function pa_load(p) {"
13964 " var sum = 0;"
13965 " for (var i=0; i<256; ++i) {"
13966 " sum += p[i];"
13967 " }"
13968 " return sum; "
13969 "}"
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000013970 "for (var i = 0; i < 5000; ++i) {"
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000013971 " pa_init(pixels);"
13972 "}"
13973 "result = pa_load(pixels);"
13974 "result");
13975 CHECK_EQ(32640, result->Int32Value());
13976
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000013977 free(pixel_data);
13978}
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000013979
ager@chromium.org96c75b52009-08-26 09:13:16 +000013980
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000013981THREADED_TEST(PixelArrayInfo) {
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000013982 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013983 v8::HandleScope scope(context->GetIsolate());
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000013984 for (int size = 0; size < 100; size += 10) {
13985 uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(size));
13986 v8::Handle<v8::Object> obj = v8::Object::New();
13987 obj->SetIndexedPropertiesToPixelData(pixel_data, size);
13988 CHECK(obj->HasIndexedPropertiesInPixelData());
13989 CHECK_EQ(pixel_data, obj->GetIndexedPropertiesPixelData());
13990 CHECK_EQ(size, obj->GetIndexedPropertiesPixelDataLength());
13991 free(pixel_data);
13992 }
13993}
13994
13995
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000013996static v8::Handle<Value> NotHandledIndexedPropertyGetter(
13997 uint32_t index,
13998 const AccessorInfo& info) {
13999 ApiTestFuzzer::Fuzz();
14000 return v8::Handle<Value>();
14001}
14002
14003
14004static v8::Handle<Value> NotHandledIndexedPropertySetter(
14005 uint32_t index,
14006 Local<Value> value,
14007 const AccessorInfo& info) {
14008 ApiTestFuzzer::Fuzz();
14009 return v8::Handle<Value>();
14010}
14011
14012
14013THREADED_TEST(PixelArrayWithInterceptor) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000014014 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000014015 v8::HandleScope scope(context->GetIsolate());
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000014016 const int kElementCount = 260;
14017 uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(kElementCount));
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000014018 i::Handle<i::ExternalPixelArray> pixels =
14019 i::Handle<i::ExternalPixelArray>::cast(
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000014020 FACTORY->NewExternalArray(kElementCount,
14021 v8::kExternalPixelArray,
14022 pixel_data));
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000014023 for (int i = 0; i < kElementCount; i++) {
14024 pixels->set(i, i % 256);
14025 }
14026 v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
14027 templ->SetIndexedPropertyHandler(NotHandledIndexedPropertyGetter,
14028 NotHandledIndexedPropertySetter);
14029 v8::Handle<v8::Object> obj = templ->NewInstance();
14030 obj->SetIndexedPropertiesToPixelData(pixel_data, kElementCount);
14031 context->Global()->Set(v8_str("pixels"), obj);
14032 v8::Handle<v8::Value> result = CompileRun("pixels[1]");
14033 CHECK_EQ(1, result->Int32Value());
14034 result = CompileRun("var sum = 0;"
14035 "for (var i = 0; i < 8; i++) {"
14036 " sum += pixels[i] = pixels[i] = -i;"
14037 "}"
14038 "sum;");
14039 CHECK_EQ(-28, result->Int32Value());
14040 result = CompileRun("pixels.hasOwnProperty('1')");
14041 CHECK(result->BooleanValue());
14042 free(pixel_data);
14043}
14044
14045
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000014046static int ExternalArrayElementSize(v8::ExternalArrayType array_type) {
14047 switch (array_type) {
14048 case v8::kExternalByteArray:
14049 case v8::kExternalUnsignedByteArray:
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000014050 case v8::kExternalPixelArray:
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000014051 return 1;
14052 break;
14053 case v8::kExternalShortArray:
14054 case v8::kExternalUnsignedShortArray:
14055 return 2;
14056 break;
14057 case v8::kExternalIntArray:
14058 case v8::kExternalUnsignedIntArray:
14059 case v8::kExternalFloatArray:
14060 return 4;
14061 break;
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +000014062 case v8::kExternalDoubleArray:
14063 return 8;
14064 break;
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000014065 default:
14066 UNREACHABLE();
14067 return -1;
14068 }
14069 UNREACHABLE();
14070 return -1;
14071}
14072
14073
ager@chromium.org3811b432009-10-28 14:53:37 +000014074template <class ExternalArrayClass, class ElementType>
14075static void ExternalArrayTestHelper(v8::ExternalArrayType array_type,
14076 int64_t low,
14077 int64_t high) {
ager@chromium.org3811b432009-10-28 14:53:37 +000014078 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000014079 v8::HandleScope scope(context->GetIsolate());
ager@chromium.org3811b432009-10-28 14:53:37 +000014080 const int kElementCount = 40;
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000014081 int element_size = ExternalArrayElementSize(array_type);
ager@chromium.org3811b432009-10-28 14:53:37 +000014082 ElementType* array_data =
14083 static_cast<ElementType*>(malloc(kElementCount * element_size));
14084 i::Handle<ExternalArrayClass> array =
14085 i::Handle<ExternalArrayClass>::cast(
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000014086 FACTORY->NewExternalArray(kElementCount, array_type, array_data));
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000014087 // Force GC to trigger verification.
14088 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org3811b432009-10-28 14:53:37 +000014089 for (int i = 0; i < kElementCount; i++) {
14090 array->set(i, static_cast<ElementType>(i));
14091 }
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000014092 // Force GC to trigger verification.
14093 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org3811b432009-10-28 14:53:37 +000014094 for (int i = 0; i < kElementCount; i++) {
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +000014095 CHECK_EQ(static_cast<int64_t>(i),
14096 static_cast<int64_t>(array->get_scalar(i)));
ager@chromium.org3811b432009-10-28 14:53:37 +000014097 CHECK_EQ(static_cast<int64_t>(i), static_cast<int64_t>(array_data[i]));
14098 }
14099
14100 v8::Handle<v8::Object> obj = v8::Object::New();
14101 i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
14102 // Set the elements to be the external array.
14103 obj->SetIndexedPropertiesToExternalArrayData(array_data,
14104 array_type,
14105 kElementCount);
lrn@chromium.org303ada72010-10-27 09:33:13 +000014106 CHECK_EQ(
14107 1, static_cast<int>(jsobj->GetElement(1)->ToObjectChecked()->Number()));
ager@chromium.org3811b432009-10-28 14:53:37 +000014108 obj->Set(v8_str("field"), v8::Int32::New(1503));
14109 context->Global()->Set(v8_str("ext_array"), obj);
14110 v8::Handle<v8::Value> result = CompileRun("ext_array.field");
14111 CHECK_EQ(1503, result->Int32Value());
14112 result = CompileRun("ext_array[1]");
14113 CHECK_EQ(1, result->Int32Value());
14114
14115 // Check pass through of assigned smis
14116 result = CompileRun("var sum = 0;"
14117 "for (var i = 0; i < 8; i++) {"
14118 " sum += ext_array[i] = ext_array[i] = -i;"
14119 "}"
14120 "sum;");
14121 CHECK_EQ(-28, result->Int32Value());
14122
14123 // Check assigned smis
14124 result = CompileRun("for (var i = 0; i < 8; i++) {"
14125 " ext_array[i] = i;"
14126 "}"
14127 "var sum = 0;"
14128 "for (var i = 0; i < 8; i++) {"
14129 " sum += ext_array[i];"
14130 "}"
14131 "sum;");
14132 CHECK_EQ(28, result->Int32Value());
14133
14134 // Check assigned smis in reverse order
14135 result = CompileRun("for (var i = 8; --i >= 0; ) {"
14136 " ext_array[i] = i;"
14137 "}"
14138 "var sum = 0;"
14139 "for (var i = 0; i < 8; i++) {"
14140 " sum += ext_array[i];"
14141 "}"
14142 "sum;");
14143 CHECK_EQ(28, result->Int32Value());
14144
14145 // Check pass through of assigned HeapNumbers
14146 result = CompileRun("var sum = 0;"
14147 "for (var i = 0; i < 16; i+=2) {"
14148 " sum += ext_array[i] = ext_array[i] = (-i * 0.5);"
14149 "}"
14150 "sum;");
14151 CHECK_EQ(-28, result->Int32Value());
14152
14153 // Check assigned HeapNumbers
14154 result = CompileRun("for (var i = 0; i < 16; i+=2) {"
14155 " ext_array[i] = (i * 0.5);"
14156 "}"
14157 "var sum = 0;"
14158 "for (var i = 0; i < 16; i+=2) {"
14159 " sum += ext_array[i];"
14160 "}"
14161 "sum;");
14162 CHECK_EQ(28, result->Int32Value());
14163
14164 // Check assigned HeapNumbers in reverse order
14165 result = CompileRun("for (var i = 14; i >= 0; i-=2) {"
14166 " ext_array[i] = (i * 0.5);"
14167 "}"
14168 "var sum = 0;"
14169 "for (var i = 0; i < 16; i+=2) {"
14170 " sum += ext_array[i];"
14171 "}"
14172 "sum;");
14173 CHECK_EQ(28, result->Int32Value());
14174
14175 i::ScopedVector<char> test_buf(1024);
14176
14177 // Check legal boundary conditions.
14178 // The repeated loads and stores ensure the ICs are exercised.
14179 const char* boundary_program =
14180 "var res = 0;"
14181 "for (var i = 0; i < 16; i++) {"
14182 " ext_array[i] = %lld;"
14183 " if (i > 8) {"
14184 " res = ext_array[i];"
14185 " }"
14186 "}"
14187 "res;";
14188 i::OS::SNPrintF(test_buf,
14189 boundary_program,
14190 low);
14191 result = CompileRun(test_buf.start());
14192 CHECK_EQ(low, result->IntegerValue());
14193
14194 i::OS::SNPrintF(test_buf,
14195 boundary_program,
14196 high);
14197 result = CompileRun(test_buf.start());
14198 CHECK_EQ(high, result->IntegerValue());
14199
14200 // Check misprediction of type in IC.
14201 result = CompileRun("var tmp_array = ext_array;"
14202 "var sum = 0;"
14203 "for (var i = 0; i < 8; i++) {"
14204 " tmp_array[i] = i;"
14205 " sum += tmp_array[i];"
14206 " if (i == 4) {"
14207 " tmp_array = {};"
14208 " }"
14209 "}"
14210 "sum;");
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000014211 // Force GC to trigger verification.
14212 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org3811b432009-10-28 14:53:37 +000014213 CHECK_EQ(28, result->Int32Value());
14214
14215 // Make sure out-of-range loads do not throw.
14216 i::OS::SNPrintF(test_buf,
14217 "var caught_exception = false;"
14218 "try {"
14219 " ext_array[%d];"
14220 "} catch (e) {"
14221 " caught_exception = true;"
14222 "}"
14223 "caught_exception;",
14224 kElementCount);
14225 result = CompileRun(test_buf.start());
14226 CHECK_EQ(false, result->BooleanValue());
14227
14228 // Make sure out-of-range stores do not throw.
14229 i::OS::SNPrintF(test_buf,
14230 "var caught_exception = false;"
14231 "try {"
14232 " ext_array[%d] = 1;"
14233 "} catch (e) {"
14234 " caught_exception = true;"
14235 "}"
14236 "caught_exception;",
14237 kElementCount);
14238 result = CompileRun(test_buf.start());
14239 CHECK_EQ(false, result->BooleanValue());
14240
14241 // Check other boundary conditions, values and operations.
14242 result = CompileRun("for (var i = 0; i < 8; i++) {"
14243 " ext_array[7] = undefined;"
14244 "}"
14245 "ext_array[7];");
14246 CHECK_EQ(0, result->Int32Value());
yangguo@chromium.org56454712012-02-16 15:33:53 +000014247 if (array_type == v8::kExternalDoubleArray ||
14248 array_type == v8::kExternalFloatArray) {
14249 CHECK_EQ(
ulan@chromium.org812308e2012-02-29 15:58:45 +000014250 static_cast<int>(i::OS::nan_value()),
yangguo@chromium.org56454712012-02-16 15:33:53 +000014251 static_cast<int>(jsobj->GetElement(7)->ToObjectChecked()->Number()));
14252 } else {
14253 CHECK_EQ(0, static_cast<int>(
14254 jsobj->GetElement(7)->ToObjectChecked()->Number()));
14255 }
ager@chromium.org3811b432009-10-28 14:53:37 +000014256
14257 result = CompileRun("for (var i = 0; i < 8; i++) {"
14258 " ext_array[6] = '2.3';"
14259 "}"
14260 "ext_array[6];");
14261 CHECK_EQ(2, result->Int32Value());
lrn@chromium.org303ada72010-10-27 09:33:13 +000014262 CHECK_EQ(
14263 2, static_cast<int>(jsobj->GetElement(6)->ToObjectChecked()->Number()));
ager@chromium.org3811b432009-10-28 14:53:37 +000014264
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +000014265 if (array_type != v8::kExternalFloatArray &&
14266 array_type != v8::kExternalDoubleArray) {
ager@chromium.org3811b432009-10-28 14:53:37 +000014267 // Though the specification doesn't state it, be explicit about
14268 // converting NaNs and +/-Infinity to zero.
14269 result = CompileRun("for (var i = 0; i < 8; i++) {"
14270 " ext_array[i] = 5;"
14271 "}"
14272 "for (var i = 0; i < 8; i++) {"
14273 " ext_array[i] = NaN;"
14274 "}"
14275 "ext_array[5];");
14276 CHECK_EQ(0, result->Int32Value());
lrn@chromium.org303ada72010-10-27 09:33:13 +000014277 CHECK_EQ(0,
14278 i::Smi::cast(jsobj->GetElement(5)->ToObjectChecked())->value());
ager@chromium.org3811b432009-10-28 14:53:37 +000014279
14280 result = CompileRun("for (var i = 0; i < 8; i++) {"
14281 " ext_array[i] = 5;"
14282 "}"
14283 "for (var i = 0; i < 8; i++) {"
14284 " ext_array[i] = Infinity;"
14285 "}"
14286 "ext_array[5];");
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000014287 int expected_value =
14288 (array_type == v8::kExternalPixelArray) ? 255 : 0;
14289 CHECK_EQ(expected_value, result->Int32Value());
14290 CHECK_EQ(expected_value,
lrn@chromium.org303ada72010-10-27 09:33:13 +000014291 i::Smi::cast(jsobj->GetElement(5)->ToObjectChecked())->value());
ager@chromium.org3811b432009-10-28 14:53:37 +000014292
14293 result = CompileRun("for (var i = 0; i < 8; i++) {"
14294 " ext_array[i] = 5;"
14295 "}"
14296 "for (var i = 0; i < 8; i++) {"
14297 " ext_array[i] = -Infinity;"
14298 "}"
14299 "ext_array[5];");
14300 CHECK_EQ(0, result->Int32Value());
lrn@chromium.org303ada72010-10-27 09:33:13 +000014301 CHECK_EQ(0,
14302 i::Smi::cast(jsobj->GetElement(5)->ToObjectChecked())->value());
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +000014303
14304 // Check truncation behavior of integral arrays.
14305 const char* unsigned_data =
14306 "var source_data = [0.6, 10.6];"
14307 "var expected_results = [0, 10];";
14308 const char* signed_data =
14309 "var source_data = [0.6, 10.6, -0.6, -10.6];"
14310 "var expected_results = [0, 10, 0, -10];";
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000014311 const char* pixel_data =
14312 "var source_data = [0.6, 10.6];"
14313 "var expected_results = [1, 11];";
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +000014314 bool is_unsigned =
14315 (array_type == v8::kExternalUnsignedByteArray ||
14316 array_type == v8::kExternalUnsignedShortArray ||
14317 array_type == v8::kExternalUnsignedIntArray);
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000014318 bool is_pixel_data = array_type == v8::kExternalPixelArray;
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +000014319
14320 i::OS::SNPrintF(test_buf,
14321 "%s"
14322 "var all_passed = true;"
14323 "for (var i = 0; i < source_data.length; i++) {"
14324 " for (var j = 0; j < 8; j++) {"
14325 " ext_array[j] = source_data[i];"
14326 " }"
14327 " all_passed = all_passed &&"
14328 " (ext_array[5] == expected_results[i]);"
14329 "}"
14330 "all_passed;",
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000014331 (is_unsigned ?
14332 unsigned_data :
14333 (is_pixel_data ? pixel_data : signed_data)));
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +000014334 result = CompileRun(test_buf.start());
14335 CHECK_EQ(true, result->BooleanValue());
ager@chromium.org3811b432009-10-28 14:53:37 +000014336 }
14337
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000014338 for (int i = 0; i < kElementCount; i++) {
14339 array->set(i, static_cast<ElementType>(i));
14340 }
14341 // Test complex assignments
14342 result = CompileRun("function ee_op_test_complex_func(sum) {"
14343 " for (var i = 0; i < 40; ++i) {"
14344 " sum += (ext_array[i] += 1);"
14345 " sum += (ext_array[i] -= 1);"
14346 " } "
14347 " return sum;"
14348 "}"
14349 "sum=0;"
14350 "for (var i=0;i<10000;++i) {"
14351 " sum=ee_op_test_complex_func(sum);"
14352 "}"
14353 "sum;");
14354 CHECK_EQ(16000000, result->Int32Value());
14355
14356 // Test count operations
14357 result = CompileRun("function ee_op_test_count_func(sum) {"
14358 " for (var i = 0; i < 40; ++i) {"
14359 " sum += (++ext_array[i]);"
14360 " sum += (--ext_array[i]);"
14361 " } "
14362 " return sum;"
14363 "}"
14364 "sum=0;"
14365 "for (var i=0;i<10000;++i) {"
14366 " sum=ee_op_test_count_func(sum);"
14367 "}"
14368 "sum;");
14369 CHECK_EQ(16000000, result->Int32Value());
14370
ager@chromium.org3811b432009-10-28 14:53:37 +000014371 result = CompileRun("ext_array[3] = 33;"
14372 "delete ext_array[3];"
14373 "ext_array[3];");
14374 CHECK_EQ(33, result->Int32Value());
14375
14376 result = CompileRun("ext_array[0] = 10; ext_array[1] = 11;"
14377 "ext_array[2] = 12; ext_array[3] = 13;"
14378 "ext_array.__defineGetter__('2',"
14379 "function() { return 120; });"
14380 "ext_array[2];");
14381 CHECK_EQ(12, result->Int32Value());
14382
14383 result = CompileRun("var js_array = new Array(40);"
14384 "js_array[0] = 77;"
14385 "js_array;");
14386 CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
14387
14388 result = CompileRun("ext_array[1] = 23;"
14389 "ext_array.__proto__ = [];"
14390 "js_array.__proto__ = ext_array;"
14391 "js_array.concat(ext_array);");
14392 CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
14393 CHECK_EQ(23, v8::Object::Cast(*result)->Get(v8_str("1"))->Int32Value());
14394
14395 result = CompileRun("ext_array[1] = 23;");
14396 CHECK_EQ(23, result->Int32Value());
14397
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +000014398 // Test more complex manipulations which cause eax to contain values
14399 // that won't be completely overwritten by loads from the arrays.
14400 // This catches bugs in the instructions used for the KeyedLoadIC
14401 // for byte and word types.
14402 {
14403 const int kXSize = 300;
14404 const int kYSize = 300;
14405 const int kLargeElementCount = kXSize * kYSize * 4;
14406 ElementType* large_array_data =
14407 static_cast<ElementType*>(malloc(kLargeElementCount * element_size));
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +000014408 v8::Handle<v8::Object> large_obj = v8::Object::New();
14409 // Set the elements to be the external array.
14410 large_obj->SetIndexedPropertiesToExternalArrayData(large_array_data,
14411 array_type,
14412 kLargeElementCount);
14413 context->Global()->Set(v8_str("large_array"), large_obj);
14414 // Initialize contents of a few rows.
14415 for (int x = 0; x < 300; x++) {
14416 int row = 0;
14417 int offset = row * 300 * 4;
14418 large_array_data[offset + 4 * x + 0] = (ElementType) 127;
14419 large_array_data[offset + 4 * x + 1] = (ElementType) 0;
14420 large_array_data[offset + 4 * x + 2] = (ElementType) 0;
14421 large_array_data[offset + 4 * x + 3] = (ElementType) 127;
14422 row = 150;
14423 offset = row * 300 * 4;
14424 large_array_data[offset + 4 * x + 0] = (ElementType) 127;
14425 large_array_data[offset + 4 * x + 1] = (ElementType) 0;
14426 large_array_data[offset + 4 * x + 2] = (ElementType) 0;
14427 large_array_data[offset + 4 * x + 3] = (ElementType) 127;
14428 row = 298;
14429 offset = row * 300 * 4;
14430 large_array_data[offset + 4 * x + 0] = (ElementType) 127;
14431 large_array_data[offset + 4 * x + 1] = (ElementType) 0;
14432 large_array_data[offset + 4 * x + 2] = (ElementType) 0;
14433 large_array_data[offset + 4 * x + 3] = (ElementType) 127;
14434 }
14435 // The goal of the code below is to make "offset" large enough
14436 // that the computation of the index (which goes into eax) has
14437 // high bits set which will not be overwritten by a byte or short
14438 // load.
14439 result = CompileRun("var failed = false;"
14440 "var offset = 0;"
14441 "for (var i = 0; i < 300; i++) {"
14442 " if (large_array[4 * i] != 127 ||"
14443 " large_array[4 * i + 1] != 0 ||"
14444 " large_array[4 * i + 2] != 0 ||"
14445 " large_array[4 * i + 3] != 127) {"
14446 " failed = true;"
14447 " }"
14448 "}"
14449 "offset = 150 * 300 * 4;"
14450 "for (var i = 0; i < 300; i++) {"
14451 " if (large_array[offset + 4 * i] != 127 ||"
14452 " large_array[offset + 4 * i + 1] != 0 ||"
14453 " large_array[offset + 4 * i + 2] != 0 ||"
14454 " large_array[offset + 4 * i + 3] != 127) {"
14455 " failed = true;"
14456 " }"
14457 "}"
14458 "offset = 298 * 300 * 4;"
14459 "for (var i = 0; i < 300; i++) {"
14460 " if (large_array[offset + 4 * i] != 127 ||"
14461 " large_array[offset + 4 * i + 1] != 0 ||"
14462 " large_array[offset + 4 * i + 2] != 0 ||"
14463 " large_array[offset + 4 * i + 3] != 127) {"
14464 " failed = true;"
14465 " }"
14466 "}"
14467 "!failed;");
14468 CHECK_EQ(true, result->BooleanValue());
14469 free(large_array_data);
14470 }
14471
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000014472 // The "" property descriptor is overloaded to store information about
14473 // the external array. Ensure that setting and accessing the "" property
14474 // works (it should overwrite the information cached about the external
14475 // array in the DescriptorArray) in various situations.
14476 result = CompileRun("ext_array[''] = 23; ext_array['']");
14477 CHECK_EQ(23, result->Int32Value());
14478
14479 // Property "" set after the external array is associated with the object.
14480 {
14481 v8::Handle<v8::Object> obj2 = v8::Object::New();
14482 obj2->Set(v8_str("ee_test_field"), v8::Int32::New(256));
14483 obj2->Set(v8_str(""), v8::Int32::New(1503));
14484 // Set the elements to be the external array.
14485 obj2->SetIndexedPropertiesToExternalArrayData(array_data,
14486 array_type,
14487 kElementCount);
14488 context->Global()->Set(v8_str("ext_array"), obj2);
14489 result = CompileRun("ext_array['']");
14490 CHECK_EQ(1503, result->Int32Value());
14491 }
14492
14493 // Property "" set after the external array is associated with the object.
14494 {
14495 v8::Handle<v8::Object> obj2 = v8::Object::New();
14496 obj2->Set(v8_str("ee_test_field_2"), v8::Int32::New(256));
14497 // Set the elements to be the external array.
14498 obj2->SetIndexedPropertiesToExternalArrayData(array_data,
14499 array_type,
14500 kElementCount);
14501 obj2->Set(v8_str(""), v8::Int32::New(1503));
14502 context->Global()->Set(v8_str("ext_array"), obj2);
14503 result = CompileRun("ext_array['']");
14504 CHECK_EQ(1503, result->Int32Value());
14505 }
14506
14507 // Should reuse the map from previous test.
14508 {
14509 v8::Handle<v8::Object> obj2 = v8::Object::New();
14510 obj2->Set(v8_str("ee_test_field_2"), v8::Int32::New(256));
14511 // Set the elements to be the external array. Should re-use the map
14512 // from previous test.
14513 obj2->SetIndexedPropertiesToExternalArrayData(array_data,
14514 array_type,
14515 kElementCount);
14516 context->Global()->Set(v8_str("ext_array"), obj2);
14517 result = CompileRun("ext_array['']");
14518 }
14519
14520 // Property "" is a constant function that shouldn't not be interfered with
14521 // when an external array is set.
14522 {
14523 v8::Handle<v8::Object> obj2 = v8::Object::New();
14524 // Start
14525 obj2->Set(v8_str("ee_test_field3"), v8::Int32::New(256));
14526
14527 // Add a constant function to an object.
14528 context->Global()->Set(v8_str("ext_array"), obj2);
14529 result = CompileRun("ext_array[''] = function() {return 1503;};"
14530 "ext_array['']();");
14531
14532 // Add an external array transition to the same map that
14533 // has the constant transition.
14534 v8::Handle<v8::Object> obj3 = v8::Object::New();
14535 obj3->Set(v8_str("ee_test_field3"), v8::Int32::New(256));
14536 obj3->SetIndexedPropertiesToExternalArrayData(array_data,
14537 array_type,
14538 kElementCount);
14539 context->Global()->Set(v8_str("ext_array"), obj3);
14540 }
14541
14542 // If a external array transition is in the map, it should get clobbered
14543 // by a constant function.
14544 {
14545 // Add an external array transition.
14546 v8::Handle<v8::Object> obj3 = v8::Object::New();
14547 obj3->Set(v8_str("ee_test_field4"), v8::Int32::New(256));
14548 obj3->SetIndexedPropertiesToExternalArrayData(array_data,
14549 array_type,
14550 kElementCount);
14551
14552 // Add a constant function to the same map that just got an external array
14553 // transition.
14554 v8::Handle<v8::Object> obj2 = v8::Object::New();
14555 obj2->Set(v8_str("ee_test_field4"), v8::Int32::New(256));
14556 context->Global()->Set(v8_str("ext_array"), obj2);
14557 result = CompileRun("ext_array[''] = function() {return 1503;};"
14558 "ext_array['']();");
14559 }
14560
ager@chromium.org3811b432009-10-28 14:53:37 +000014561 free(array_data);
14562}
14563
14564
14565THREADED_TEST(ExternalByteArray) {
lrn@chromium.org32d961d2010-06-30 09:09:34 +000014566 ExternalArrayTestHelper<i::ExternalByteArray, int8_t>(
ager@chromium.org3811b432009-10-28 14:53:37 +000014567 v8::kExternalByteArray,
14568 -128,
14569 127);
14570}
14571
14572
14573THREADED_TEST(ExternalUnsignedByteArray) {
lrn@chromium.org32d961d2010-06-30 09:09:34 +000014574 ExternalArrayTestHelper<i::ExternalUnsignedByteArray, uint8_t>(
ager@chromium.org3811b432009-10-28 14:53:37 +000014575 v8::kExternalUnsignedByteArray,
14576 0,
14577 255);
14578}
14579
14580
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000014581THREADED_TEST(ExternalPixelArray) {
14582 ExternalArrayTestHelper<i::ExternalPixelArray, uint8_t>(
14583 v8::kExternalPixelArray,
14584 0,
14585 255);
14586}
14587
14588
ager@chromium.org3811b432009-10-28 14:53:37 +000014589THREADED_TEST(ExternalShortArray) {
lrn@chromium.org32d961d2010-06-30 09:09:34 +000014590 ExternalArrayTestHelper<i::ExternalShortArray, int16_t>(
ager@chromium.org3811b432009-10-28 14:53:37 +000014591 v8::kExternalShortArray,
14592 -32768,
14593 32767);
14594}
14595
14596
14597THREADED_TEST(ExternalUnsignedShortArray) {
lrn@chromium.org32d961d2010-06-30 09:09:34 +000014598 ExternalArrayTestHelper<i::ExternalUnsignedShortArray, uint16_t>(
ager@chromium.org3811b432009-10-28 14:53:37 +000014599 v8::kExternalUnsignedShortArray,
14600 0,
14601 65535);
14602}
14603
14604
14605THREADED_TEST(ExternalIntArray) {
lrn@chromium.org32d961d2010-06-30 09:09:34 +000014606 ExternalArrayTestHelper<i::ExternalIntArray, int32_t>(
ager@chromium.org3811b432009-10-28 14:53:37 +000014607 v8::kExternalIntArray,
14608 INT_MIN, // -2147483648
14609 INT_MAX); // 2147483647
14610}
14611
14612
14613THREADED_TEST(ExternalUnsignedIntArray) {
lrn@chromium.org32d961d2010-06-30 09:09:34 +000014614 ExternalArrayTestHelper<i::ExternalUnsignedIntArray, uint32_t>(
ager@chromium.org3811b432009-10-28 14:53:37 +000014615 v8::kExternalUnsignedIntArray,
14616 0,
14617 UINT_MAX); // 4294967295
14618}
14619
14620
14621THREADED_TEST(ExternalFloatArray) {
lrn@chromium.org32d961d2010-06-30 09:09:34 +000014622 ExternalArrayTestHelper<i::ExternalFloatArray, float>(
ager@chromium.org3811b432009-10-28 14:53:37 +000014623 v8::kExternalFloatArray,
14624 -500,
14625 500);
14626}
14627
14628
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +000014629THREADED_TEST(ExternalDoubleArray) {
14630 ExternalArrayTestHelper<i::ExternalDoubleArray, double>(
14631 v8::kExternalDoubleArray,
14632 -500,
14633 500);
14634}
14635
14636
ager@chromium.org3811b432009-10-28 14:53:37 +000014637THREADED_TEST(ExternalArrays) {
14638 TestExternalByteArray();
14639 TestExternalUnsignedByteArray();
14640 TestExternalShortArray();
14641 TestExternalUnsignedShortArray();
14642 TestExternalIntArray();
14643 TestExternalUnsignedIntArray();
14644 TestExternalFloatArray();
14645}
14646
14647
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000014648void ExternalArrayInfoTestHelper(v8::ExternalArrayType array_type) {
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000014649 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000014650 v8::HandleScope scope(context->GetIsolate());
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000014651 for (int size = 0; size < 100; size += 10) {
14652 int element_size = ExternalArrayElementSize(array_type);
14653 void* external_data = malloc(size * element_size);
14654 v8::Handle<v8::Object> obj = v8::Object::New();
14655 obj->SetIndexedPropertiesToExternalArrayData(
14656 external_data, array_type, size);
14657 CHECK(obj->HasIndexedPropertiesInExternalArrayData());
14658 CHECK_EQ(external_data, obj->GetIndexedPropertiesExternalArrayData());
14659 CHECK_EQ(array_type, obj->GetIndexedPropertiesExternalArrayDataType());
14660 CHECK_EQ(size, obj->GetIndexedPropertiesExternalArrayDataLength());
14661 free(external_data);
14662 }
14663}
14664
14665
14666THREADED_TEST(ExternalArrayInfo) {
14667 ExternalArrayInfoTestHelper(v8::kExternalByteArray);
14668 ExternalArrayInfoTestHelper(v8::kExternalUnsignedByteArray);
14669 ExternalArrayInfoTestHelper(v8::kExternalShortArray);
14670 ExternalArrayInfoTestHelper(v8::kExternalUnsignedShortArray);
14671 ExternalArrayInfoTestHelper(v8::kExternalIntArray);
14672 ExternalArrayInfoTestHelper(v8::kExternalUnsignedIntArray);
14673 ExternalArrayInfoTestHelper(v8::kExternalFloatArray);
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +000014674 ExternalArrayInfoTestHelper(v8::kExternalDoubleArray);
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000014675 ExternalArrayInfoTestHelper(v8::kExternalPixelArray);
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000014676}
14677
14678
danno@chromium.org412fa512012-09-14 13:28:26 +000014679void ExternalArrayLimitTestHelper(v8::ExternalArrayType array_type, int size) {
14680 v8::Handle<v8::Object> obj = v8::Object::New();
14681 v8::V8::SetFatalErrorHandler(StoringErrorCallback);
14682 last_location = last_message = NULL;
14683 obj->SetIndexedPropertiesToExternalArrayData(NULL, array_type, size);
14684 CHECK(!obj->HasIndexedPropertiesInExternalArrayData());
14685 CHECK_NE(NULL, last_location);
14686 CHECK_NE(NULL, last_message);
14687}
14688
14689
14690TEST(ExternalArrayLimits) {
danno@chromium.org412fa512012-09-14 13:28:26 +000014691 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000014692 v8::HandleScope scope(context->GetIsolate());
danno@chromium.org412fa512012-09-14 13:28:26 +000014693 ExternalArrayLimitTestHelper(v8::kExternalByteArray, 0x40000000);
14694 ExternalArrayLimitTestHelper(v8::kExternalByteArray, 0xffffffff);
14695 ExternalArrayLimitTestHelper(v8::kExternalUnsignedByteArray, 0x40000000);
14696 ExternalArrayLimitTestHelper(v8::kExternalUnsignedByteArray, 0xffffffff);
14697 ExternalArrayLimitTestHelper(v8::kExternalShortArray, 0x40000000);
14698 ExternalArrayLimitTestHelper(v8::kExternalShortArray, 0xffffffff);
14699 ExternalArrayLimitTestHelper(v8::kExternalUnsignedShortArray, 0x40000000);
14700 ExternalArrayLimitTestHelper(v8::kExternalUnsignedShortArray, 0xffffffff);
14701 ExternalArrayLimitTestHelper(v8::kExternalIntArray, 0x40000000);
14702 ExternalArrayLimitTestHelper(v8::kExternalIntArray, 0xffffffff);
14703 ExternalArrayLimitTestHelper(v8::kExternalUnsignedIntArray, 0x40000000);
14704 ExternalArrayLimitTestHelper(v8::kExternalUnsignedIntArray, 0xffffffff);
14705 ExternalArrayLimitTestHelper(v8::kExternalFloatArray, 0x40000000);
14706 ExternalArrayLimitTestHelper(v8::kExternalFloatArray, 0xffffffff);
14707 ExternalArrayLimitTestHelper(v8::kExternalDoubleArray, 0x40000000);
14708 ExternalArrayLimitTestHelper(v8::kExternalDoubleArray, 0xffffffff);
14709 ExternalArrayLimitTestHelper(v8::kExternalPixelArray, 0x40000000);
14710 ExternalArrayLimitTestHelper(v8::kExternalPixelArray, 0xffffffff);
14711}
14712
14713
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000014714THREADED_TEST(ScriptContextDependence) {
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000014715 LocalContext c1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000014716 v8::HandleScope scope(c1->GetIsolate());
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000014717 const char *source = "foo";
14718 v8::Handle<v8::Script> dep = v8::Script::Compile(v8::String::New(source));
14719 v8::Handle<v8::Script> indep = v8::Script::New(v8::String::New(source));
14720 c1->Global()->Set(v8::String::New("foo"), v8::Integer::New(100));
14721 CHECK_EQ(dep->Run()->Int32Value(), 100);
14722 CHECK_EQ(indep->Run()->Int32Value(), 100);
14723 LocalContext c2;
14724 c2->Global()->Set(v8::String::New("foo"), v8::Integer::New(101));
14725 CHECK_EQ(dep->Run()->Int32Value(), 100);
14726 CHECK_EQ(indep->Run()->Int32Value(), 101);
14727}
14728
ager@chromium.org96c75b52009-08-26 09:13:16 +000014729
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000014730THREADED_TEST(StackTrace) {
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000014731 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000014732 v8::HandleScope scope(context->GetIsolate());
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000014733 v8::TryCatch try_catch;
14734 const char *source = "function foo() { FAIL.FAIL; }; foo();";
14735 v8::Handle<v8::String> src = v8::String::New(source);
14736 v8::Handle<v8::String> origin = v8::String::New("stack-trace-test");
14737 v8::Script::New(src, origin)->Run();
14738 CHECK(try_catch.HasCaught());
14739 v8::String::Utf8Value stack(try_catch.StackTrace());
14740 CHECK(strstr(*stack, "at foo (stack-trace-test") != NULL);
14741}
ager@chromium.org96c75b52009-08-26 09:13:16 +000014742
14743
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000014744// Checks that a StackFrame has certain expected values.
14745void checkStackFrame(const char* expected_script_name,
14746 const char* expected_func_name, int expected_line_number,
14747 int expected_column, bool is_eval, bool is_constructor,
14748 v8::Handle<v8::StackFrame> frame) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000014749 v8::HandleScope scope(v8::Isolate::GetCurrent());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000014750 v8::String::Utf8Value func_name(frame->GetFunctionName());
14751 v8::String::Utf8Value script_name(frame->GetScriptName());
14752 if (*script_name == NULL) {
14753 // The situation where there is no associated script, like for evals.
14754 CHECK(expected_script_name == NULL);
14755 } else {
14756 CHECK(strstr(*script_name, expected_script_name) != NULL);
14757 }
14758 CHECK(strstr(*func_name, expected_func_name) != NULL);
14759 CHECK_EQ(expected_line_number, frame->GetLineNumber());
14760 CHECK_EQ(expected_column, frame->GetColumn());
14761 CHECK_EQ(is_eval, frame->IsEval());
14762 CHECK_EQ(is_constructor, frame->IsConstructor());
14763}
14764
14765
14766v8::Handle<Value> AnalyzeStackInNativeCode(const v8::Arguments& args) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000014767 v8::HandleScope scope(args.GetIsolate());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000014768 const char* origin = "capture-stack-trace-test";
14769 const int kOverviewTest = 1;
14770 const int kDetailedTest = 2;
14771
14772 ASSERT(args.Length() == 1);
14773
14774 int testGroup = args[0]->Int32Value();
14775 if (testGroup == kOverviewTest) {
14776 v8::Handle<v8::StackTrace> stackTrace =
14777 v8::StackTrace::CurrentStackTrace(10, v8::StackTrace::kOverview);
14778 CHECK_EQ(4, stackTrace->GetFrameCount());
14779 checkStackFrame(origin, "bar", 2, 10, false, false,
14780 stackTrace->GetFrame(0));
14781 checkStackFrame(origin, "foo", 6, 3, false, false,
14782 stackTrace->GetFrame(1));
whesse@chromium.org030d38e2011-07-13 13:23:34 +000014783 // This is the source string inside the eval which has the call to foo.
14784 checkStackFrame(NULL, "", 1, 5, false, false,
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000014785 stackTrace->GetFrame(2));
whesse@chromium.org030d38e2011-07-13 13:23:34 +000014786 // The last frame is an anonymous function which has the initial eval call.
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000014787 checkStackFrame(origin, "", 8, 7, false, false,
14788 stackTrace->GetFrame(3));
14789
14790 CHECK(stackTrace->AsArray()->IsArray());
14791 } else if (testGroup == kDetailedTest) {
14792 v8::Handle<v8::StackTrace> stackTrace =
14793 v8::StackTrace::CurrentStackTrace(10, v8::StackTrace::kDetailed);
14794 CHECK_EQ(4, stackTrace->GetFrameCount());
14795 checkStackFrame(origin, "bat", 4, 22, false, false,
14796 stackTrace->GetFrame(0));
14797 checkStackFrame(origin, "baz", 8, 3, false, true,
14798 stackTrace->GetFrame(1));
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +000014799#ifdef ENABLE_DEBUGGER_SUPPORT
14800 bool is_eval = true;
14801#else // ENABLE_DEBUGGER_SUPPORT
14802 bool is_eval = false;
14803#endif // ENABLE_DEBUGGER_SUPPORT
14804
whesse@chromium.org030d38e2011-07-13 13:23:34 +000014805 // This is the source string inside the eval which has the call to baz.
14806 checkStackFrame(NULL, "", 1, 5, is_eval, false,
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000014807 stackTrace->GetFrame(2));
whesse@chromium.org030d38e2011-07-13 13:23:34 +000014808 // The last frame is an anonymous function which has the initial eval call.
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000014809 checkStackFrame(origin, "", 10, 1, false, false,
14810 stackTrace->GetFrame(3));
14811
14812 CHECK(stackTrace->AsArray()->IsArray());
14813 }
14814 return v8::Undefined();
14815}
14816
14817
14818// Tests the C++ StackTrace API.
kasperl@chromium.orga5551262010-12-07 12:49:48 +000014819// TODO(3074796): Reenable this as a THREADED_TEST once it passes.
14820// THREADED_TEST(CaptureStackTrace) {
14821TEST(CaptureStackTrace) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000014822 v8::HandleScope scope(v8::Isolate::GetCurrent());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000014823 v8::Handle<v8::String> origin = v8::String::New("capture-stack-trace-test");
14824 Local<ObjectTemplate> templ = ObjectTemplate::New();
14825 templ->Set(v8_str("AnalyzeStackInNativeCode"),
14826 v8::FunctionTemplate::New(AnalyzeStackInNativeCode));
14827 LocalContext context(0, templ);
14828
14829 // Test getting OVERVIEW information. Should ignore information that is not
14830 // script name, function name, line number, and column offset.
14831 const char *overview_source =
14832 "function bar() {\n"
14833 " var y; AnalyzeStackInNativeCode(1);\n"
14834 "}\n"
14835 "function foo() {\n"
14836 "\n"
14837 " bar();\n"
14838 "}\n"
14839 "var x;eval('new foo();');";
14840 v8::Handle<v8::String> overview_src = v8::String::New(overview_source);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000014841 v8::Handle<Value> overview_result(
14842 v8::Script::New(overview_src, origin)->Run());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000014843 CHECK(!overview_result.IsEmpty());
14844 CHECK(overview_result->IsObject());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000014845
14846 // Test getting DETAILED information.
14847 const char *detailed_source =
14848 "function bat() {AnalyzeStackInNativeCode(2);\n"
14849 "}\n"
14850 "\n"
14851 "function baz() {\n"
14852 " bat();\n"
14853 "}\n"
14854 "eval('new baz();');";
14855 v8::Handle<v8::String> detailed_src = v8::String::New(detailed_source);
14856 // Make the script using a non-zero line and column offset.
14857 v8::Handle<v8::Integer> line_offset = v8::Integer::New(3);
14858 v8::Handle<v8::Integer> column_offset = v8::Integer::New(5);
14859 v8::ScriptOrigin detailed_origin(origin, line_offset, column_offset);
14860 v8::Handle<v8::Script> detailed_script(
14861 v8::Script::New(detailed_src, &detailed_origin));
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000014862 v8::Handle<Value> detailed_result(detailed_script->Run());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000014863 CHECK(!detailed_result.IsEmpty());
14864 CHECK(detailed_result->IsObject());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000014865}
14866
14867
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000014868static void StackTraceForUncaughtExceptionListener(
14869 v8::Handle<v8::Message> message,
14870 v8::Handle<Value>) {
14871 v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
14872 CHECK_EQ(2, stack_trace->GetFrameCount());
14873 checkStackFrame("origin", "foo", 2, 3, false, false,
14874 stack_trace->GetFrame(0));
14875 checkStackFrame("origin", "bar", 5, 3, false, false,
14876 stack_trace->GetFrame(1));
14877}
14878
14879TEST(CaptureStackTraceForUncaughtException) {
14880 report_count = 0;
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000014881 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000014882 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000014883 v8::V8::AddMessageListener(StackTraceForUncaughtExceptionListener);
14884 v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
14885
14886 Script::Compile(v8_str("function foo() {\n"
14887 " throw 1;\n"
14888 "};\n"
14889 "function bar() {\n"
14890 " foo();\n"
14891 "};"),
14892 v8_str("origin"))->Run();
14893 v8::Local<v8::Object> global = env->Global();
14894 Local<Value> trouble = global->Get(v8_str("bar"));
14895 CHECK(trouble->IsFunction());
14896 Function::Cast(*trouble)->Call(global, 0, NULL);
14897 v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
14898 v8::V8::RemoveMessageListeners(StackTraceForUncaughtExceptionListener);
14899}
14900
14901
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000014902TEST(CaptureStackTraceForUncaughtExceptionAndSetters) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000014903 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000014904 v8::HandleScope scope(env->GetIsolate());
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000014905 v8::V8::SetCaptureStackTraceForUncaughtExceptions(true,
14906 1024,
14907 v8::StackTrace::kDetailed);
14908
14909 CompileRun(
14910 "var setters = ['column', 'lineNumber', 'scriptName',\n"
14911 " 'scriptNameOrSourceURL', 'functionName', 'isEval',\n"
14912 " 'isConstructor'];\n"
14913 "for (var i = 0; i < setters.length; i++) {\n"
14914 " var prop = setters[i];\n"
14915 " Object.prototype.__defineSetter__(prop, function() { throw prop; });\n"
14916 "}\n");
14917 CompileRun("throw 'exception';");
14918 v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
14919}
14920
14921
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000014922static void RethrowStackTraceHandler(v8::Handle<v8::Message> message,
14923 v8::Handle<v8::Value> data) {
14924 // Use the frame where JavaScript is called from.
14925 v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
14926 CHECK(!stack_trace.IsEmpty());
14927 int frame_count = stack_trace->GetFrameCount();
14928 CHECK_EQ(3, frame_count);
14929 int line_number[] = {1, 2, 5};
14930 for (int i = 0; i < frame_count; i++) {
14931 CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber());
14932 }
14933}
14934
14935
14936// Test that we only return the stack trace at the site where the exception
14937// is first thrown (not where it is rethrown).
14938TEST(RethrowStackTrace) {
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000014939 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000014940 v8::HandleScope scope(env->GetIsolate());
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000014941 // We make sure that
14942 // - the stack trace of the ReferenceError in g() is reported.
14943 // - the stack trace is not overwritten when e1 is rethrown by t().
14944 // - the stack trace of e2 does not overwrite that of e1.
14945 const char* source =
14946 "function g() { error; } \n"
14947 "function f() { g(); } \n"
14948 "function t(e) { throw e; } \n"
14949 "try { \n"
14950 " f(); \n"
14951 "} catch (e1) { \n"
14952 " try { \n"
14953 " error; \n"
14954 " } catch (e2) { \n"
14955 " t(e1); \n"
14956 " } \n"
14957 "} \n";
14958 v8::V8::AddMessageListener(RethrowStackTraceHandler);
14959 v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
14960 CompileRun(source);
14961 v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
14962 v8::V8::RemoveMessageListeners(RethrowStackTraceHandler);
14963}
14964
14965
14966static void RethrowPrimitiveStackTraceHandler(v8::Handle<v8::Message> message,
14967 v8::Handle<v8::Value> data) {
14968 v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
14969 CHECK(!stack_trace.IsEmpty());
14970 int frame_count = stack_trace->GetFrameCount();
14971 CHECK_EQ(2, frame_count);
14972 int line_number[] = {3, 7};
14973 for (int i = 0; i < frame_count; i++) {
14974 CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber());
14975 }
14976}
14977
14978
14979// Test that we do not recognize identity for primitive exceptions.
14980TEST(RethrowPrimitiveStackTrace) {
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000014981 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000014982 v8::HandleScope scope(env->GetIsolate());
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000014983 // We do not capture stack trace for non Error objects on creation time.
14984 // Instead, we capture the stack trace on last throw.
14985 const char* source =
14986 "function g() { throw 404; } \n"
14987 "function f() { g(); } \n"
14988 "function t(e) { throw e; } \n"
14989 "try { \n"
14990 " f(); \n"
14991 "} catch (e1) { \n"
14992 " t(e1) \n"
14993 "} \n";
14994 v8::V8::AddMessageListener(RethrowPrimitiveStackTraceHandler);
14995 v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
14996 CompileRun(source);
14997 v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
14998 v8::V8::RemoveMessageListeners(RethrowPrimitiveStackTraceHandler);
14999}
15000
15001
15002static void RethrowExistingStackTraceHandler(v8::Handle<v8::Message> message,
15003 v8::Handle<v8::Value> data) {
15004 // Use the frame where JavaScript is called from.
15005 v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
15006 CHECK(!stack_trace.IsEmpty());
15007 CHECK_EQ(1, stack_trace->GetFrameCount());
15008 CHECK_EQ(1, stack_trace->GetFrame(0)->GetLineNumber());
15009}
15010
15011
15012// Test that the stack trace is captured when the error object is created and
15013// not where it is thrown.
15014TEST(RethrowExistingStackTrace) {
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000015015 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015016 v8::HandleScope scope(env->GetIsolate());
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000015017 const char* source =
15018 "var e = new Error(); \n"
15019 "throw e; \n";
15020 v8::V8::AddMessageListener(RethrowExistingStackTraceHandler);
15021 v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
15022 CompileRun(source);
15023 v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
15024 v8::V8::RemoveMessageListeners(RethrowExistingStackTraceHandler);
15025}
15026
15027
15028static void RethrowBogusErrorStackTraceHandler(v8::Handle<v8::Message> message,
15029 v8::Handle<v8::Value> data) {
15030 // Use the frame where JavaScript is called from.
15031 v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
15032 CHECK(!stack_trace.IsEmpty());
15033 CHECK_EQ(1, stack_trace->GetFrameCount());
15034 CHECK_EQ(2, stack_trace->GetFrame(0)->GetLineNumber());
15035}
15036
15037
15038// Test that the stack trace is captured where the bogus Error object is thrown.
15039TEST(RethrowBogusErrorStackTrace) {
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000015040 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015041 v8::HandleScope scope(env->GetIsolate());
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000015042 const char* source =
15043 "var e = {__proto__: new Error()} \n"
15044 "throw e; \n";
15045 v8::V8::AddMessageListener(RethrowBogusErrorStackTraceHandler);
15046 v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
15047 CompileRun(source);
15048 v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
15049 v8::V8::RemoveMessageListeners(RethrowBogusErrorStackTraceHandler);
15050}
15051
15052
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000015053v8::Handle<Value> AnalyzeStackOfEvalWithSourceURL(const v8::Arguments& args) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015054 v8::HandleScope scope(args.GetIsolate());
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000015055 v8::Handle<v8::StackTrace> stackTrace =
15056 v8::StackTrace::CurrentStackTrace(10, v8::StackTrace::kDetailed);
15057 CHECK_EQ(5, stackTrace->GetFrameCount());
15058 v8::Handle<v8::String> url = v8_str("eval_url");
15059 for (int i = 0; i < 3; i++) {
15060 v8::Handle<v8::String> name =
15061 stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
15062 CHECK(!name.IsEmpty());
15063 CHECK_EQ(url, name);
15064 }
15065 return v8::Undefined();
15066}
15067
15068
15069TEST(SourceURLInStackTrace) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015070 v8::HandleScope scope(v8::Isolate::GetCurrent());
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000015071 Local<ObjectTemplate> templ = ObjectTemplate::New();
15072 templ->Set(v8_str("AnalyzeStackOfEvalWithSourceURL"),
15073 v8::FunctionTemplate::New(AnalyzeStackOfEvalWithSourceURL));
15074 LocalContext context(0, templ);
15075
15076 const char *source =
15077 "function outer() {\n"
15078 "function bar() {\n"
15079 " AnalyzeStackOfEvalWithSourceURL();\n"
15080 "}\n"
15081 "function foo() {\n"
15082 "\n"
15083 " bar();\n"
15084 "}\n"
15085 "foo();\n"
15086 "}\n"
15087 "eval('(' + outer +')()//@ sourceURL=eval_url');";
15088 CHECK(CompileRun(source)->IsUndefined());
15089}
15090
15091
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000015092v8::Handle<Value> AnalyzeStackOfInlineScriptWithSourceURL(
15093 const v8::Arguments& args) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015094 v8::HandleScope scope(args.GetIsolate());
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000015095 v8::Handle<v8::StackTrace> stackTrace =
15096 v8::StackTrace::CurrentStackTrace(10, v8::StackTrace::kDetailed);
15097 CHECK_EQ(4, stackTrace->GetFrameCount());
15098 v8::Handle<v8::String> url = v8_str("url");
15099 for (int i = 0; i < 3; i++) {
15100 v8::Handle<v8::String> name =
15101 stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
15102 CHECK(!name.IsEmpty());
15103 CHECK_EQ(url, name);
15104 }
15105 return v8::Undefined();
15106}
15107
15108
15109TEST(InlineScriptWithSourceURLInStackTrace) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015110 v8::HandleScope scope(v8::Isolate::GetCurrent());
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000015111 Local<ObjectTemplate> templ = ObjectTemplate::New();
15112 templ->Set(v8_str("AnalyzeStackOfInlineScriptWithSourceURL"),
15113 v8::FunctionTemplate::New(
15114 AnalyzeStackOfInlineScriptWithSourceURL));
15115 LocalContext context(0, templ);
15116
15117 const char *source =
15118 "function outer() {\n"
15119 "function bar() {\n"
15120 " AnalyzeStackOfInlineScriptWithSourceURL();\n"
15121 "}\n"
15122 "function foo() {\n"
15123 "\n"
15124 " bar();\n"
15125 "}\n"
15126 "foo();\n"
15127 "}\n"
15128 "outer()\n"
15129 "//@ sourceURL=source_url";
15130 CHECK(CompileRunWithOrigin(source, "url", 0, 1)->IsUndefined());
15131}
15132
15133
15134v8::Handle<Value> AnalyzeStackOfDynamicScriptWithSourceURL(
15135 const v8::Arguments& args) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015136 v8::HandleScope scope(args.GetIsolate());
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000015137 v8::Handle<v8::StackTrace> stackTrace =
15138 v8::StackTrace::CurrentStackTrace(10, v8::StackTrace::kDetailed);
15139 CHECK_EQ(4, stackTrace->GetFrameCount());
15140 v8::Handle<v8::String> url = v8_str("source_url");
15141 for (int i = 0; i < 3; i++) {
15142 v8::Handle<v8::String> name =
15143 stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
15144 CHECK(!name.IsEmpty());
15145 CHECK_EQ(url, name);
15146 }
15147 return v8::Undefined();
15148}
15149
15150
15151TEST(DynamicWithSourceURLInStackTrace) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015152 v8::HandleScope scope(v8::Isolate::GetCurrent());
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000015153 Local<ObjectTemplate> templ = ObjectTemplate::New();
15154 templ->Set(v8_str("AnalyzeStackOfDynamicScriptWithSourceURL"),
15155 v8::FunctionTemplate::New(
15156 AnalyzeStackOfDynamicScriptWithSourceURL));
15157 LocalContext context(0, templ);
15158
15159 const char *source =
15160 "function outer() {\n"
15161 "function bar() {\n"
15162 " AnalyzeStackOfDynamicScriptWithSourceURL();\n"
15163 "}\n"
15164 "function foo() {\n"
15165 "\n"
15166 " bar();\n"
15167 "}\n"
15168 "foo();\n"
15169 "}\n"
15170 "outer()\n"
15171 "//@ sourceURL=source_url";
15172 CHECK(CompileRunWithOrigin(source, "url", 0, 0)->IsUndefined());
15173}
15174
danno@chromium.org2c26cb12012-05-03 09:06:43 +000015175static void CreateGarbageInOldSpace() {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015176 v8::HandleScope scope(v8::Isolate::GetCurrent());
danno@chromium.org2c26cb12012-05-03 09:06:43 +000015177 i::AlwaysAllocateScope always_allocate;
15178 for (int i = 0; i < 1000; i++) {
15179 FACTORY->NewFixedArray(1000, i::TENURED);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000015180 }
svenpanne@chromium.orgecb9dd62011-12-01 08:22:35 +000015181}
15182
15183// Test that idle notification can be handled and eventually returns true.
danno@chromium.org2c26cb12012-05-03 09:06:43 +000015184TEST(IdleNotification) {
15185 const intptr_t MB = 1024 * 1024;
danno@chromium.org2c26cb12012-05-03 09:06:43 +000015186 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015187 v8::HandleScope scope(env->GetIsolate());
danno@chromium.org2c26cb12012-05-03 09:06:43 +000015188 intptr_t initial_size = HEAP->SizeOfObjects();
15189 CreateGarbageInOldSpace();
15190 intptr_t size_with_garbage = HEAP->SizeOfObjects();
15191 CHECK_GT(size_with_garbage, initial_size + MB);
15192 bool finished = false;
15193 for (int i = 0; i < 200 && !finished; i++) {
15194 finished = v8::V8::IdleNotification();
15195 }
15196 intptr_t final_size = HEAP->SizeOfObjects();
15197 CHECK(finished);
15198 CHECK_LT(final_size, initial_size + 1);
15199}
15200
15201
15202// Test that idle notification can be handled and eventually collects garbage.
yangguo@chromium.org56454712012-02-16 15:33:53 +000015203TEST(IdleNotificationWithSmallHint) {
danno@chromium.org2c26cb12012-05-03 09:06:43 +000015204 const intptr_t MB = 1024 * 1024;
15205 const int IdlePauseInMs = 900;
svenpanne@chromium.orgecb9dd62011-12-01 08:22:35 +000015206 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015207 v8::HandleScope scope(env->GetIsolate());
danno@chromium.org2c26cb12012-05-03 09:06:43 +000015208 intptr_t initial_size = HEAP->SizeOfObjects();
15209 CreateGarbageInOldSpace();
15210 intptr_t size_with_garbage = HEAP->SizeOfObjects();
15211 CHECK_GT(size_with_garbage, initial_size + MB);
15212 bool finished = false;
15213 for (int i = 0; i < 200 && !finished; i++) {
15214 finished = v8::V8::IdleNotification(IdlePauseInMs);
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000015215 }
danno@chromium.org2c26cb12012-05-03 09:06:43 +000015216 intptr_t final_size = HEAP->SizeOfObjects();
15217 CHECK(finished);
15218 CHECK_LT(final_size, initial_size + 1);
yangguo@chromium.org56454712012-02-16 15:33:53 +000015219}
15220
15221
danno@chromium.org2c26cb12012-05-03 09:06:43 +000015222// Test that idle notification can be handled and eventually collects garbage.
yangguo@chromium.org56454712012-02-16 15:33:53 +000015223TEST(IdleNotificationWithLargeHint) {
danno@chromium.org2c26cb12012-05-03 09:06:43 +000015224 const intptr_t MB = 1024 * 1024;
15225 const int IdlePauseInMs = 900;
yangguo@chromium.org56454712012-02-16 15:33:53 +000015226 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015227 v8::HandleScope scope(env->GetIsolate());
danno@chromium.org2c26cb12012-05-03 09:06:43 +000015228 intptr_t initial_size = HEAP->SizeOfObjects();
15229 CreateGarbageInOldSpace();
15230 intptr_t size_with_garbage = HEAP->SizeOfObjects();
15231 CHECK_GT(size_with_garbage, initial_size + MB);
15232 bool finished = false;
15233 for (int i = 0; i < 200 && !finished; i++) {
15234 finished = v8::V8::IdleNotification(IdlePauseInMs);
yangguo@chromium.org56454712012-02-16 15:33:53 +000015235 }
danno@chromium.org2c26cb12012-05-03 09:06:43 +000015236 intptr_t final_size = HEAP->SizeOfObjects();
15237 CHECK(finished);
15238 CHECK_LT(final_size, initial_size + 1);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000015239}
15240
15241
danno@chromium.org2c26cb12012-05-03 09:06:43 +000015242TEST(Regress2107) {
15243 const intptr_t MB = 1024 * 1024;
15244 const int kShortIdlePauseInMs = 100;
15245 const int kLongIdlePauseInMs = 1000;
danno@chromium.org2c26cb12012-05-03 09:06:43 +000015246 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015247 v8::HandleScope scope(env->GetIsolate());
danno@chromium.org2c26cb12012-05-03 09:06:43 +000015248 intptr_t initial_size = HEAP->SizeOfObjects();
15249 // Send idle notification to start a round of incremental GCs.
15250 v8::V8::IdleNotification(kShortIdlePauseInMs);
15251 // Emulate 7 page reloads.
15252 for (int i = 0; i < 7; i++) {
15253 v8::Persistent<v8::Context> ctx = v8::Context::New();
15254 ctx->Enter();
15255 CreateGarbageInOldSpace();
15256 ctx->Exit();
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000015257 ctx.Dispose(ctx->GetIsolate());
danno@chromium.org2c26cb12012-05-03 09:06:43 +000015258 v8::V8::ContextDisposedNotification();
15259 v8::V8::IdleNotification(kLongIdlePauseInMs);
15260 }
15261 // Create garbage and check that idle notification still collects it.
15262 CreateGarbageInOldSpace();
15263 intptr_t size_with_garbage = HEAP->SizeOfObjects();
15264 CHECK_GT(size_with_garbage, initial_size + MB);
15265 bool finished = false;
15266 for (int i = 0; i < 200 && !finished; i++) {
15267 finished = v8::V8::IdleNotification(kShortIdlePauseInMs);
15268 }
15269 intptr_t final_size = HEAP->SizeOfObjects();
15270 CHECK_LT(final_size, initial_size + 1);
15271}
15272
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000015273static uint32_t* stack_limit;
15274
15275static v8::Handle<Value> GetStackLimitCallback(const v8::Arguments& args) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000015276 stack_limit = reinterpret_cast<uint32_t*>(
15277 i::Isolate::Current()->stack_guard()->real_climit());
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000015278 return v8::Undefined();
15279}
15280
15281
15282// Uses the address of a local variable to determine the stack top now.
15283// Given a size, returns an address that is that far from the current
15284// top of stack.
15285static uint32_t* ComputeStackLimit(uint32_t size) {
15286 uint32_t* answer = &size - (size / sizeof(size));
15287 // If the size is very large and the stack is very near the bottom of
15288 // memory then the calculation above may wrap around and give an address
15289 // that is above the (downwards-growing) stack. In that case we return
15290 // a very low address.
15291 if (answer > &size) return reinterpret_cast<uint32_t*>(sizeof(size));
15292 return answer;
15293}
15294
15295
15296TEST(SetResourceConstraints) {
15297 static const int K = 1024;
15298 uint32_t* set_limit = ComputeStackLimit(128 * K);
15299
15300 // Set stack limit.
15301 v8::ResourceConstraints constraints;
15302 constraints.set_stack_limit(set_limit);
15303 CHECK(v8::SetResourceConstraints(&constraints));
15304
15305 // Execute a script.
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000015306 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015307 v8::HandleScope scope(env->GetIsolate());
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000015308 Local<v8::FunctionTemplate> fun_templ =
15309 v8::FunctionTemplate::New(GetStackLimitCallback);
15310 Local<Function> fun = fun_templ->GetFunction();
15311 env->Global()->Set(v8_str("get_stack_limit"), fun);
15312 CompileRun("get_stack_limit();");
15313
15314 CHECK(stack_limit == set_limit);
15315}
15316
15317
15318TEST(SetResourceConstraintsInThread) {
15319 uint32_t* set_limit;
15320 {
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000015321 v8::Locker locker(CcTest::default_isolate());
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000015322 static const int K = 1024;
15323 set_limit = ComputeStackLimit(128 * K);
15324
15325 // Set stack limit.
15326 v8::ResourceConstraints constraints;
15327 constraints.set_stack_limit(set_limit);
15328 CHECK(v8::SetResourceConstraints(&constraints));
15329
15330 // Execute a script.
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015331 v8::HandleScope scope(CcTest::default_isolate());
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000015332 LocalContext env;
15333 Local<v8::FunctionTemplate> fun_templ =
15334 v8::FunctionTemplate::New(GetStackLimitCallback);
15335 Local<Function> fun = fun_templ->GetFunction();
15336 env->Global()->Set(v8_str("get_stack_limit"), fun);
15337 CompileRun("get_stack_limit();");
15338
15339 CHECK(stack_limit == set_limit);
15340 }
15341 {
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000015342 v8::Locker locker(CcTest::default_isolate());
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000015343 CHECK(stack_limit == set_limit);
15344 }
ager@chromium.org96c75b52009-08-26 09:13:16 +000015345}
ager@chromium.org3811b432009-10-28 14:53:37 +000015346
15347
15348THREADED_TEST(GetHeapStatistics) {
ager@chromium.org3811b432009-10-28 14:53:37 +000015349 LocalContext c1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015350 v8::HandleScope scope(c1->GetIsolate());
ager@chromium.org3811b432009-10-28 14:53:37 +000015351 v8::HeapStatistics heap_statistics;
ager@chromium.orgc4c92722009-11-18 14:12:51 +000015352 CHECK_EQ(static_cast<int>(heap_statistics.total_heap_size()), 0);
15353 CHECK_EQ(static_cast<int>(heap_statistics.used_heap_size()), 0);
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +000015354 c1->GetIsolate()->GetHeapStatistics(&heap_statistics);
ager@chromium.orgc4c92722009-11-18 14:12:51 +000015355 CHECK_NE(static_cast<int>(heap_statistics.total_heap_size()), 0);
15356 CHECK_NE(static_cast<int>(heap_statistics.used_heap_size()), 0);
ager@chromium.org3811b432009-10-28 14:53:37 +000015357}
15358
15359
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000015360class VisitorImpl : public v8::ExternalResourceVisitor {
15361 public:
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000015362 explicit VisitorImpl(TestResource** resource) {
15363 for (int i = 0; i < 4; i++) {
15364 resource_[i] = resource[i];
15365 found_resource_[i] = false;
15366 }
15367 }
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000015368 virtual ~VisitorImpl() {}
15369 virtual void VisitExternalString(v8::Handle<v8::String> string) {
15370 if (!string->IsExternal()) {
15371 CHECK(string->IsExternalAscii());
15372 return;
15373 }
15374 v8::String::ExternalStringResource* resource =
15375 string->GetExternalStringResource();
15376 CHECK(resource);
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000015377 for (int i = 0; i < 4; i++) {
15378 if (resource_[i] == resource) {
15379 CHECK(!found_resource_[i]);
15380 found_resource_[i] = true;
15381 }
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000015382 }
15383 }
15384 void CheckVisitedResources() {
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000015385 for (int i = 0; i < 4; i++) {
15386 CHECK(found_resource_[i]);
15387 }
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000015388 }
15389
15390 private:
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000015391 v8::String::ExternalStringResource* resource_[4];
15392 bool found_resource_[4];
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000015393};
15394
15395TEST(VisitExternalStrings) {
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000015396 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015397 v8::HandleScope scope(env->GetIsolate());
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000015398 const char* string = "Some string";
15399 uint16_t* two_byte_string = AsciiToTwoByteString(string);
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000015400 TestResource* resource[4];
15401 resource[0] = new TestResource(two_byte_string);
15402 v8::Local<v8::String> string0 = v8::String::NewExternal(resource[0]);
15403 resource[1] = new TestResource(two_byte_string);
15404 v8::Local<v8::String> string1 = v8::String::NewExternal(resource[1]);
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000015405
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000015406 // Externalized symbol.
15407 resource[2] = new TestResource(two_byte_string);
15408 v8::Local<v8::String> string2 = v8::String::NewSymbol(string);
15409 CHECK(string2->MakeExternal(resource[2]));
15410
15411 // Symbolized External.
15412 resource[3] = new TestResource(AsciiToTwoByteString("Some other string"));
15413 v8::Local<v8::String> string3 = v8::String::NewExternal(resource[3]);
15414 HEAP->CollectAllAvailableGarbage(); // Tenure string.
15415 // Turn into a symbol.
15416 i::Handle<i::String> string3_i = v8::Utils::OpenHandle(*string3);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +000015417 CHECK(!HEAP->InternalizeString(*string3_i)->IsFailure());
15418 CHECK(string3_i->IsInternalizedString());
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000015419
15420 // We need to add usages for string* to avoid warnings in GCC 4.7
15421 CHECK(string0->IsExternal());
ulan@chromium.org2efb9002012-01-19 15:36:35 +000015422 CHECK(string1->IsExternal());
15423 CHECK(string2->IsExternal());
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000015424 CHECK(string3->IsExternal());
ulan@chromium.org2efb9002012-01-19 15:36:35 +000015425
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000015426 VisitorImpl visitor(resource);
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000015427 v8::V8::VisitExternalResources(&visitor);
15428 visitor.CheckVisitedResources();
15429}
15430
15431
ager@chromium.org3811b432009-10-28 14:53:37 +000015432static double DoubleFromBits(uint64_t value) {
15433 double target;
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +000015434 i::OS::MemCopy(&target, &value, sizeof(target));
ager@chromium.org3811b432009-10-28 14:53:37 +000015435 return target;
15436}
15437
15438
15439static uint64_t DoubleToBits(double value) {
15440 uint64_t target;
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +000015441 i::OS::MemCopy(&target, &value, sizeof(target));
ager@chromium.org3811b432009-10-28 14:53:37 +000015442 return target;
15443}
15444
15445
15446static double DoubleToDateTime(double input) {
15447 double date_limit = 864e13;
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +000015448 if (isnan(input) || input < -date_limit || input > date_limit) {
ager@chromium.org3811b432009-10-28 14:53:37 +000015449 return i::OS::nan_value();
15450 }
15451 return (input < 0) ? -(floor(-input)) : floor(input);
15452}
15453
15454// We don't have a consistent way to write 64-bit constants syntactically, so we
15455// split them into two 32-bit constants and combine them programmatically.
15456static double DoubleFromBits(uint32_t high_bits, uint32_t low_bits) {
15457 return DoubleFromBits((static_cast<uint64_t>(high_bits) << 32) | low_bits);
15458}
15459
15460
15461THREADED_TEST(QuietSignalingNaNs) {
ager@chromium.org3811b432009-10-28 14:53:37 +000015462 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015463 v8::HandleScope scope(context->GetIsolate());
ager@chromium.org3811b432009-10-28 14:53:37 +000015464 v8::TryCatch try_catch;
15465
15466 // Special double values.
15467 double snan = DoubleFromBits(0x7ff00000, 0x00000001);
15468 double qnan = DoubleFromBits(0x7ff80000, 0x00000000);
15469 double infinity = DoubleFromBits(0x7ff00000, 0x00000000);
15470 double max_normal = DoubleFromBits(0x7fefffff, 0xffffffffu);
15471 double min_normal = DoubleFromBits(0x00100000, 0x00000000);
15472 double max_denormal = DoubleFromBits(0x000fffff, 0xffffffffu);
15473 double min_denormal = DoubleFromBits(0x00000000, 0x00000001);
15474
15475 // Date values are capped at +/-100000000 days (times 864e5 ms per day)
15476 // on either side of the epoch.
15477 double date_limit = 864e13;
15478
15479 double test_values[] = {
15480 snan,
15481 qnan,
15482 infinity,
15483 max_normal,
15484 date_limit + 1,
15485 date_limit,
15486 min_normal,
15487 max_denormal,
15488 min_denormal,
15489 0,
15490 -0,
15491 -min_denormal,
15492 -max_denormal,
15493 -min_normal,
15494 -date_limit,
15495 -date_limit - 1,
15496 -max_normal,
15497 -infinity,
15498 -qnan,
15499 -snan
15500 };
15501 int num_test_values = 20;
15502
15503 for (int i = 0; i < num_test_values; i++) {
15504 double test_value = test_values[i];
15505
15506 // Check that Number::New preserves non-NaNs and quiets SNaNs.
15507 v8::Handle<v8::Value> number = v8::Number::New(test_value);
15508 double stored_number = number->NumberValue();
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +000015509 if (!isnan(test_value)) {
ager@chromium.org3811b432009-10-28 14:53:37 +000015510 CHECK_EQ(test_value, stored_number);
15511 } else {
15512 uint64_t stored_bits = DoubleToBits(stored_number);
15513 // Check if quiet nan (bits 51..62 all set).
danno@chromium.orgc612e022011-11-10 11:38:15 +000015514#if defined(V8_TARGET_ARCH_MIPS) && !defined(USE_SIMULATOR)
15515 // Most significant fraction bit for quiet nan is set to 0
15516 // on MIPS architecture. Allowed by IEEE-754.
15517 CHECK_EQ(0xffe, static_cast<int>((stored_bits >> 51) & 0xfff));
15518#else
ager@chromium.org3811b432009-10-28 14:53:37 +000015519 CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff));
danno@chromium.orgc612e022011-11-10 11:38:15 +000015520#endif
ager@chromium.org3811b432009-10-28 14:53:37 +000015521 }
15522
15523 // Check that Date::New preserves non-NaNs in the date range and
15524 // quiets SNaNs.
15525 v8::Handle<v8::Value> date = v8::Date::New(test_value);
15526 double expected_stored_date = DoubleToDateTime(test_value);
15527 double stored_date = date->NumberValue();
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +000015528 if (!isnan(expected_stored_date)) {
ager@chromium.org3811b432009-10-28 14:53:37 +000015529 CHECK_EQ(expected_stored_date, stored_date);
15530 } else {
15531 uint64_t stored_bits = DoubleToBits(stored_date);
15532 // Check if quiet nan (bits 51..62 all set).
danno@chromium.orgc612e022011-11-10 11:38:15 +000015533#if defined(V8_TARGET_ARCH_MIPS) && !defined(USE_SIMULATOR)
15534 // Most significant fraction bit for quiet nan is set to 0
15535 // on MIPS architecture. Allowed by IEEE-754.
15536 CHECK_EQ(0xffe, static_cast<int>((stored_bits >> 51) & 0xfff));
15537#else
ager@chromium.org3811b432009-10-28 14:53:37 +000015538 CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff));
danno@chromium.orgc612e022011-11-10 11:38:15 +000015539#endif
ager@chromium.org3811b432009-10-28 14:53:37 +000015540 }
15541 }
15542}
christian.plesner.hansen@gmail.comb9ce6372009-11-03 11:38:18 +000015543
15544
15545static v8::Handle<Value> SpaghettiIncident(const v8::Arguments& args) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015546 v8::HandleScope scope(args.GetIsolate());
christian.plesner.hansen@gmail.comb9ce6372009-11-03 11:38:18 +000015547 v8::TryCatch tc;
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000015548 v8::Handle<v8::String> str(args[0]->ToString());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000015549 USE(str);
christian.plesner.hansen@gmail.comb9ce6372009-11-03 11:38:18 +000015550 if (tc.HasCaught())
15551 return tc.ReThrow();
15552 return v8::Undefined();
15553}
15554
15555
15556// Test that an exception can be propagated down through a spaghetti
15557// stack using ReThrow.
15558THREADED_TEST(SpaghettiStackReThrow) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015559 v8::HandleScope scope(v8::Isolate::GetCurrent());
christian.plesner.hansen@gmail.comb9ce6372009-11-03 11:38:18 +000015560 LocalContext context;
15561 context->Global()->Set(
15562 v8::String::New("s"),
15563 v8::FunctionTemplate::New(SpaghettiIncident)->GetFunction());
15564 v8::TryCatch try_catch;
15565 CompileRun(
15566 "var i = 0;"
15567 "var o = {"
15568 " toString: function () {"
15569 " if (i == 10) {"
15570 " throw 'Hey!';"
15571 " } else {"
15572 " i++;"
15573 " return s(o);"
15574 " }"
15575 " }"
15576 "};"
15577 "s(o);");
15578 CHECK(try_catch.HasCaught());
15579 v8::String::Utf8Value value(try_catch.Exception());
15580 CHECK_EQ(0, strcmp(*value, "Hey!"));
15581}
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000015582
15583
sgjesse@chromium.org98180592009-12-02 08:17:28 +000015584TEST(Regress528) {
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000015585 v8::V8::Initialize();
15586
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015587 v8::HandleScope scope(v8::Isolate::GetCurrent());
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000015588 v8::Persistent<Context> context;
ager@chromium.org60121232009-12-03 11:25:37 +000015589 v8::Persistent<Context> other_context;
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000015590 int gc_count;
15591
ager@chromium.org60121232009-12-03 11:25:37 +000015592 // Create a context used to keep the code from aging in the compilation
15593 // cache.
15594 other_context = Context::New();
15595
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000015596 // Context-dependent context data creates reference from the compilation
15597 // cache to the global object.
ager@chromium.org60121232009-12-03 11:25:37 +000015598 const char* source_simple = "1";
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000015599 context = Context::New();
15600 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015601 v8::HandleScope scope(v8::Isolate::GetCurrent());
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000015602
15603 context->Enter();
15604 Local<v8::String> obj = v8::String::New("");
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000015605 context->SetEmbedderData(0, obj);
ager@chromium.org60121232009-12-03 11:25:37 +000015606 CompileRun(source_simple);
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000015607 context->Exit();
15608 }
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000015609 context.Dispose(context->GetIsolate());
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000015610 v8::V8::ContextDisposedNotification();
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000015611 for (gc_count = 1; gc_count < 10; gc_count++) {
ager@chromium.org60121232009-12-03 11:25:37 +000015612 other_context->Enter();
15613 CompileRun(source_simple);
15614 other_context->Exit();
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000015615 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org60121232009-12-03 11:25:37 +000015616 if (GetGlobalObjectsCount() == 1) break;
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000015617 }
ager@chromium.org60121232009-12-03 11:25:37 +000015618 CHECK_GE(2, gc_count);
15619 CHECK_EQ(1, GetGlobalObjectsCount());
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000015620
15621 // Eval in a function creates reference from the compilation cache to the
15622 // global object.
ager@chromium.org60121232009-12-03 11:25:37 +000015623 const char* source_eval = "function f(){eval('1')}; f()";
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000015624 context = Context::New();
15625 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015626 v8::HandleScope scope(v8::Isolate::GetCurrent());
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000015627
15628 context->Enter();
ager@chromium.org60121232009-12-03 11:25:37 +000015629 CompileRun(source_eval);
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000015630 context->Exit();
15631 }
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000015632 context.Dispose(context->GetIsolate());
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000015633 v8::V8::ContextDisposedNotification();
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000015634 for (gc_count = 1; gc_count < 10; gc_count++) {
ager@chromium.org60121232009-12-03 11:25:37 +000015635 other_context->Enter();
15636 CompileRun(source_eval);
15637 other_context->Exit();
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000015638 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org60121232009-12-03 11:25:37 +000015639 if (GetGlobalObjectsCount() == 1) break;
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000015640 }
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +000015641 CHECK_GE(2, gc_count);
sgjesse@chromium.org98180592009-12-02 08:17:28 +000015642 CHECK_EQ(1, GetGlobalObjectsCount());
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000015643
15644 // Looking up the line number for an exception creates reference from the
15645 // compilation cache to the global object.
ager@chromium.org60121232009-12-03 11:25:37 +000015646 const char* source_exception = "function f(){throw 1;} f()";
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000015647 context = Context::New();
15648 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015649 v8::HandleScope scope(v8::Isolate::GetCurrent());
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000015650
15651 context->Enter();
15652 v8::TryCatch try_catch;
ager@chromium.org60121232009-12-03 11:25:37 +000015653 CompileRun(source_exception);
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000015654 CHECK(try_catch.HasCaught());
15655 v8::Handle<v8::Message> message = try_catch.Message();
15656 CHECK(!message.IsEmpty());
15657 CHECK_EQ(1, message->GetLineNumber());
15658 context->Exit();
15659 }
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000015660 context.Dispose(context->GetIsolate());
svenpanne@chromium.orgc859c4f2012-10-15 11:51:39 +000015661 v8::V8::ContextDisposedNotification();
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000015662 for (gc_count = 1; gc_count < 10; gc_count++) {
ager@chromium.org60121232009-12-03 11:25:37 +000015663 other_context->Enter();
15664 CompileRun(source_exception);
15665 other_context->Exit();
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000015666 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org60121232009-12-03 11:25:37 +000015667 if (GetGlobalObjectsCount() == 1) break;
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000015668 }
ager@chromium.org60121232009-12-03 11:25:37 +000015669 CHECK_GE(2, gc_count);
15670 CHECK_EQ(1, GetGlobalObjectsCount());
15671
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000015672 other_context.Dispose(other_context->GetIsolate());
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000015673 v8::V8::ContextDisposedNotification();
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000015674}
ager@chromium.org5c838252010-02-19 08:53:10 +000015675
15676
15677THREADED_TEST(ScriptOrigin) {
ager@chromium.org5c838252010-02-19 08:53:10 +000015678 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015679 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org5c838252010-02-19 08:53:10 +000015680 v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::New("test"));
15681 v8::Handle<v8::String> script = v8::String::New(
15682 "function f() {}\n\nfunction g() {}");
15683 v8::Script::Compile(script, &origin)->Run();
15684 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
15685 env->Global()->Get(v8::String::New("f")));
15686 v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
15687 env->Global()->Get(v8::String::New("g")));
15688
15689 v8::ScriptOrigin script_origin_f = f->GetScriptOrigin();
15690 CHECK_EQ("test", *v8::String::AsciiValue(script_origin_f.ResourceName()));
15691 CHECK_EQ(0, script_origin_f.ResourceLineOffset()->Int32Value());
15692
15693 v8::ScriptOrigin script_origin_g = g->GetScriptOrigin();
15694 CHECK_EQ("test", *v8::String::AsciiValue(script_origin_g.ResourceName()));
15695 CHECK_EQ(0, script_origin_g.ResourceLineOffset()->Int32Value());
15696}
15697
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000015698THREADED_TEST(FunctionGetInferredName) {
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000015699 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015700 v8::HandleScope scope(env->GetIsolate());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000015701 v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::New("test"));
15702 v8::Handle<v8::String> script = v8::String::New(
15703 "var foo = { bar : { baz : function() {}}}; var f = foo.bar.baz;");
15704 v8::Script::Compile(script, &origin)->Run();
15705 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
15706 env->Global()->Get(v8::String::New("f")));
15707 CHECK_EQ("foo.bar.baz", *v8::String::AsciiValue(f->GetInferredName()));
15708}
ager@chromium.org5c838252010-02-19 08:53:10 +000015709
15710THREADED_TEST(ScriptLineNumber) {
ager@chromium.org5c838252010-02-19 08:53:10 +000015711 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015712 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org5c838252010-02-19 08:53:10 +000015713 v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::New("test"));
15714 v8::Handle<v8::String> script = v8::String::New(
15715 "function f() {}\n\nfunction g() {}");
15716 v8::Script::Compile(script, &origin)->Run();
15717 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
15718 env->Global()->Get(v8::String::New("f")));
15719 v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
15720 env->Global()->Get(v8::String::New("g")));
15721 CHECK_EQ(0, f->GetScriptLineNumber());
15722 CHECK_EQ(2, g->GetScriptLineNumber());
15723}
15724
15725
danno@chromium.orgc612e022011-11-10 11:38:15 +000015726THREADED_TEST(ScriptColumnNumber) {
danno@chromium.orgc612e022011-11-10 11:38:15 +000015727 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015728 v8::HandleScope scope(env->GetIsolate());
danno@chromium.orgc612e022011-11-10 11:38:15 +000015729 v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::New("test"),
15730 v8::Integer::New(3), v8::Integer::New(2));
15731 v8::Handle<v8::String> script = v8::String::New(
15732 "function foo() {}\n\n function bar() {}");
15733 v8::Script::Compile(script, &origin)->Run();
15734 v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
15735 env->Global()->Get(v8::String::New("foo")));
15736 v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
15737 env->Global()->Get(v8::String::New("bar")));
15738 CHECK_EQ(14, foo->GetScriptColumnNumber());
15739 CHECK_EQ(17, bar->GetScriptColumnNumber());
15740}
15741
15742
15743THREADED_TEST(FunctionGetScriptId) {
danno@chromium.orgc612e022011-11-10 11:38:15 +000015744 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015745 v8::HandleScope scope(env->GetIsolate());
danno@chromium.orgc612e022011-11-10 11:38:15 +000015746 v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::New("test"),
15747 v8::Integer::New(3), v8::Integer::New(2));
15748 v8::Handle<v8::String> scriptSource = v8::String::New(
15749 "function foo() {}\n\n function bar() {}");
15750 v8::Local<v8::Script> script(v8::Script::Compile(scriptSource, &origin));
15751 script->Run();
15752 v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
15753 env->Global()->Get(v8::String::New("foo")));
15754 v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
15755 env->Global()->Get(v8::String::New("bar")));
15756 CHECK_EQ(script->Id(), foo->GetScriptId());
15757 CHECK_EQ(script->Id(), bar->GetScriptId());
15758}
15759
15760
ager@chromium.org5c838252010-02-19 08:53:10 +000015761static v8::Handle<Value> GetterWhichReturns42(Local<String> name,
15762 const AccessorInfo& info) {
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000015763 CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
15764 CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
ager@chromium.org5c838252010-02-19 08:53:10 +000015765 return v8_num(42);
15766}
15767
15768
15769static void SetterWhichSetsYOnThisTo23(Local<String> name,
15770 Local<Value> value,
15771 const AccessorInfo& info) {
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000015772 CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
15773 CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
ager@chromium.org5c838252010-02-19 08:53:10 +000015774 info.This()->Set(v8_str("y"), v8_num(23));
15775}
15776
15777
erik.corry@gmail.com88767242012-08-08 14:43:45 +000015778Handle<Value> FooGetInterceptor(Local<String> name,
15779 const AccessorInfo& info) {
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000015780 CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
15781 CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
erik.corry@gmail.com88767242012-08-08 14:43:45 +000015782 if (!name->Equals(v8_str("foo"))) return Handle<Value>();
15783 return v8_num(42);
15784}
15785
15786
15787Handle<Value> FooSetInterceptor(Local<String> name,
15788 Local<Value> value,
15789 const AccessorInfo& info) {
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000015790 CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
15791 CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
erik.corry@gmail.com88767242012-08-08 14:43:45 +000015792 if (!name->Equals(v8_str("foo"))) return Handle<Value>();
15793 info.This()->Set(v8_str("y"), v8_num(23));
15794 return v8_num(23);
15795}
15796
15797
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000015798TEST(SetterOnConstructorPrototype) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015799 v8::HandleScope scope(v8::Isolate::GetCurrent());
ager@chromium.org5c838252010-02-19 08:53:10 +000015800 Local<ObjectTemplate> templ = ObjectTemplate::New();
15801 templ->SetAccessor(v8_str("x"),
15802 GetterWhichReturns42,
15803 SetterWhichSetsYOnThisTo23);
15804 LocalContext context;
15805 context->Global()->Set(v8_str("P"), templ->NewInstance());
15806 CompileRun("function C1() {"
15807 " this.x = 23;"
15808 "};"
15809 "C1.prototype = P;"
15810 "function C2() {"
15811 " this.x = 23"
15812 "};"
15813 "C2.prototype = { };"
15814 "C2.prototype.__proto__ = P;");
15815
15816 v8::Local<v8::Script> script;
15817 script = v8::Script::Compile(v8_str("new C1();"));
15818 for (int i = 0; i < 10; i++) {
15819 v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
15820 CHECK_EQ(42, c1->Get(v8_str("x"))->Int32Value());
15821 CHECK_EQ(23, c1->Get(v8_str("y"))->Int32Value());
15822 }
15823
15824 script = v8::Script::Compile(v8_str("new C2();"));
15825 for (int i = 0; i < 10; i++) {
15826 v8::Handle<v8::Object> c2 = v8::Handle<v8::Object>::Cast(script->Run());
15827 CHECK_EQ(42, c2->Get(v8_str("x"))->Int32Value());
15828 CHECK_EQ(23, c2->Get(v8_str("y"))->Int32Value());
15829 }
15830}
15831
15832
15833static v8::Handle<Value> NamedPropertyGetterWhichReturns42(
15834 Local<String> name, const AccessorInfo& info) {
15835 return v8_num(42);
15836}
15837
15838
15839static v8::Handle<Value> NamedPropertySetterWhichSetsYOnThisTo23(
15840 Local<String> name, Local<Value> value, const AccessorInfo& info) {
15841 if (name->Equals(v8_str("x"))) {
15842 info.This()->Set(v8_str("y"), v8_num(23));
15843 }
15844 return v8::Handle<Value>();
15845}
15846
15847
15848THREADED_TEST(InterceptorOnConstructorPrototype) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015849 v8::HandleScope scope(v8::Isolate::GetCurrent());
ager@chromium.org5c838252010-02-19 08:53:10 +000015850 Local<ObjectTemplate> templ = ObjectTemplate::New();
15851 templ->SetNamedPropertyHandler(NamedPropertyGetterWhichReturns42,
15852 NamedPropertySetterWhichSetsYOnThisTo23);
15853 LocalContext context;
15854 context->Global()->Set(v8_str("P"), templ->NewInstance());
15855 CompileRun("function C1() {"
15856 " this.x = 23;"
15857 "};"
15858 "C1.prototype = P;"
15859 "function C2() {"
15860 " this.x = 23"
15861 "};"
15862 "C2.prototype = { };"
15863 "C2.prototype.__proto__ = P;");
15864
15865 v8::Local<v8::Script> script;
15866 script = v8::Script::Compile(v8_str("new C1();"));
15867 for (int i = 0; i < 10; i++) {
15868 v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
15869 CHECK_EQ(23, c1->Get(v8_str("x"))->Int32Value());
15870 CHECK_EQ(42, c1->Get(v8_str("y"))->Int32Value());
15871 }
15872
15873 script = v8::Script::Compile(v8_str("new C2();"));
15874 for (int i = 0; i < 10; i++) {
15875 v8::Handle<v8::Object> c2 = v8::Handle<v8::Object>::Cast(script->Run());
15876 CHECK_EQ(23, c2->Get(v8_str("x"))->Int32Value());
15877 CHECK_EQ(42, c2->Get(v8_str("y"))->Int32Value());
15878 }
15879}
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000015880
15881
15882TEST(Bug618) {
15883 const char* source = "function C1() {"
15884 " this.x = 23;"
15885 "};"
15886 "C1.prototype = P;";
15887
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000015888 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015889 v8::HandleScope scope(context->GetIsolate());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000015890 v8::Local<v8::Script> script;
15891
15892 // Use a simple object as prototype.
15893 v8::Local<v8::Object> prototype = v8::Object::New();
15894 prototype->Set(v8_str("y"), v8_num(42));
15895 context->Global()->Set(v8_str("P"), prototype);
15896
15897 // This compile will add the code to the compilation cache.
15898 CompileRun(source);
15899
15900 script = v8::Script::Compile(v8_str("new C1();"));
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +000015901 // Allow enough iterations for the inobject slack tracking logic
15902 // to finalize instance size and install the fast construct stub.
15903 for (int i = 0; i < 256; i++) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000015904 v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
15905 CHECK_EQ(23, c1->Get(v8_str("x"))->Int32Value());
15906 CHECK_EQ(42, c1->Get(v8_str("y"))->Int32Value());
15907 }
15908
15909 // Use an API object with accessors as prototype.
15910 Local<ObjectTemplate> templ = ObjectTemplate::New();
15911 templ->SetAccessor(v8_str("x"),
15912 GetterWhichReturns42,
15913 SetterWhichSetsYOnThisTo23);
15914 context->Global()->Set(v8_str("P"), templ->NewInstance());
15915
15916 // This compile will get the code from the compilation cache.
15917 CompileRun(source);
15918
15919 script = v8::Script::Compile(v8_str("new C1();"));
15920 for (int i = 0; i < 10; i++) {
15921 v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
15922 CHECK_EQ(42, c1->Get(v8_str("x"))->Int32Value());
15923 CHECK_EQ(23, c1->Get(v8_str("y"))->Int32Value());
15924 }
15925}
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000015926
15927int prologue_call_count = 0;
15928int epilogue_call_count = 0;
15929int prologue_call_count_second = 0;
15930int epilogue_call_count_second = 0;
15931
15932void PrologueCallback(v8::GCType, v8::GCCallbackFlags) {
15933 ++prologue_call_count;
15934}
15935
15936void EpilogueCallback(v8::GCType, v8::GCCallbackFlags) {
15937 ++epilogue_call_count;
15938}
15939
15940void PrologueCallbackSecond(v8::GCType, v8::GCCallbackFlags) {
15941 ++prologue_call_count_second;
15942}
15943
15944void EpilogueCallbackSecond(v8::GCType, v8::GCCallbackFlags) {
15945 ++epilogue_call_count_second;
15946}
15947
15948TEST(GCCallbacks) {
15949 LocalContext context;
15950
15951 v8::V8::AddGCPrologueCallback(PrologueCallback);
15952 v8::V8::AddGCEpilogueCallback(EpilogueCallback);
15953 CHECK_EQ(0, prologue_call_count);
15954 CHECK_EQ(0, epilogue_call_count);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000015955 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000015956 CHECK_EQ(1, prologue_call_count);
15957 CHECK_EQ(1, epilogue_call_count);
15958 v8::V8::AddGCPrologueCallback(PrologueCallbackSecond);
15959 v8::V8::AddGCEpilogueCallback(EpilogueCallbackSecond);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000015960 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000015961 CHECK_EQ(2, prologue_call_count);
15962 CHECK_EQ(2, epilogue_call_count);
15963 CHECK_EQ(1, prologue_call_count_second);
15964 CHECK_EQ(1, epilogue_call_count_second);
15965 v8::V8::RemoveGCPrologueCallback(PrologueCallback);
15966 v8::V8::RemoveGCEpilogueCallback(EpilogueCallback);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000015967 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000015968 CHECK_EQ(2, prologue_call_count);
15969 CHECK_EQ(2, epilogue_call_count);
15970 CHECK_EQ(2, prologue_call_count_second);
15971 CHECK_EQ(2, epilogue_call_count_second);
15972 v8::V8::RemoveGCPrologueCallback(PrologueCallbackSecond);
15973 v8::V8::RemoveGCEpilogueCallback(EpilogueCallbackSecond);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000015974 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000015975 CHECK_EQ(2, prologue_call_count);
15976 CHECK_EQ(2, epilogue_call_count);
15977 CHECK_EQ(2, prologue_call_count_second);
15978 CHECK_EQ(2, epilogue_call_count_second);
15979}
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000015980
15981
15982THREADED_TEST(AddToJSFunctionResultCache) {
15983 i::FLAG_allow_natives_syntax = true;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015984 v8::HandleScope scope(v8::Isolate::GetCurrent());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000015985
15986 LocalContext context;
15987
15988 const char* code =
15989 "(function() {"
15990 " var key0 = 'a';"
15991 " var key1 = 'b';"
15992 " var r0 = %_GetFromCache(0, key0);"
15993 " var r1 = %_GetFromCache(0, key1);"
15994 " var r0_ = %_GetFromCache(0, key0);"
15995 " if (r0 !== r0_)"
15996 " return 'Different results for ' + key0 + ': ' + r0 + ' vs. ' + r0_;"
15997 " var r1_ = %_GetFromCache(0, key1);"
15998 " if (r1 !== r1_)"
15999 " return 'Different results for ' + key1 + ': ' + r1 + ' vs. ' + r1_;"
16000 " return 'PASSED';"
16001 "})()";
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000016002 HEAP->ClearJSFunctionResultCaches();
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000016003 ExpectString(code, "PASSED");
16004}
16005
16006
16007static const int k0CacheSize = 16;
16008
16009THREADED_TEST(FillJSFunctionResultCache) {
16010 i::FLAG_allow_natives_syntax = true;
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000016011 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016012 v8::HandleScope scope(context->GetIsolate());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000016013
16014 const char* code =
16015 "(function() {"
16016 " var k = 'a';"
16017 " var r = %_GetFromCache(0, k);"
16018 " for (var i = 0; i < 16; i++) {"
16019 " %_GetFromCache(0, 'a' + i);"
16020 " };"
16021 " if (r === %_GetFromCache(0, k))"
16022 " return 'FAILED: k0CacheSize is too small';"
16023 " return 'PASSED';"
16024 "})()";
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000016025 HEAP->ClearJSFunctionResultCaches();
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000016026 ExpectString(code, "PASSED");
16027}
16028
16029
16030THREADED_TEST(RoundRobinGetFromCache) {
16031 i::FLAG_allow_natives_syntax = true;
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000016032 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016033 v8::HandleScope scope(context->GetIsolate());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000016034
16035 const char* code =
16036 "(function() {"
16037 " var keys = [];"
16038 " for (var i = 0; i < 16; i++) keys.push(i);"
16039 " var values = [];"
16040 " for (var i = 0; i < 16; i++) values[i] = %_GetFromCache(0, keys[i]);"
16041 " for (var i = 0; i < 16; i++) {"
16042 " var v = %_GetFromCache(0, keys[i]);"
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000016043 " if (v.toString() !== values[i].toString())"
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000016044 " return 'Wrong value for ' + "
16045 " keys[i] + ': ' + v + ' vs. ' + values[i];"
16046 " };"
16047 " return 'PASSED';"
16048 "})()";
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000016049 HEAP->ClearJSFunctionResultCaches();
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000016050 ExpectString(code, "PASSED");
16051}
16052
16053
16054THREADED_TEST(ReverseGetFromCache) {
16055 i::FLAG_allow_natives_syntax = true;
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000016056 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016057 v8::HandleScope scope(context->GetIsolate());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000016058
16059 const char* code =
16060 "(function() {"
16061 " var keys = [];"
16062 " for (var i = 0; i < 16; i++) keys.push(i);"
16063 " var values = [];"
16064 " for (var i = 0; i < 16; i++) values[i] = %_GetFromCache(0, keys[i]);"
16065 " for (var i = 15; i >= 16; i--) {"
16066 " var v = %_GetFromCache(0, keys[i]);"
16067 " if (v !== values[i])"
16068 " return 'Wrong value for ' + "
16069 " keys[i] + ': ' + v + ' vs. ' + values[i];"
16070 " };"
16071 " return 'PASSED';"
16072 "})()";
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000016073 HEAP->ClearJSFunctionResultCaches();
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000016074 ExpectString(code, "PASSED");
16075}
16076
16077
16078THREADED_TEST(TestEviction) {
16079 i::FLAG_allow_natives_syntax = true;
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000016080 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016081 v8::HandleScope scope(context->GetIsolate());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000016082
16083 const char* code =
16084 "(function() {"
16085 " for (var i = 0; i < 2*16; i++) {"
16086 " %_GetFromCache(0, 'a' + i);"
16087 " };"
16088 " return 'PASSED';"
16089 "})()";
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000016090 HEAP->ClearJSFunctionResultCaches();
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000016091 ExpectString(code, "PASSED");
16092}
lrn@chromium.org32d961d2010-06-30 09:09:34 +000016093
16094
16095THREADED_TEST(TwoByteStringInAsciiCons) {
16096 // See Chromium issue 47824.
lrn@chromium.org32d961d2010-06-30 09:09:34 +000016097 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016098 v8::HandleScope scope(context->GetIsolate());
16099
lrn@chromium.org32d961d2010-06-30 09:09:34 +000016100 const char* init_code =
16101 "var str1 = 'abelspendabel';"
16102 "var str2 = str1 + str1 + str1;"
16103 "str2;";
16104 Local<Value> result = CompileRun(init_code);
16105
ricow@chromium.orgddd545c2011-08-24 12:02:41 +000016106 Local<Value> indexof = CompileRun("str2.indexOf('els')");
16107 Local<Value> lastindexof = CompileRun("str2.lastIndexOf('dab')");
16108
lrn@chromium.org32d961d2010-06-30 09:09:34 +000016109 CHECK(result->IsString());
16110 i::Handle<i::String> string = v8::Utils::OpenHandle(String::Cast(*result));
16111 int length = string->length();
ulan@chromium.org8e8d8822012-11-23 14:36:46 +000016112 CHECK(string->IsOneByteRepresentation());
lrn@chromium.org32d961d2010-06-30 09:09:34 +000016113
16114 FlattenString(string);
16115 i::Handle<i::String> flat_string = FlattenGetString(string);
16116
ulan@chromium.org8e8d8822012-11-23 14:36:46 +000016117 CHECK(string->IsOneByteRepresentation());
16118 CHECK(flat_string->IsOneByteRepresentation());
lrn@chromium.org32d961d2010-06-30 09:09:34 +000016119
16120 // Create external resource.
16121 uint16_t* uc16_buffer = new uint16_t[length + 1];
16122
16123 i::String::WriteToFlat(*flat_string, uc16_buffer, 0, length);
16124 uc16_buffer[length] = 0;
16125
16126 TestResource resource(uc16_buffer);
16127
16128 flat_string->MakeExternal(&resource);
16129
16130 CHECK(flat_string->IsTwoByteRepresentation());
16131
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +000016132 // If the cons string has been short-circuited, skip the following checks.
16133 if (!string.is_identical_to(flat_string)) {
16134 // At this point, we should have a Cons string which is flat and ASCII,
16135 // with a first half that is a two-byte string (although it only contains
16136 // ASCII characters). This is a valid sequence of steps, and it can happen
16137 // in real pages.
16138 CHECK(string->IsOneByteRepresentation());
16139 i::ConsString* cons = i::ConsString::cast(*string);
16140 CHECK_EQ(0, cons->second()->length());
16141 CHECK(cons->first()->IsTwoByteRepresentation());
16142 }
lrn@chromium.org32d961d2010-06-30 09:09:34 +000016143
16144 // Check that some string operations work.
16145
16146 // Atom RegExp.
16147 Local<Value> reresult = CompileRun("str2.match(/abel/g).length;");
16148 CHECK_EQ(6, reresult->Int32Value());
16149
16150 // Nonatom RegExp.
16151 reresult = CompileRun("str2.match(/abe./g).length;");
16152 CHECK_EQ(6, reresult->Int32Value());
16153
16154 reresult = CompileRun("str2.search(/bel/g);");
16155 CHECK_EQ(1, reresult->Int32Value());
16156
16157 reresult = CompileRun("str2.search(/be./g);");
16158 CHECK_EQ(1, reresult->Int32Value());
16159
16160 ExpectTrue("/bel/g.test(str2);");
16161
16162 ExpectTrue("/be./g.test(str2);");
16163
16164 reresult = CompileRun("/bel/g.exec(str2);");
16165 CHECK(!reresult->IsNull());
16166
16167 reresult = CompileRun("/be./g.exec(str2);");
16168 CHECK(!reresult->IsNull());
16169
16170 ExpectString("str2.substring(2, 10);", "elspenda");
16171
16172 ExpectString("str2.substring(2, 20);", "elspendabelabelspe");
16173
16174 ExpectString("str2.charAt(2);", "e");
16175
ricow@chromium.orgddd545c2011-08-24 12:02:41 +000016176 ExpectObject("str2.indexOf('els');", indexof);
16177
16178 ExpectObject("str2.lastIndexOf('dab');", lastindexof);
16179
lrn@chromium.org32d961d2010-06-30 09:09:34 +000016180 reresult = CompileRun("str2.charCodeAt(2);");
16181 CHECK_EQ(static_cast<int32_t>('e'), reresult->Int32Value());
16182}
ager@chromium.orgea4f62e2010-08-16 16:28:43 +000016183
16184
16185// Failed access check callback that performs a GC on each invocation.
16186void FailedAccessCheckCallbackGC(Local<v8::Object> target,
16187 v8::AccessType type,
16188 Local<v8::Value> data) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000016189 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.orgea4f62e2010-08-16 16:28:43 +000016190}
16191
16192
16193TEST(GCInFailedAccessCheckCallback) {
16194 // Install a failed access check callback that performs a GC on each
16195 // invocation. Then force the callback to be called from va
16196
16197 v8::V8::Initialize();
16198 v8::V8::SetFailedAccessCheckCallbackFunction(&FailedAccessCheckCallbackGC);
16199
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016200 v8::HandleScope scope(v8::Isolate::GetCurrent());
ager@chromium.orgea4f62e2010-08-16 16:28:43 +000016201
16202 // Create an ObjectTemplate for global objects and install access
16203 // check callbacks that will block access.
16204 v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
16205 global_template->SetAccessCheckCallbacks(NamedGetAccessBlocker,
16206 IndexedGetAccessBlocker,
16207 v8::Handle<v8::Value>(),
16208 false);
16209
16210 // Create a context and set an x property on it's global object.
16211 LocalContext context0(NULL, global_template);
16212 context0->Global()->Set(v8_str("x"), v8_num(42));
16213 v8::Handle<v8::Object> global0 = context0->Global();
16214
16215 // Create a context with a different security token so that the
16216 // failed access check callback will be called on each access.
16217 LocalContext context1(NULL, global_template);
16218 context1->Global()->Set(v8_str("other"), global0);
16219
16220 // Get property with failed access check.
16221 ExpectUndefined("other.x");
16222
16223 // Get element with failed access check.
16224 ExpectUndefined("other[0]");
16225
16226 // Set property with failed access check.
16227 v8::Handle<v8::Value> result = CompileRun("other.x = new Object()");
16228 CHECK(result->IsObject());
16229
16230 // Set element with failed access check.
16231 result = CompileRun("other[0] = new Object()");
16232 CHECK(result->IsObject());
16233
16234 // Get property attribute with failed access check.
16235 ExpectFalse("\'x\' in other");
16236
16237 // Get property attribute for element with failed access check.
16238 ExpectFalse("0 in other");
16239
16240 // Delete property.
16241 ExpectFalse("delete other.x");
16242
16243 // Delete element.
16244 CHECK_EQ(false, global0->Delete(0));
16245
16246 // DefineAccessor.
16247 CHECK_EQ(false,
16248 global0->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("x")));
16249
16250 // Define JavaScript accessor.
16251 ExpectUndefined("Object.prototype.__defineGetter__.call("
16252 " other, \'x\', function() { return 42; })");
16253
16254 // LookupAccessor.
16255 ExpectUndefined("Object.prototype.__lookupGetter__.call("
16256 " other, \'x\')");
16257
16258 // HasLocalElement.
16259 ExpectFalse("Object.prototype.hasOwnProperty.call(other, \'0\')");
16260
16261 CHECK_EQ(false, global0->HasRealIndexedProperty(0));
16262 CHECK_EQ(false, global0->HasRealNamedProperty(v8_str("x")));
16263 CHECK_EQ(false, global0->HasRealNamedCallbackProperty(v8_str("x")));
16264
16265 // Reset the failed access check callback so it does not influence
16266 // the other tests.
16267 v8::V8::SetFailedAccessCheckCallbackFunction(NULL);
16268}
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000016269
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000016270TEST(DefaultIsolateGetCurrent) {
16271 CHECK(v8::Isolate::GetCurrent() != NULL);
16272 v8::Isolate* isolate = v8::Isolate::GetCurrent();
16273 CHECK(reinterpret_cast<i::Isolate*>(isolate)->IsDefaultIsolate());
16274 printf("*** %s\n", "DefaultIsolateGetCurrent success");
16275}
16276
16277TEST(IsolateNewDispose) {
16278 v8::Isolate* current_isolate = v8::Isolate::GetCurrent();
16279 v8::Isolate* isolate = v8::Isolate::New();
16280 CHECK(isolate != NULL);
16281 CHECK(!reinterpret_cast<i::Isolate*>(isolate)->IsDefaultIsolate());
16282 CHECK(current_isolate != isolate);
16283 CHECK(current_isolate == v8::Isolate::GetCurrent());
16284
16285 v8::V8::SetFatalErrorHandler(StoringErrorCallback);
16286 last_location = last_message = NULL;
16287 isolate->Dispose();
16288 CHECK_EQ(last_location, NULL);
16289 CHECK_EQ(last_message, NULL);
16290}
16291
16292TEST(IsolateEnterExitDefault) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000016293 v8::Isolate* current_isolate = v8::Isolate::GetCurrent();
16294 CHECK(current_isolate != NULL); // Default isolate.
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016295 v8::HandleScope scope(current_isolate);
16296 LocalContext context;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000016297 ExpectString("'hello'", "hello");
16298 current_isolate->Enter();
16299 ExpectString("'still working'", "still working");
16300 current_isolate->Exit();
16301 ExpectString("'still working 2'", "still working 2");
16302 current_isolate->Exit();
16303 // Default isolate is always, well, 'default current'.
16304 CHECK_EQ(v8::Isolate::GetCurrent(), current_isolate);
16305 // Still working since default isolate is auto-entering any thread
16306 // that has no isolate and attempts to execute V8 APIs.
16307 ExpectString("'still working 3'", "still working 3");
16308}
16309
16310TEST(DisposeDefaultIsolate) {
16311 v8::V8::SetFatalErrorHandler(StoringErrorCallback);
16312
16313 // Run some V8 code to trigger default isolate to become 'current'.
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016314 v8::HandleScope scope(v8::Isolate::GetCurrent());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000016315 LocalContext context;
16316 ExpectString("'run some V8'", "run some V8");
16317
16318 v8::Isolate* isolate = v8::Isolate::GetCurrent();
16319 CHECK(reinterpret_cast<i::Isolate*>(isolate)->IsDefaultIsolate());
16320 last_location = last_message = NULL;
16321 isolate->Dispose();
16322 // It is not possible to dispose default isolate via Isolate API.
16323 CHECK_NE(last_location, NULL);
16324 CHECK_NE(last_message, NULL);
16325}
16326
16327TEST(RunDefaultAndAnotherIsolate) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016328 v8::HandleScope scope(v8::Isolate::GetCurrent());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000016329 LocalContext context;
16330
16331 // Enter new isolate.
16332 v8::Isolate* isolate = v8::Isolate::New();
16333 CHECK(isolate);
16334 isolate->Enter();
16335 { // Need this block because subsequent Exit() will deallocate Heap,
16336 // so we need all scope objects to be deconstructed when it happens.
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016337 v8::HandleScope scope_new(isolate);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000016338 LocalContext context_new;
16339
16340 // Run something in new isolate.
16341 CompileRun("var foo = 153;");
16342 ExpectTrue("function f() { return foo == 153; }; f()");
16343 }
16344 isolate->Exit();
16345
16346 // This runs automatically in default isolate.
16347 // Variables in another isolate should be not available.
16348 ExpectTrue("function f() {"
16349 " try {"
16350 " foo;"
16351 " return false;"
16352 " } catch(e) {"
16353 " return true;"
16354 " }"
16355 "};"
16356 "var bar = 371;"
16357 "f()");
16358
16359 v8::V8::SetFatalErrorHandler(StoringErrorCallback);
16360 last_location = last_message = NULL;
16361 isolate->Dispose();
16362 CHECK_EQ(last_location, NULL);
16363 CHECK_EQ(last_message, NULL);
16364
16365 // Check that default isolate still runs.
16366 ExpectTrue("function f() { return bar == 371; }; f()");
16367}
16368
16369TEST(DisposeIsolateWhenInUse) {
16370 v8::Isolate* isolate = v8::Isolate::New();
16371 CHECK(isolate);
16372 isolate->Enter();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016373 v8::HandleScope scope(isolate);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000016374 LocalContext context;
16375 // Run something in this isolate.
16376 ExpectTrue("true");
16377 v8::V8::SetFatalErrorHandler(StoringErrorCallback);
16378 last_location = last_message = NULL;
16379 // Still entered, should fail.
16380 isolate->Dispose();
16381 CHECK_NE(last_location, NULL);
16382 CHECK_NE(last_message, NULL);
16383}
16384
16385TEST(RunTwoIsolatesOnSingleThread) {
16386 // Run isolate 1.
16387 v8::Isolate* isolate1 = v8::Isolate::New();
16388 isolate1->Enter();
16389 v8::Persistent<v8::Context> context1 = v8::Context::New();
16390
16391 {
16392 v8::Context::Scope cscope(context1);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016393 v8::HandleScope scope(isolate1);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000016394 // Run something in new isolate.
16395 CompileRun("var foo = 'isolate 1';");
16396 ExpectString("function f() { return foo; }; f()", "isolate 1");
16397 }
16398
16399 // Run isolate 2.
16400 v8::Isolate* isolate2 = v8::Isolate::New();
16401 v8::Persistent<v8::Context> context2;
16402
16403 {
16404 v8::Isolate::Scope iscope(isolate2);
16405 context2 = v8::Context::New();
16406 v8::Context::Scope cscope(context2);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016407 v8::HandleScope scope(isolate2);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000016408
16409 // Run something in new isolate.
16410 CompileRun("var foo = 'isolate 2';");
16411 ExpectString("function f() { return foo; }; f()", "isolate 2");
16412 }
16413
16414 {
16415 v8::Context::Scope cscope(context1);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016416 v8::HandleScope scope(isolate1);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000016417 // Now again in isolate 1
16418 ExpectString("function f() { return foo; }; f()", "isolate 1");
16419 }
16420
16421 isolate1->Exit();
16422
16423 // Run some stuff in default isolate.
16424 v8::Persistent<v8::Context> context_default = v8::Context::New();
16425
16426 {
16427 v8::Context::Scope cscope(context_default);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016428 v8::HandleScope scope(v8::Isolate::GetCurrent());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000016429 // Variables in other isolates should be not available, verify there
16430 // is an exception.
16431 ExpectTrue("function f() {"
16432 " try {"
16433 " foo;"
16434 " return false;"
16435 " } catch(e) {"
16436 " return true;"
16437 " }"
16438 "};"
16439 "var isDefaultIsolate = true;"
16440 "f()");
16441 }
16442
16443 isolate1->Enter();
16444
16445 {
16446 v8::Isolate::Scope iscope(isolate2);
16447 v8::Context::Scope cscope(context2);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016448 v8::HandleScope scope(v8::Isolate::GetCurrent());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000016449 ExpectString("function f() { return foo; }; f()", "isolate 2");
16450 }
16451
16452 {
16453 v8::Context::Scope cscope(context1);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016454 v8::HandleScope scope(v8::Isolate::GetCurrent());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000016455 ExpectString("function f() { return foo; }; f()", "isolate 1");
16456 }
16457
16458 {
16459 v8::Isolate::Scope iscope(isolate2);
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000016460 context2.Dispose(context2->GetIsolate());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000016461 }
16462
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000016463 context1.Dispose(context1->GetIsolate());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000016464 isolate1->Exit();
16465
16466 v8::V8::SetFatalErrorHandler(StoringErrorCallback);
16467 last_location = last_message = NULL;
16468
16469 isolate1->Dispose();
16470 CHECK_EQ(last_location, NULL);
16471 CHECK_EQ(last_message, NULL);
16472
16473 isolate2->Dispose();
16474 CHECK_EQ(last_location, NULL);
16475 CHECK_EQ(last_message, NULL);
16476
16477 // Check that default isolate still runs.
16478 {
16479 v8::Context::Scope cscope(context_default);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016480 v8::HandleScope scope(v8::Isolate::GetCurrent());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000016481 ExpectTrue("function f() { return isDefaultIsolate; }; f()");
16482 }
16483}
16484
16485static int CalcFibonacci(v8::Isolate* isolate, int limit) {
16486 v8::Isolate::Scope isolate_scope(isolate);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016487 v8::HandleScope scope(isolate);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000016488 LocalContext context;
16489 i::ScopedVector<char> code(1024);
16490 i::OS::SNPrintF(code, "function fib(n) {"
16491 " if (n <= 2) return 1;"
16492 " return fib(n-1) + fib(n-2);"
16493 "}"
16494 "fib(%d)", limit);
16495 Local<Value> value = CompileRun(code.start());
16496 CHECK(value->IsNumber());
16497 return static_cast<int>(value->NumberValue());
16498}
16499
16500class IsolateThread : public v8::internal::Thread {
16501 public:
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000016502 IsolateThread(v8::Isolate* isolate, int fib_limit)
16503 : Thread("IsolateThread"),
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000016504 isolate_(isolate),
16505 fib_limit_(fib_limit),
16506 result_(0) { }
16507
16508 void Run() {
16509 result_ = CalcFibonacci(isolate_, fib_limit_);
16510 }
16511
16512 int result() { return result_; }
16513
16514 private:
16515 v8::Isolate* isolate_;
16516 int fib_limit_;
16517 int result_;
16518};
16519
16520TEST(MultipleIsolatesOnIndividualThreads) {
16521 v8::Isolate* isolate1 = v8::Isolate::New();
16522 v8::Isolate* isolate2 = v8::Isolate::New();
16523
16524 IsolateThread thread1(isolate1, 21);
16525 IsolateThread thread2(isolate2, 12);
16526
16527 // Compute some fibonacci numbers on 3 threads in 3 isolates.
16528 thread1.Start();
16529 thread2.Start();
16530
16531 int result1 = CalcFibonacci(v8::Isolate::GetCurrent(), 21);
16532 int result2 = CalcFibonacci(v8::Isolate::GetCurrent(), 12);
16533
16534 thread1.Join();
16535 thread2.Join();
16536
16537 // Compare results. The actual fibonacci numbers for 12 and 21 are taken
16538 // (I'm lazy!) from http://en.wikipedia.org/wiki/Fibonacci_number
16539 CHECK_EQ(result1, 10946);
16540 CHECK_EQ(result2, 144);
16541 CHECK_EQ(result1, thread1.result());
16542 CHECK_EQ(result2, thread2.result());
16543
16544 isolate1->Dispose();
16545 isolate2->Dispose();
16546}
16547
lrn@chromium.org1c092762011-05-09 09:42:16 +000016548TEST(IsolateDifferentContexts) {
16549 v8::Isolate* isolate = v8::Isolate::New();
16550 Persistent<v8::Context> context;
16551 {
16552 v8::Isolate::Scope isolate_scope(isolate);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016553 v8::HandleScope handle_scope(isolate);
lrn@chromium.org1c092762011-05-09 09:42:16 +000016554 context = v8::Context::New();
16555 v8::Context::Scope context_scope(context);
16556 Local<Value> v = CompileRun("2");
16557 CHECK(v->IsNumber());
16558 CHECK_EQ(2, static_cast<int>(v->NumberValue()));
16559 }
16560 {
16561 v8::Isolate::Scope isolate_scope(isolate);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016562 v8::HandleScope handle_scope(isolate);
lrn@chromium.org1c092762011-05-09 09:42:16 +000016563 context = v8::Context::New();
16564 v8::Context::Scope context_scope(context);
16565 Local<Value> v = CompileRun("22");
16566 CHECK(v->IsNumber());
16567 CHECK_EQ(22, static_cast<int>(v->NumberValue()));
16568 }
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +000016569 isolate->Dispose();
lrn@chromium.org1c092762011-05-09 09:42:16 +000016570}
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000016571
16572class InitDefaultIsolateThread : public v8::internal::Thread {
16573 public:
sgjesse@chromium.orge0599052011-03-25 07:34:35 +000016574 enum TestCase {
16575 IgnoreOOM,
16576 SetResourceConstraints,
16577 SetFatalHandler,
16578 SetCounterFunction,
16579 SetCreateHistogramFunction,
16580 SetAddHistogramSampleFunction
16581 };
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000016582
16583 explicit InitDefaultIsolateThread(TestCase testCase)
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000016584 : Thread("InitDefaultIsolateThread"),
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000016585 testCase_(testCase),
16586 result_(false) { }
16587
16588 void Run() {
16589 switch (testCase_) {
16590 case IgnoreOOM:
16591 v8::V8::IgnoreOutOfMemoryException();
16592 break;
16593
16594 case SetResourceConstraints: {
16595 static const int K = 1024;
16596 v8::ResourceConstraints constraints;
16597 constraints.set_max_young_space_size(256 * K);
16598 constraints.set_max_old_space_size(4 * K * K);
16599 v8::SetResourceConstraints(&constraints);
16600 break;
16601 }
16602
16603 case SetFatalHandler:
16604 v8::V8::SetFatalErrorHandler(NULL);
16605 break;
sgjesse@chromium.orge0599052011-03-25 07:34:35 +000016606
16607 case SetCounterFunction:
16608 v8::V8::SetCounterFunction(NULL);
16609 break;
16610
16611 case SetCreateHistogramFunction:
16612 v8::V8::SetCreateHistogramFunction(NULL);
16613 break;
16614
16615 case SetAddHistogramSampleFunction:
16616 v8::V8::SetAddHistogramSampleFunction(NULL);
16617 break;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000016618 }
16619 result_ = true;
16620 }
16621
16622 bool result() { return result_; }
16623
16624 private:
16625 TestCase testCase_;
16626 bool result_;
16627};
16628
16629
16630static void InitializeTestHelper(InitDefaultIsolateThread::TestCase testCase) {
16631 InitDefaultIsolateThread thread(testCase);
16632 thread.Start();
16633 thread.Join();
16634 CHECK_EQ(thread.result(), true);
16635}
16636
16637TEST(InitializeDefaultIsolateOnSecondaryThread1) {
16638 InitializeTestHelper(InitDefaultIsolateThread::IgnoreOOM);
16639}
16640
16641TEST(InitializeDefaultIsolateOnSecondaryThread2) {
16642 InitializeTestHelper(InitDefaultIsolateThread::SetResourceConstraints);
16643}
16644
16645TEST(InitializeDefaultIsolateOnSecondaryThread3) {
16646 InitializeTestHelper(InitDefaultIsolateThread::SetFatalHandler);
16647}
16648
sgjesse@chromium.orge0599052011-03-25 07:34:35 +000016649TEST(InitializeDefaultIsolateOnSecondaryThread4) {
16650 InitializeTestHelper(InitDefaultIsolateThread::SetCounterFunction);
16651}
16652
16653TEST(InitializeDefaultIsolateOnSecondaryThread5) {
16654 InitializeTestHelper(InitDefaultIsolateThread::SetCreateHistogramFunction);
16655}
16656
16657TEST(InitializeDefaultIsolateOnSecondaryThread6) {
16658 InitializeTestHelper(InitDefaultIsolateThread::SetAddHistogramSampleFunction);
16659}
16660
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000016661
16662TEST(StringCheckMultipleContexts) {
16663 const char* code =
16664 "(function() { return \"a\".charAt(0); })()";
16665
16666 {
16667 // Run the code twice in the first context to initialize the call IC.
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000016668 LocalContext context1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016669 v8::HandleScope scope(context1->GetIsolate());
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000016670 ExpectString(code, "a");
16671 ExpectString(code, "a");
16672 }
16673
16674 {
16675 // Change the String.prototype in the second context and check
16676 // that the right function gets called.
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000016677 LocalContext context2;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016678 v8::HandleScope scope(context2->GetIsolate());
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000016679 CompileRun("String.prototype.charAt = function() { return \"not a\"; }");
16680 ExpectString(code, "not a");
16681 }
16682}
16683
16684
16685TEST(NumberCheckMultipleContexts) {
16686 const char* code =
16687 "(function() { return (42).toString(); })()";
16688
16689 {
16690 // Run the code twice in the first context to initialize the call IC.
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000016691 LocalContext context1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016692 v8::HandleScope scope(context1->GetIsolate());
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000016693 ExpectString(code, "42");
16694 ExpectString(code, "42");
16695 }
16696
16697 {
16698 // Change the Number.prototype in the second context and check
16699 // that the right function gets called.
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000016700 LocalContext context2;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016701 v8::HandleScope scope(context2->GetIsolate());
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000016702 CompileRun("Number.prototype.toString = function() { return \"not 42\"; }");
16703 ExpectString(code, "not 42");
16704 }
16705}
16706
16707
16708TEST(BooleanCheckMultipleContexts) {
16709 const char* code =
16710 "(function() { return true.toString(); })()";
16711
16712 {
16713 // Run the code twice in the first context to initialize the call IC.
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000016714 LocalContext context1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016715 v8::HandleScope scope(context1->GetIsolate());
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000016716 ExpectString(code, "true");
16717 ExpectString(code, "true");
16718 }
16719
16720 {
16721 // Change the Boolean.prototype in the second context and check
16722 // that the right function gets called.
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000016723 LocalContext context2;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016724 v8::HandleScope scope(context2->GetIsolate());
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000016725 CompileRun("Boolean.prototype.toString = function() { return \"\"; }");
16726 ExpectString(code, "");
16727 }
16728}
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000016729
16730
16731TEST(DontDeleteCellLoadIC) {
16732 const char* function_code =
16733 "function readCell() { while (true) { return cell; } }";
16734
16735 {
16736 // Run the code twice in the first context to initialize the load
16737 // IC for a don't delete cell.
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000016738 LocalContext context1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016739 v8::HandleScope scope(context1->GetIsolate());
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000016740 CompileRun("var cell = \"first\";");
16741 ExpectBoolean("delete cell", false);
16742 CompileRun(function_code);
16743 ExpectString("readCell()", "first");
16744 ExpectString("readCell()", "first");
16745 }
16746
16747 {
16748 // Use a deletable cell in the second context.
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000016749 LocalContext context2;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016750 v8::HandleScope scope(context2->GetIsolate());
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000016751 CompileRun("cell = \"second\";");
16752 CompileRun(function_code);
16753 ExpectString("readCell()", "second");
16754 ExpectBoolean("delete cell", true);
16755 ExpectString("(function() {"
16756 " try {"
16757 " return readCell();"
16758 " } catch(e) {"
16759 " return e.toString();"
16760 " }"
16761 "})()",
16762 "ReferenceError: cell is not defined");
16763 CompileRun("cell = \"new_second\";");
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000016764 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000016765 ExpectString("readCell()", "new_second");
16766 ExpectString("readCell()", "new_second");
16767 }
16768}
16769
16770
16771TEST(DontDeleteCellLoadICForceDelete) {
16772 const char* function_code =
16773 "function readCell() { while (true) { return cell; } }";
16774
16775 // Run the code twice to initialize the load IC for a don't delete
16776 // cell.
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000016777 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016778 v8::HandleScope scope(context->GetIsolate());
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000016779 CompileRun("var cell = \"value\";");
16780 ExpectBoolean("delete cell", false);
16781 CompileRun(function_code);
16782 ExpectString("readCell()", "value");
16783 ExpectString("readCell()", "value");
16784
16785 // Delete the cell using the API and check the inlined code works
16786 // correctly.
16787 CHECK(context->Global()->ForceDelete(v8_str("cell")));
16788 ExpectString("(function() {"
16789 " try {"
16790 " return readCell();"
16791 " } catch(e) {"
16792 " return e.toString();"
16793 " }"
16794 "})()",
16795 "ReferenceError: cell is not defined");
16796}
16797
16798
16799TEST(DontDeleteCellLoadICAPI) {
16800 const char* function_code =
16801 "function readCell() { while (true) { return cell; } }";
16802
16803 // Run the code twice to initialize the load IC for a don't delete
16804 // cell created using the API.
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000016805 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016806 v8::HandleScope scope(context->GetIsolate());
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000016807 context->Global()->Set(v8_str("cell"), v8_str("value"), v8::DontDelete);
16808 ExpectBoolean("delete cell", false);
16809 CompileRun(function_code);
16810 ExpectString("readCell()", "value");
16811 ExpectString("readCell()", "value");
16812
16813 // Delete the cell using the API and check the inlined code works
16814 // correctly.
16815 CHECK(context->Global()->ForceDelete(v8_str("cell")));
16816 ExpectString("(function() {"
16817 " try {"
16818 " return readCell();"
16819 " } catch(e) {"
16820 " return e.toString();"
16821 " }"
16822 "})()",
16823 "ReferenceError: cell is not defined");
16824}
16825
16826
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000016827class Visitor42 : public v8::PersistentHandleVisitor {
16828 public:
16829 explicit Visitor42(v8::Persistent<v8::Object> object)
16830 : counter_(0), object_(object) { }
16831
16832 virtual void VisitPersistentHandle(Persistent<Value> value,
16833 uint16_t class_id) {
16834 if (class_id == 42) {
16835 CHECK(value->IsObject());
16836 v8::Persistent<v8::Object> visited =
16837 v8::Persistent<v8::Object>::Cast(value);
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000016838 CHECK_EQ(42, visited.WrapperClassId(v8::Isolate::GetCurrent()));
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000016839 CHECK_EQ(object_, visited);
16840 ++counter_;
16841 }
16842 }
16843
16844 int counter_;
16845 v8::Persistent<v8::Object> object_;
16846};
16847
16848
16849TEST(PersistentHandleVisitor) {
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000016850 LocalContext context;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000016851 v8::Isolate* isolate = context->GetIsolate();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016852 v8::HandleScope scope(isolate);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000016853 v8::Persistent<v8::Object> object =
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000016854 v8::Persistent<v8::Object>::New(isolate, v8::Object::New());
16855 CHECK_EQ(0, object.WrapperClassId(isolate));
16856 object.SetWrapperClassId(isolate, 42);
16857 CHECK_EQ(42, object.WrapperClassId(isolate));
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000016858
16859 Visitor42 visitor(object);
16860 v8::V8::VisitHandlesWithClassIds(&visitor);
16861 CHECK_EQ(1, visitor.counter_);
16862
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000016863 object.Dispose(isolate);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000016864}
16865
16866
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000016867TEST(WrapperClassId) {
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000016868 LocalContext context;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000016869 v8::Isolate* isolate = context->GetIsolate();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016870 v8::HandleScope scope(isolate);
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000016871 v8::Persistent<v8::Object> object =
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000016872 v8::Persistent<v8::Object>::New(isolate, v8::Object::New());
16873 CHECK_EQ(0, object.WrapperClassId(isolate));
16874 object.SetWrapperClassId(isolate, 65535);
16875 CHECK_EQ(65535, object.WrapperClassId(isolate));
16876 object.Dispose(isolate);
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000016877}
16878
16879
yangguo@chromium.org003650e2013-01-24 16:31:08 +000016880TEST(PersistentHandleInNewSpaceVisitor) {
yangguo@chromium.org003650e2013-01-24 16:31:08 +000016881 LocalContext context;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000016882 v8::Isolate* isolate = context->GetIsolate();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016883 v8::HandleScope scope(isolate);
yangguo@chromium.org003650e2013-01-24 16:31:08 +000016884 v8::Persistent<v8::Object> object1 =
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000016885 v8::Persistent<v8::Object>::New(isolate, v8::Object::New());
16886 CHECK_EQ(0, object1.WrapperClassId(isolate));
16887 object1.SetWrapperClassId(isolate, 42);
16888 CHECK_EQ(42, object1.WrapperClassId(isolate));
yangguo@chromium.org003650e2013-01-24 16:31:08 +000016889
16890 HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
16891
16892 v8::Persistent<v8::Object> object2 =
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000016893 v8::Persistent<v8::Object>::New(isolate, v8::Object::New());
16894 CHECK_EQ(0, object2.WrapperClassId(isolate));
16895 object2.SetWrapperClassId(isolate, 42);
16896 CHECK_EQ(42, object2.WrapperClassId(isolate));
yangguo@chromium.org003650e2013-01-24 16:31:08 +000016897
16898 Visitor42 visitor(object2);
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000016899 v8::V8::VisitHandlesForPartialDependence(isolate, &visitor);
yangguo@chromium.org003650e2013-01-24 16:31:08 +000016900 CHECK_EQ(1, visitor.counter_);
16901
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000016902 object1.Dispose(isolate);
16903 object2.Dispose(isolate);
yangguo@chromium.org003650e2013-01-24 16:31:08 +000016904}
16905
16906
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000016907TEST(RegExp) {
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000016908 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016909 v8::HandleScope scope(context->GetIsolate());
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000016910
16911 v8::Handle<v8::RegExp> re = v8::RegExp::New(v8_str("foo"), v8::RegExp::kNone);
16912 CHECK(re->IsRegExp());
16913 CHECK(re->GetSource()->Equals(v8_str("foo")));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000016914 CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000016915
16916 re = v8::RegExp::New(v8_str("bar"),
16917 static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
16918 v8::RegExp::kGlobal));
16919 CHECK(re->IsRegExp());
16920 CHECK(re->GetSource()->Equals(v8_str("bar")));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000016921 CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kGlobal,
16922 static_cast<int>(re->GetFlags()));
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000016923
16924 re = v8::RegExp::New(v8_str("baz"),
16925 static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
16926 v8::RegExp::kMultiline));
16927 CHECK(re->IsRegExp());
16928 CHECK(re->GetSource()->Equals(v8_str("baz")));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000016929 CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
16930 static_cast<int>(re->GetFlags()));
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000016931
16932 re = CompileRun("/quux/").As<v8::RegExp>();
16933 CHECK(re->IsRegExp());
16934 CHECK(re->GetSource()->Equals(v8_str("quux")));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000016935 CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000016936
16937 re = CompileRun("/quux/gm").As<v8::RegExp>();
16938 CHECK(re->IsRegExp());
16939 CHECK(re->GetSource()->Equals(v8_str("quux")));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000016940 CHECK_EQ(v8::RegExp::kGlobal | v8::RegExp::kMultiline,
16941 static_cast<int>(re->GetFlags()));
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000016942
16943 // Override the RegExp constructor and check the API constructor
16944 // still works.
16945 CompileRun("RegExp = function() {}");
16946
16947 re = v8::RegExp::New(v8_str("foobar"), v8::RegExp::kNone);
16948 CHECK(re->IsRegExp());
16949 CHECK(re->GetSource()->Equals(v8_str("foobar")));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000016950 CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000016951
16952 re = v8::RegExp::New(v8_str("foobarbaz"),
16953 static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
16954 v8::RegExp::kMultiline));
16955 CHECK(re->IsRegExp());
16956 CHECK(re->GetSource()->Equals(v8_str("foobarbaz")));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000016957 CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
16958 static_cast<int>(re->GetFlags()));
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000016959
16960 context->Global()->Set(v8_str("re"), re);
16961 ExpectTrue("re.test('FoobarbaZ')");
16962
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000016963 // RegExps are objects on which you can set properties.
16964 re->Set(v8_str("property"), v8::Integer::New(32));
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000016965 v8::Handle<v8::Value> value(CompileRun("re.property"));
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000016966 CHECK_EQ(32, value->Int32Value());
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000016967
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000016968 v8::TryCatch try_catch;
16969 re = v8::RegExp::New(v8_str("foo["), v8::RegExp::kNone);
16970 CHECK(re.IsEmpty());
16971 CHECK(try_catch.HasCaught());
16972 context->Global()->Set(v8_str("ex"), try_catch.Exception());
16973 ExpectTrue("ex instanceof SyntaxError");
16974}
16975
16976
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000016977THREADED_TEST(Equals) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000016978 LocalContext localContext;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016979 v8::HandleScope handleScope(localContext->GetIsolate());
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000016980
16981 v8::Handle<v8::Object> globalProxy = localContext->Global();
16982 v8::Handle<Value> global = globalProxy->GetPrototype();
16983
16984 CHECK(global->StrictEquals(global));
16985 CHECK(!global->StrictEquals(globalProxy));
16986 CHECK(!globalProxy->StrictEquals(global));
16987 CHECK(globalProxy->StrictEquals(globalProxy));
16988
16989 CHECK(global->Equals(global));
16990 CHECK(!global->Equals(globalProxy));
16991 CHECK(!globalProxy->Equals(global));
16992 CHECK(globalProxy->Equals(globalProxy));
16993}
16994
16995
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000016996static v8::Handle<v8::Value> Getter(v8::Local<v8::String> property,
16997 const v8::AccessorInfo& info ) {
16998 return v8_str("42!");
16999}
17000
17001
17002static v8::Handle<v8::Array> Enumerator(const v8::AccessorInfo& info) {
17003 v8::Handle<v8::Array> result = v8::Array::New();
17004 result->Set(0, v8_str("universalAnswer"));
17005 return result;
17006}
17007
17008
17009TEST(NamedEnumeratorAndForIn) {
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000017010 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017011 v8::HandleScope handle_scope(context->GetIsolate());
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000017012 v8::Context::Scope context_scope(context.local());
17013
17014 v8::Handle<v8::ObjectTemplate> tmpl = v8::ObjectTemplate::New();
17015 tmpl->SetNamedPropertyHandler(Getter, NULL, NULL, NULL, Enumerator);
17016 context->Global()->Set(v8_str("o"), tmpl->NewInstance());
17017 v8::Handle<v8::Array> result = v8::Handle<v8::Array>::Cast(CompileRun(
17018 "var result = []; for (var k in o) result.push(k); result"));
17019 CHECK_EQ(1, result->Length());
17020 CHECK_EQ(v8_str("universalAnswer"), result->Get(0));
17021}
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +000017022
17023
17024TEST(DefinePropertyPostDetach) {
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +000017025 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017026 v8::HandleScope scope(context->GetIsolate());
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +000017027 v8::Handle<v8::Object> proxy = context->Global();
17028 v8::Handle<v8::Function> define_property =
17029 CompileRun("(function() {"
17030 " Object.defineProperty("
17031 " this,"
17032 " 1,"
17033 " { configurable: true, enumerable: true, value: 3 });"
17034 "})").As<Function>();
17035 context->DetachGlobal();
17036 define_property->Call(proxy, 0, NULL);
17037}
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000017038
17039
17040static void InstallContextId(v8::Handle<Context> context, int id) {
17041 Context::Scope scope(context);
17042 CompileRun("Object.prototype").As<Object>()->
17043 Set(v8_str("context_id"), v8::Integer::New(id));
17044}
17045
17046
17047static void CheckContextId(v8::Handle<Object> object, int expected) {
17048 CHECK_EQ(expected, object->Get(v8_str("context_id"))->Int32Value());
17049}
17050
17051
17052THREADED_TEST(CreationContext) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017053 HandleScope handle_scope(v8::Isolate::GetCurrent());
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000017054 Persistent<Context> context1 = Context::New();
17055 InstallContextId(context1, 1);
17056 Persistent<Context> context2 = Context::New();
17057 InstallContextId(context2, 2);
17058 Persistent<Context> context3 = Context::New();
17059 InstallContextId(context3, 3);
17060
17061 Local<v8::FunctionTemplate> tmpl = v8::FunctionTemplate::New();
17062
17063 Local<Object> object1;
17064 Local<Function> func1;
17065 {
17066 Context::Scope scope(context1);
17067 object1 = Object::New();
17068 func1 = tmpl->GetFunction();
17069 }
17070
17071 Local<Object> object2;
17072 Local<Function> func2;
17073 {
17074 Context::Scope scope(context2);
17075 object2 = Object::New();
17076 func2 = tmpl->GetFunction();
17077 }
17078
17079 Local<Object> instance1;
17080 Local<Object> instance2;
17081
17082 {
17083 Context::Scope scope(context3);
17084 instance1 = func1->NewInstance();
17085 instance2 = func2->NewInstance();
17086 }
17087
17088 CHECK(object1->CreationContext() == context1);
17089 CheckContextId(object1, 1);
17090 CHECK(func1->CreationContext() == context1);
17091 CheckContextId(func1, 1);
17092 CHECK(instance1->CreationContext() == context1);
17093 CheckContextId(instance1, 1);
17094 CHECK(object2->CreationContext() == context2);
17095 CheckContextId(object2, 2);
17096 CHECK(func2->CreationContext() == context2);
17097 CheckContextId(func2, 2);
17098 CHECK(instance2->CreationContext() == context2);
17099 CheckContextId(instance2, 2);
17100
17101 {
17102 Context::Scope scope(context1);
17103 CHECK(object1->CreationContext() == context1);
17104 CheckContextId(object1, 1);
17105 CHECK(func1->CreationContext() == context1);
17106 CheckContextId(func1, 1);
17107 CHECK(instance1->CreationContext() == context1);
17108 CheckContextId(instance1, 1);
17109 CHECK(object2->CreationContext() == context2);
17110 CheckContextId(object2, 2);
17111 CHECK(func2->CreationContext() == context2);
17112 CheckContextId(func2, 2);
17113 CHECK(instance2->CreationContext() == context2);
17114 CheckContextId(instance2, 2);
17115 }
17116
17117 {
17118 Context::Scope scope(context2);
17119 CHECK(object1->CreationContext() == context1);
17120 CheckContextId(object1, 1);
17121 CHECK(func1->CreationContext() == context1);
17122 CheckContextId(func1, 1);
17123 CHECK(instance1->CreationContext() == context1);
17124 CheckContextId(instance1, 1);
17125 CHECK(object2->CreationContext() == context2);
17126 CheckContextId(object2, 2);
17127 CHECK(func2->CreationContext() == context2);
17128 CheckContextId(func2, 2);
17129 CHECK(instance2->CreationContext() == context2);
17130 CheckContextId(instance2, 2);
17131 }
17132
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000017133 context1.Dispose(context1->GetIsolate());
17134 context2.Dispose(context2->GetIsolate());
17135 context3.Dispose(context3->GetIsolate());
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000017136}
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000017137
17138
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +000017139THREADED_TEST(CreationContextOfJsFunction) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017140 HandleScope handle_scope(v8::Isolate::GetCurrent());
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +000017141 Persistent<Context> context = Context::New();
17142 InstallContextId(context, 1);
17143
17144 Local<Object> function;
17145 {
17146 Context::Scope scope(context);
17147 function = CompileRun("function foo() {}; foo").As<Object>();
17148 }
17149
17150 CHECK(function->CreationContext() == context);
17151 CheckContextId(function, 1);
17152
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000017153 context.Dispose(context->GetIsolate());
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +000017154}
17155
17156
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000017157Handle<Value> HasOwnPropertyIndexedPropertyGetter(uint32_t index,
17158 const AccessorInfo& info) {
17159 if (index == 42) return v8_str("yes");
17160 return Handle<v8::Integer>();
17161}
17162
17163
17164Handle<Value> HasOwnPropertyNamedPropertyGetter(Local<String> property,
17165 const AccessorInfo& info) {
17166 if (property->Equals(v8_str("foo"))) return v8_str("yes");
17167 return Handle<Value>();
17168}
17169
17170
17171Handle<v8::Integer> HasOwnPropertyIndexedPropertyQuery(
17172 uint32_t index, const AccessorInfo& info) {
17173 if (index == 42) return v8_num(1).As<v8::Integer>();
17174 return Handle<v8::Integer>();
17175}
17176
17177
17178Handle<v8::Integer> HasOwnPropertyNamedPropertyQuery(
17179 Local<String> property, const AccessorInfo& info) {
17180 if (property->Equals(v8_str("foo"))) return v8_num(1).As<v8::Integer>();
17181 return Handle<v8::Integer>();
17182}
17183
17184
17185Handle<v8::Integer> HasOwnPropertyNamedPropertyQuery2(
17186 Local<String> property, const AccessorInfo& info) {
17187 if (property->Equals(v8_str("bar"))) return v8_num(1).As<v8::Integer>();
17188 return Handle<v8::Integer>();
17189}
17190
17191
17192Handle<Value> HasOwnPropertyAccessorGetter(Local<String> property,
17193 const AccessorInfo& info) {
17194 return v8_str("yes");
17195}
17196
17197
17198TEST(HasOwnProperty) {
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000017199 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017200 v8::HandleScope scope(env->GetIsolate());
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000017201 { // Check normal properties and defined getters.
17202 Handle<Value> value = CompileRun(
17203 "function Foo() {"
17204 " this.foo = 11;"
17205 " this.__defineGetter__('baz', function() { return 1; });"
17206 "};"
17207 "function Bar() { "
17208 " this.bar = 13;"
17209 " this.__defineGetter__('bla', function() { return 2; });"
17210 "};"
17211 "Bar.prototype = new Foo();"
17212 "new Bar();");
17213 CHECK(value->IsObject());
17214 Handle<Object> object = value->ToObject();
17215 CHECK(object->Has(v8_str("foo")));
17216 CHECK(!object->HasOwnProperty(v8_str("foo")));
17217 CHECK(object->HasOwnProperty(v8_str("bar")));
17218 CHECK(object->Has(v8_str("baz")));
17219 CHECK(!object->HasOwnProperty(v8_str("baz")));
17220 CHECK(object->HasOwnProperty(v8_str("bla")));
17221 }
17222 { // Check named getter interceptors.
17223 Handle<ObjectTemplate> templ = ObjectTemplate::New();
17224 templ->SetNamedPropertyHandler(HasOwnPropertyNamedPropertyGetter);
17225 Handle<Object> instance = templ->NewInstance();
17226 CHECK(!instance->HasOwnProperty(v8_str("42")));
17227 CHECK(instance->HasOwnProperty(v8_str("foo")));
17228 CHECK(!instance->HasOwnProperty(v8_str("bar")));
17229 }
17230 { // Check indexed getter interceptors.
17231 Handle<ObjectTemplate> templ = ObjectTemplate::New();
17232 templ->SetIndexedPropertyHandler(HasOwnPropertyIndexedPropertyGetter);
17233 Handle<Object> instance = templ->NewInstance();
17234 CHECK(instance->HasOwnProperty(v8_str("42")));
17235 CHECK(!instance->HasOwnProperty(v8_str("43")));
17236 CHECK(!instance->HasOwnProperty(v8_str("foo")));
17237 }
17238 { // Check named query interceptors.
17239 Handle<ObjectTemplate> templ = ObjectTemplate::New();
17240 templ->SetNamedPropertyHandler(0, 0, HasOwnPropertyNamedPropertyQuery);
17241 Handle<Object> instance = templ->NewInstance();
17242 CHECK(instance->HasOwnProperty(v8_str("foo")));
17243 CHECK(!instance->HasOwnProperty(v8_str("bar")));
17244 }
17245 { // Check indexed query interceptors.
17246 Handle<ObjectTemplate> templ = ObjectTemplate::New();
17247 templ->SetIndexedPropertyHandler(0, 0, HasOwnPropertyIndexedPropertyQuery);
17248 Handle<Object> instance = templ->NewInstance();
17249 CHECK(instance->HasOwnProperty(v8_str("42")));
17250 CHECK(!instance->HasOwnProperty(v8_str("41")));
17251 }
17252 { // Check callbacks.
17253 Handle<ObjectTemplate> templ = ObjectTemplate::New();
17254 templ->SetAccessor(v8_str("foo"), HasOwnPropertyAccessorGetter);
17255 Handle<Object> instance = templ->NewInstance();
17256 CHECK(instance->HasOwnProperty(v8_str("foo")));
17257 CHECK(!instance->HasOwnProperty(v8_str("bar")));
17258 }
17259 { // Check that query wins on disagreement.
17260 Handle<ObjectTemplate> templ = ObjectTemplate::New();
17261 templ->SetNamedPropertyHandler(HasOwnPropertyNamedPropertyGetter,
17262 0,
17263 HasOwnPropertyNamedPropertyQuery2);
17264 Handle<Object> instance = templ->NewInstance();
17265 CHECK(!instance->HasOwnProperty(v8_str("foo")));
17266 CHECK(instance->HasOwnProperty(v8_str("bar")));
17267 }
17268}
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000017269
17270
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +000017271TEST(IndexedInterceptorWithStringProto) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017272 v8::HandleScope scope(v8::Isolate::GetCurrent());
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +000017273 Handle<ObjectTemplate> templ = ObjectTemplate::New();
17274 templ->SetIndexedPropertyHandler(NULL,
17275 NULL,
17276 HasOwnPropertyIndexedPropertyQuery);
17277 LocalContext context;
17278 context->Global()->Set(v8_str("obj"), templ->NewInstance());
17279 CompileRun("var s = new String('foobar'); obj.__proto__ = s;");
17280 // These should be intercepted.
17281 CHECK(CompileRun("42 in obj")->BooleanValue());
17282 CHECK(CompileRun("'42' in obj")->BooleanValue());
17283 // These should fall through to the String prototype.
17284 CHECK(CompileRun("0 in obj")->BooleanValue());
17285 CHECK(CompileRun("'0' in obj")->BooleanValue());
17286 // And these should both fail.
17287 CHECK(!CompileRun("32 in obj")->BooleanValue());
17288 CHECK(!CompileRun("'32' in obj")->BooleanValue());
17289}
17290
17291
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000017292void CheckCodeGenerationAllowed() {
17293 Handle<Value> result = CompileRun("eval('42')");
17294 CHECK_EQ(42, result->Int32Value());
17295 result = CompileRun("(function(e) { return e('42'); })(eval)");
17296 CHECK_EQ(42, result->Int32Value());
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000017297 result = CompileRun("var f = new Function('return 42'); f()");
17298 CHECK_EQ(42, result->Int32Value());
17299}
17300
17301
17302void CheckCodeGenerationDisallowed() {
17303 TryCatch try_catch;
17304
17305 Handle<Value> result = CompileRun("eval('42')");
17306 CHECK(result.IsEmpty());
17307 CHECK(try_catch.HasCaught());
17308 try_catch.Reset();
17309
17310 result = CompileRun("(function(e) { return e('42'); })(eval)");
17311 CHECK(result.IsEmpty());
17312 CHECK(try_catch.HasCaught());
17313 try_catch.Reset();
17314
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000017315 result = CompileRun("var f = new Function('return 42'); f()");
17316 CHECK(result.IsEmpty());
17317 CHECK(try_catch.HasCaught());
17318}
17319
17320
17321bool CodeGenerationAllowed(Local<Context> context) {
17322 ApiTestFuzzer::Fuzz();
17323 return true;
17324}
17325
17326
17327bool CodeGenerationDisallowed(Local<Context> context) {
17328 ApiTestFuzzer::Fuzz();
17329 return false;
17330}
17331
17332
17333THREADED_TEST(AllowCodeGenFromStrings) {
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000017334 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017335 v8::HandleScope scope(context->GetIsolate());
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000017336
ager@chromium.orgea91cc52011-05-23 06:06:11 +000017337 // eval and the Function constructor allowed by default.
jkummerow@chromium.org1145ef82012-02-02 16:21:15 +000017338 CHECK(context->IsCodeGenerationFromStringsAllowed());
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000017339 CheckCodeGenerationAllowed();
17340
ager@chromium.orgea91cc52011-05-23 06:06:11 +000017341 // Disallow eval and the Function constructor.
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000017342 context->AllowCodeGenerationFromStrings(false);
jkummerow@chromium.org1145ef82012-02-02 16:21:15 +000017343 CHECK(!context->IsCodeGenerationFromStringsAllowed());
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000017344 CheckCodeGenerationDisallowed();
17345
17346 // Allow again.
17347 context->AllowCodeGenerationFromStrings(true);
17348 CheckCodeGenerationAllowed();
17349
17350 // Disallow but setting a global callback that will allow the calls.
17351 context->AllowCodeGenerationFromStrings(false);
17352 V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationAllowed);
jkummerow@chromium.org1145ef82012-02-02 16:21:15 +000017353 CHECK(!context->IsCodeGenerationFromStringsAllowed());
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000017354 CheckCodeGenerationAllowed();
17355
17356 // Set a callback that disallows the code generation.
17357 V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationDisallowed);
jkummerow@chromium.org1145ef82012-02-02 16:21:15 +000017358 CHECK(!context->IsCodeGenerationFromStringsAllowed());
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000017359 CheckCodeGenerationDisallowed();
17360}
lrn@chromium.org1c092762011-05-09 09:42:16 +000017361
17362
ulan@chromium.org56c14af2012-09-20 12:51:09 +000017363TEST(SetErrorMessageForCodeGenFromStrings) {
ulan@chromium.org56c14af2012-09-20 12:51:09 +000017364 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017365 v8::HandleScope scope(context->GetIsolate());
ulan@chromium.org56c14af2012-09-20 12:51:09 +000017366 TryCatch try_catch;
17367
17368 Handle<String> message = v8_str("Message") ;
17369 Handle<String> expected_message = v8_str("Uncaught EvalError: Message");
17370 V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationDisallowed);
17371 context->AllowCodeGenerationFromStrings(false);
17372 context->SetErrorMessageForCodeGenerationFromStrings(message);
17373 Handle<Value> result = CompileRun("eval('42')");
17374 CHECK(result.IsEmpty());
17375 CHECK(try_catch.HasCaught());
17376 Handle<String> actual_message = try_catch.Message()->Get();
17377 CHECK(expected_message->Equals(actual_message));
17378}
17379
17380
lrn@chromium.org1c092762011-05-09 09:42:16 +000017381static v8::Handle<Value> NonObjectThis(const v8::Arguments& args) {
17382 return v8::Undefined();
17383}
17384
17385
17386THREADED_TEST(CallAPIFunctionOnNonObject) {
lrn@chromium.org1c092762011-05-09 09:42:16 +000017387 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017388 v8::HandleScope scope(context->GetIsolate());
lrn@chromium.org1c092762011-05-09 09:42:16 +000017389 Handle<FunctionTemplate> templ = v8::FunctionTemplate::New(NonObjectThis);
17390 Handle<Function> function = templ->GetFunction();
17391 context->Global()->Set(v8_str("f"), function);
17392 TryCatch try_catch;
17393 CompileRun("f.call(2)");
lrn@chromium.org1c092762011-05-09 09:42:16 +000017394}
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000017395
17396
17397// Regression test for issue 1470.
17398THREADED_TEST(ReadOnlyIndexedProperties) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017399 v8::HandleScope scope(v8::Isolate::GetCurrent());
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000017400 Local<ObjectTemplate> templ = ObjectTemplate::New();
17401
17402 LocalContext context;
17403 Local<v8::Object> obj = templ->NewInstance();
17404 context->Global()->Set(v8_str("obj"), obj);
17405 obj->Set(v8_str("1"), v8_str("DONT_CHANGE"), v8::ReadOnly);
17406 obj->Set(v8_str("1"), v8_str("foobar"));
17407 CHECK_EQ(v8_str("DONT_CHANGE"), obj->Get(v8_str("1")));
17408 obj->Set(v8_num(2), v8_str("DONT_CHANGE"), v8::ReadOnly);
17409 obj->Set(v8_num(2), v8_str("foobar"));
17410 CHECK_EQ(v8_str("DONT_CHANGE"), obj->Get(v8_num(2)));
17411
17412 // Test non-smi case.
17413 obj->Set(v8_str("2000000000"), v8_str("DONT_CHANGE"), v8::ReadOnly);
17414 obj->Set(v8_str("2000000000"), v8_str("foobar"));
17415 CHECK_EQ(v8_str("DONT_CHANGE"), obj->Get(v8_str("2000000000")));
17416}
ricow@chromium.org4f693d62011-07-04 14:01:31 +000017417
17418
17419THREADED_TEST(Regress1516) {
ricow@chromium.org4f693d62011-07-04 14:01:31 +000017420 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017421 v8::HandleScope scope(context->GetIsolate());
17422
17423 { v8::HandleScope temp_scope(context->GetIsolate());
ricow@chromium.org4f693d62011-07-04 14:01:31 +000017424 CompileRun("({'a': 0})");
17425 }
17426
17427 int elements;
17428 { i::MapCache* map_cache =
17429 i::MapCache::cast(i::Isolate::Current()->context()->map_cache());
17430 elements = map_cache->NumberOfElements();
17431 CHECK_LE(1, elements);
17432 }
17433
yangguo@chromium.orgd2899aa2012-06-21 11:16:20 +000017434 i::Isolate::Current()->heap()->CollectAllGarbage(
17435 i::Heap::kAbortIncrementalMarkingMask);
ricow@chromium.org4f693d62011-07-04 14:01:31 +000017436 { i::Object* raw_map_cache = i::Isolate::Current()->context()->map_cache();
17437 if (raw_map_cache != i::Isolate::Current()->heap()->undefined_value()) {
17438 i::MapCache* map_cache = i::MapCache::cast(raw_map_cache);
17439 CHECK_GT(elements, map_cache->NumberOfElements());
17440 }
17441 }
17442}
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000017443
17444
17445static bool BlockProtoNamedSecurityTestCallback(Local<v8::Object> global,
17446 Local<Value> name,
17447 v8::AccessType type,
17448 Local<Value> data) {
17449 // Only block read access to __proto__.
17450 if (type == v8::ACCESS_GET &&
17451 name->IsString() &&
17452 name->ToString()->Length() == 9 &&
17453 name->ToString()->Utf8Length() == 9) {
17454 char buffer[10];
17455 CHECK_EQ(10, name->ToString()->WriteUtf8(buffer));
17456 return strncmp(buffer, "__proto__", 9) != 0;
17457 }
17458
17459 return true;
17460}
17461
17462
17463THREADED_TEST(Regress93759) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017464 HandleScope scope(v8::Isolate::GetCurrent());
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000017465
17466 // Template for object with security check.
17467 Local<ObjectTemplate> no_proto_template = v8::ObjectTemplate::New();
17468 // We don't do indexing, so any callback can be used for that.
17469 no_proto_template->SetAccessCheckCallbacks(
17470 BlockProtoNamedSecurityTestCallback,
17471 IndexedSecurityTestCallback);
17472
17473 // Templates for objects with hidden prototypes and possibly security check.
17474 Local<FunctionTemplate> hidden_proto_template = v8::FunctionTemplate::New();
17475 hidden_proto_template->SetHiddenPrototype(true);
17476
17477 Local<FunctionTemplate> protected_hidden_proto_template =
17478 v8::FunctionTemplate::New();
17479 protected_hidden_proto_template->InstanceTemplate()->SetAccessCheckCallbacks(
17480 BlockProtoNamedSecurityTestCallback,
17481 IndexedSecurityTestCallback);
17482 protected_hidden_proto_template->SetHiddenPrototype(true);
17483
17484 // Context for "foreign" objects used in test.
17485 Persistent<Context> context = v8::Context::New();
17486 context->Enter();
17487
17488 // Plain object, no security check.
17489 Local<Object> simple_object = Object::New();
17490
17491 // Object with explicit security check.
17492 Local<Object> protected_object =
17493 no_proto_template->NewInstance();
17494
17495 // JSGlobalProxy object, always have security check.
17496 Local<Object> proxy_object =
17497 context->Global();
17498
17499 // Global object, the prototype of proxy_object. No security checks.
17500 Local<Object> global_object =
17501 proxy_object->GetPrototype()->ToObject();
17502
17503 // Hidden prototype without security check.
17504 Local<Object> hidden_prototype =
17505 hidden_proto_template->GetFunction()->NewInstance();
17506 Local<Object> object_with_hidden =
17507 Object::New();
17508 object_with_hidden->SetPrototype(hidden_prototype);
17509
17510 // Hidden prototype with security check on the hidden prototype.
17511 Local<Object> protected_hidden_prototype =
17512 protected_hidden_proto_template->GetFunction()->NewInstance();
17513 Local<Object> object_with_protected_hidden =
17514 Object::New();
17515 object_with_protected_hidden->SetPrototype(protected_hidden_prototype);
17516
17517 context->Exit();
17518
17519 // Template for object for second context. Values to test are put on it as
17520 // properties.
17521 Local<ObjectTemplate> global_template = ObjectTemplate::New();
17522 global_template->Set(v8_str("simple"), simple_object);
17523 global_template->Set(v8_str("protected"), protected_object);
17524 global_template->Set(v8_str("global"), global_object);
17525 global_template->Set(v8_str("proxy"), proxy_object);
17526 global_template->Set(v8_str("hidden"), object_with_hidden);
17527 global_template->Set(v8_str("phidden"), object_with_protected_hidden);
17528
17529 LocalContext context2(NULL, global_template);
17530
17531 Local<Value> result1 = CompileRun("Object.getPrototypeOf(simple)");
17532 CHECK(result1->Equals(simple_object->GetPrototype()));
17533
17534 Local<Value> result2 = CompileRun("Object.getPrototypeOf(protected)");
17535 CHECK(result2->Equals(Undefined()));
17536
17537 Local<Value> result3 = CompileRun("Object.getPrototypeOf(global)");
17538 CHECK(result3->Equals(global_object->GetPrototype()));
17539
17540 Local<Value> result4 = CompileRun("Object.getPrototypeOf(proxy)");
17541 CHECK(result4->Equals(Undefined()));
17542
17543 Local<Value> result5 = CompileRun("Object.getPrototypeOf(hidden)");
17544 CHECK(result5->Equals(
17545 object_with_hidden->GetPrototype()->ToObject()->GetPrototype()));
17546
17547 Local<Value> result6 = CompileRun("Object.getPrototypeOf(phidden)");
17548 CHECK(result6->Equals(Undefined()));
17549
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000017550 context.Dispose(context->GetIsolate());
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000017551}
17552
17553
jkummerow@chromium.org212d9642012-05-11 15:02:09 +000017554THREADED_TEST(Regress125988) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017555 v8::HandleScope scope(v8::Isolate::GetCurrent());
jkummerow@chromium.org212d9642012-05-11 15:02:09 +000017556 Handle<FunctionTemplate> intercept = FunctionTemplate::New();
17557 AddInterceptor(intercept, EmptyInterceptorGetter, EmptyInterceptorSetter);
17558 LocalContext env;
17559 env->Global()->Set(v8_str("Intercept"), intercept->GetFunction());
17560 CompileRun("var a = new Object();"
17561 "var b = new Intercept();"
17562 "var c = new Object();"
17563 "c.__proto__ = b;"
17564 "b.__proto__ = a;"
17565 "a.x = 23;"
17566 "for (var i = 0; i < 3; i++) c.x;");
17567 ExpectBoolean("c.hasOwnProperty('x')", false);
17568 ExpectInt32("c.x", 23);
17569 CompileRun("a.y = 42;"
17570 "for (var i = 0; i < 3; i++) c.x;");
17571 ExpectBoolean("c.hasOwnProperty('x')", false);
17572 ExpectInt32("c.x", 23);
17573 ExpectBoolean("c.hasOwnProperty('y')", false);
17574 ExpectInt32("c.y", 42);
17575}
17576
17577
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000017578static void TestReceiver(Local<Value> expected_result,
17579 Local<Value> expected_receiver,
17580 const char* code) {
17581 Local<Value> result = CompileRun(code);
17582 CHECK(result->IsObject());
17583 CHECK(expected_receiver->Equals(result->ToObject()->Get(1)));
17584 CHECK(expected_result->Equals(result->ToObject()->Get(0)));
17585}
17586
17587
17588THREADED_TEST(ForeignFunctionReceiver) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017589 HandleScope scope(v8::Isolate::GetCurrent());
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000017590
17591 // Create two contexts with different "id" properties ('i' and 'o').
17592 // Call a function both from its own context and from a the foreign
17593 // context, and see what "this" is bound to (returning both "this"
17594 // and "this.id" for comparison).
17595
17596 Persistent<Context> foreign_context = v8::Context::New();
17597 foreign_context->Enter();
17598 Local<Value> foreign_function =
17599 CompileRun("function func() { return { 0: this.id, "
17600 " 1: this, "
17601 " toString: function() { "
17602 " return this[0];"
17603 " }"
17604 " };"
17605 "}"
17606 "var id = 'i';"
17607 "func;");
17608 CHECK(foreign_function->IsFunction());
17609 foreign_context->Exit();
17610
17611 LocalContext context;
17612
17613 Local<String> password = v8_str("Password");
17614 // Don't get hit by security checks when accessing foreign_context's
17615 // global receiver (aka. global proxy).
17616 context->SetSecurityToken(password);
17617 foreign_context->SetSecurityToken(password);
17618
17619 Local<String> i = v8_str("i");
17620 Local<String> o = v8_str("o");
17621 Local<String> id = v8_str("id");
17622
17623 CompileRun("function ownfunc() { return { 0: this.id, "
17624 " 1: this, "
17625 " toString: function() { "
17626 " return this[0];"
17627 " }"
17628 " };"
17629 "}"
17630 "var id = 'o';"
17631 "ownfunc");
17632 context->Global()->Set(v8_str("func"), foreign_function);
17633
17634 // Sanity check the contexts.
17635 CHECK(i->Equals(foreign_context->Global()->Get(id)));
17636 CHECK(o->Equals(context->Global()->Get(id)));
17637
17638 // Checking local function's receiver.
17639 // Calling function using its call/apply methods.
17640 TestReceiver(o, context->Global(), "ownfunc.call()");
17641 TestReceiver(o, context->Global(), "ownfunc.apply()");
17642 // Making calls through built-in functions.
17643 TestReceiver(o, context->Global(), "[1].map(ownfunc)[0]");
17644 CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/,ownfunc)[1]")));
17645 CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/g,ownfunc)[1]")));
17646 CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/g,ownfunc)[3]")));
17647 // Calling with environment record as base.
17648 TestReceiver(o, context->Global(), "ownfunc()");
17649 // Calling with no base.
17650 TestReceiver(o, context->Global(), "(1,ownfunc)()");
17651
17652 // Checking foreign function return value.
17653 // Calling function using its call/apply methods.
17654 TestReceiver(i, foreign_context->Global(), "func.call()");
17655 TestReceiver(i, foreign_context->Global(), "func.apply()");
17656 // Calling function using another context's call/apply methods.
17657 TestReceiver(i, foreign_context->Global(),
17658 "Function.prototype.call.call(func)");
17659 TestReceiver(i, foreign_context->Global(),
17660 "Function.prototype.call.apply(func)");
17661 TestReceiver(i, foreign_context->Global(),
17662 "Function.prototype.apply.call(func)");
17663 TestReceiver(i, foreign_context->Global(),
17664 "Function.prototype.apply.apply(func)");
17665 // Making calls through built-in functions.
17666 TestReceiver(i, foreign_context->Global(), "[1].map(func)[0]");
17667 // ToString(func()) is func()[0], i.e., the returned this.id.
17668 CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/,func)[1]")));
17669 CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/g,func)[1]")));
17670 CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/g,func)[3]")));
17671
17672 // TODO(1547): Make the following also return "i".
17673 // Calling with environment record as base.
17674 TestReceiver(o, context->Global(), "func()");
17675 // Calling with no base.
17676 TestReceiver(o, context->Global(), "(1,func)()");
17677
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000017678 foreign_context.Dispose(foreign_context->GetIsolate());
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000017679}
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000017680
17681
17682uint8_t callback_fired = 0;
17683
17684
17685void CallCompletedCallback1() {
17686 i::OS::Print("Firing callback 1.\n");
17687 callback_fired ^= 1; // Toggle first bit.
17688}
17689
17690
17691void CallCompletedCallback2() {
17692 i::OS::Print("Firing callback 2.\n");
17693 callback_fired ^= 2; // Toggle second bit.
17694}
17695
17696
17697Handle<Value> RecursiveCall(const Arguments& args) {
17698 int32_t level = args[0]->Int32Value();
17699 if (level < 3) {
17700 level++;
17701 i::OS::Print("Entering recursion level %d.\n", level);
17702 char script[64];
17703 i::Vector<char> script_vector(script, sizeof(script));
17704 i::OS::SNPrintF(script_vector, "recursion(%d)", level);
17705 CompileRun(script_vector.start());
17706 i::OS::Print("Leaving recursion level %d.\n", level);
17707 CHECK_EQ(0, callback_fired);
17708 } else {
17709 i::OS::Print("Recursion ends.\n");
17710 CHECK_EQ(0, callback_fired);
17711 }
17712 return Undefined();
17713}
17714
17715
17716TEST(CallCompletedCallback) {
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000017717 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017718 v8::HandleScope scope(env->GetIsolate());
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000017719 v8::Handle<v8::FunctionTemplate> recursive_runtime =
17720 v8::FunctionTemplate::New(RecursiveCall);
17721 env->Global()->Set(v8_str("recursion"),
17722 recursive_runtime->GetFunction());
17723 // Adding the same callback a second time has no effect.
17724 v8::V8::AddCallCompletedCallback(CallCompletedCallback1);
17725 v8::V8::AddCallCompletedCallback(CallCompletedCallback1);
17726 v8::V8::AddCallCompletedCallback(CallCompletedCallback2);
17727 i::OS::Print("--- Script (1) ---\n");
17728 Local<Script> script =
17729 v8::Script::Compile(v8::String::New("recursion(0)"));
17730 script->Run();
17731 CHECK_EQ(3, callback_fired);
17732
17733 i::OS::Print("\n--- Script (2) ---\n");
17734 callback_fired = 0;
17735 v8::V8::RemoveCallCompletedCallback(CallCompletedCallback1);
17736 script->Run();
17737 CHECK_EQ(2, callback_fired);
17738
17739 i::OS::Print("\n--- Function ---\n");
17740 callback_fired = 0;
17741 Local<Function> recursive_function =
17742 Local<Function>::Cast(env->Global()->Get(v8_str("recursion")));
17743 v8::Handle<Value> args[] = { v8_num(0) };
17744 recursive_function->Call(env->Global(), 1, args);
17745 CHECK_EQ(2, callback_fired);
17746}
17747
17748
17749void CallCompletedCallbackNoException() {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017750 v8::HandleScope scope(v8::Isolate::GetCurrent());
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000017751 CompileRun("1+1;");
17752}
17753
17754
17755void CallCompletedCallbackException() {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017756 v8::HandleScope scope(v8::Isolate::GetCurrent());
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000017757 CompileRun("throw 'second exception';");
17758}
17759
17760
17761TEST(CallCompletedCallbackOneException) {
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000017762 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017763 v8::HandleScope scope(env->GetIsolate());
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000017764 v8::V8::AddCallCompletedCallback(CallCompletedCallbackNoException);
17765 CompileRun("throw 'exception';");
17766}
17767
17768
17769TEST(CallCompletedCallbackTwoExceptions) {
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000017770 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017771 v8::HandleScope scope(env->GetIsolate());
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000017772 v8::V8::AddCallCompletedCallback(CallCompletedCallbackException);
17773 CompileRun("throw 'first exception';");
17774}
ulan@chromium.org812308e2012-02-29 15:58:45 +000017775
17776
17777static int probes_counter = 0;
17778static int misses_counter = 0;
17779static int updates_counter = 0;
17780
17781
17782static int* LookupCounter(const char* name) {
17783 if (strcmp(name, "c:V8.MegamorphicStubCacheProbes") == 0) {
17784 return &probes_counter;
17785 } else if (strcmp(name, "c:V8.MegamorphicStubCacheMisses") == 0) {
17786 return &misses_counter;
17787 } else if (strcmp(name, "c:V8.MegamorphicStubCacheUpdates") == 0) {
17788 return &updates_counter;
17789 }
17790 return NULL;
17791}
17792
17793
17794static const char* kMegamorphicTestProgram =
17795 "function ClassA() { };"
17796 "function ClassB() { };"
17797 "ClassA.prototype.foo = function() { };"
17798 "ClassB.prototype.foo = function() { };"
17799 "function fooify(obj) { obj.foo(); };"
17800 "var a = new ClassA();"
17801 "var b = new ClassB();"
17802 "for (var i = 0; i < 10000; i++) {"
17803 " fooify(a);"
17804 " fooify(b);"
17805 "}";
17806
17807
17808static void StubCacheHelper(bool primary) {
17809 V8::SetCounterFunction(LookupCounter);
17810 USE(kMegamorphicTestProgram);
17811#ifdef DEBUG
17812 i::FLAG_native_code_counters = true;
17813 if (primary) {
17814 i::FLAG_test_primary_stub_cache = true;
17815 } else {
17816 i::FLAG_test_secondary_stub_cache = true;
17817 }
17818 i::FLAG_crankshaft = false;
ulan@chromium.org812308e2012-02-29 15:58:45 +000017819 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017820 v8::HandleScope scope(env->GetIsolate());
ulan@chromium.org812308e2012-02-29 15:58:45 +000017821 int initial_probes = probes_counter;
17822 int initial_misses = misses_counter;
17823 int initial_updates = updates_counter;
17824 CompileRun(kMegamorphicTestProgram);
17825 int probes = probes_counter - initial_probes;
17826 int misses = misses_counter - initial_misses;
17827 int updates = updates_counter - initial_updates;
17828 CHECK_LT(updates, 10);
17829 CHECK_LT(misses, 10);
17830 CHECK_GE(probes, 10000);
17831#endif
17832}
17833
17834
17835TEST(SecondaryStubCache) {
17836 StubCacheHelper(true);
17837}
17838
17839
17840TEST(PrimaryStubCache) {
17841 StubCacheHelper(false);
17842}
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000017843
17844
17845static int fatal_error_callback_counter = 0;
17846static void CountingErrorCallback(const char* location, const char* message) {
17847 printf("CountingErrorCallback(\"%s\", \"%s\")\n", location, message);
17848 fatal_error_callback_counter++;
17849}
17850
17851
17852TEST(StaticGetters) {
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000017853 LocalContext context;
17854 v8::Isolate* isolate = v8::Isolate::GetCurrent();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017855 v8::HandleScope scope(isolate);
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000017856 i::Handle<i::Object> undefined_value = FACTORY->undefined_value();
17857 CHECK(*v8::Utils::OpenHandle(*v8::Undefined()) == *undefined_value);
17858 CHECK(*v8::Utils::OpenHandle(*v8::Undefined(isolate)) == *undefined_value);
17859 i::Handle<i::Object> null_value = FACTORY->null_value();
17860 CHECK(*v8::Utils::OpenHandle(*v8::Null()) == *null_value);
17861 CHECK(*v8::Utils::OpenHandle(*v8::Null(isolate)) == *null_value);
17862 i::Handle<i::Object> true_value = FACTORY->true_value();
17863 CHECK(*v8::Utils::OpenHandle(*v8::True()) == *true_value);
17864 CHECK(*v8::Utils::OpenHandle(*v8::True(isolate)) == *true_value);
17865 i::Handle<i::Object> false_value = FACTORY->false_value();
17866 CHECK(*v8::Utils::OpenHandle(*v8::False()) == *false_value);
17867 CHECK(*v8::Utils::OpenHandle(*v8::False(isolate)) == *false_value);
17868
17869 // Test after-death behavior.
17870 CHECK(i::Internals::IsInitialized(isolate));
17871 CHECK_EQ(0, fatal_error_callback_counter);
17872 v8::V8::SetFatalErrorHandler(CountingErrorCallback);
17873 v8::Utils::ReportApiFailure("StaticGetters()", "Kill V8");
17874 i::Isolate::Current()->TearDown();
17875 CHECK(!i::Internals::IsInitialized(isolate));
17876 CHECK_EQ(1, fatal_error_callback_counter);
17877 CHECK(v8::Undefined().IsEmpty());
17878 CHECK_EQ(2, fatal_error_callback_counter);
17879 CHECK(v8::Undefined(isolate).IsEmpty());
17880 CHECK_EQ(3, fatal_error_callback_counter);
17881 CHECK(v8::Null().IsEmpty());
17882 CHECK_EQ(4, fatal_error_callback_counter);
17883 CHECK(v8::Null(isolate).IsEmpty());
17884 CHECK_EQ(5, fatal_error_callback_counter);
17885 CHECK(v8::True().IsEmpty());
17886 CHECK_EQ(6, fatal_error_callback_counter);
17887 CHECK(v8::True(isolate).IsEmpty());
17888 CHECK_EQ(7, fatal_error_callback_counter);
17889 CHECK(v8::False().IsEmpty());
17890 CHECK_EQ(8, fatal_error_callback_counter);
17891 CHECK(v8::False(isolate).IsEmpty());
17892 CHECK_EQ(9, fatal_error_callback_counter);
17893}
17894
17895
17896TEST(IsolateEmbedderData) {
17897 v8::Isolate* isolate = v8::Isolate::GetCurrent();
17898 CHECK_EQ(NULL, isolate->GetData());
17899 CHECK_EQ(NULL, ISOLATE->GetData());
17900 static void* data1 = reinterpret_cast<void*>(0xacce55ed);
17901 isolate->SetData(data1);
17902 CHECK_EQ(data1, isolate->GetData());
17903 CHECK_EQ(data1, ISOLATE->GetData());
17904 static void* data2 = reinterpret_cast<void*>(0xdecea5ed);
17905 ISOLATE->SetData(data2);
17906 CHECK_EQ(data2, isolate->GetData());
17907 CHECK_EQ(data2, ISOLATE->GetData());
17908 ISOLATE->TearDown();
17909 CHECK_EQ(data2, isolate->GetData());
17910 CHECK_EQ(data2, ISOLATE->GetData());
17911}
17912
17913
17914TEST(StringEmpty) {
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000017915 LocalContext context;
17916 v8::Isolate* isolate = v8::Isolate::GetCurrent();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017917 v8::HandleScope scope(isolate);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +000017918 i::Handle<i::Object> empty_string = FACTORY->empty_string();
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000017919 CHECK(*v8::Utils::OpenHandle(*v8::String::Empty()) == *empty_string);
17920 CHECK(*v8::Utils::OpenHandle(*v8::String::Empty(isolate)) == *empty_string);
17921
17922 // Test after-death behavior.
17923 CHECK(i::Internals::IsInitialized(isolate));
17924 CHECK_EQ(0, fatal_error_callback_counter);
17925 v8::V8::SetFatalErrorHandler(CountingErrorCallback);
17926 v8::Utils::ReportApiFailure("StringEmpty()", "Kill V8");
17927 i::Isolate::Current()->TearDown();
17928 CHECK(!i::Internals::IsInitialized(isolate));
17929 CHECK_EQ(1, fatal_error_callback_counter);
17930 CHECK(v8::String::Empty().IsEmpty());
17931 CHECK_EQ(2, fatal_error_callback_counter);
17932 CHECK(v8::String::Empty(isolate).IsEmpty());
17933 CHECK_EQ(3, fatal_error_callback_counter);
17934}
mmassi@chromium.org7028c052012-06-13 11:51:58 +000017935
17936
17937static int instance_checked_getter_count = 0;
17938static Handle<Value> InstanceCheckedGetter(Local<String> name,
17939 const AccessorInfo& info) {
17940 CHECK_EQ(name, v8_str("foo"));
17941 instance_checked_getter_count++;
17942 return v8_num(11);
17943}
17944
17945
17946static int instance_checked_setter_count = 0;
17947static void InstanceCheckedSetter(Local<String> name,
17948 Local<Value> value,
17949 const AccessorInfo& info) {
17950 CHECK_EQ(name, v8_str("foo"));
17951 CHECK_EQ(value, v8_num(23));
17952 instance_checked_setter_count++;
17953}
17954
17955
17956static void CheckInstanceCheckedResult(int getters,
17957 int setters,
17958 bool expects_callbacks,
17959 TryCatch* try_catch) {
17960 if (expects_callbacks) {
17961 CHECK(!try_catch->HasCaught());
17962 CHECK_EQ(getters, instance_checked_getter_count);
17963 CHECK_EQ(setters, instance_checked_setter_count);
17964 } else {
17965 CHECK(try_catch->HasCaught());
17966 CHECK_EQ(0, instance_checked_getter_count);
17967 CHECK_EQ(0, instance_checked_setter_count);
17968 }
17969 try_catch->Reset();
17970}
17971
17972
17973static void CheckInstanceCheckedAccessors(bool expects_callbacks) {
17974 instance_checked_getter_count = 0;
17975 instance_checked_setter_count = 0;
17976 TryCatch try_catch;
17977
17978 // Test path through generic runtime code.
17979 CompileRun("obj.foo");
17980 CheckInstanceCheckedResult(1, 0, expects_callbacks, &try_catch);
17981 CompileRun("obj.foo = 23");
17982 CheckInstanceCheckedResult(1, 1, expects_callbacks, &try_catch);
17983
17984 // Test path through generated LoadIC and StoredIC.
17985 CompileRun("function test_get(o) { o.foo; }"
17986 "test_get(obj);");
17987 CheckInstanceCheckedResult(2, 1, expects_callbacks, &try_catch);
17988 CompileRun("test_get(obj);");
17989 CheckInstanceCheckedResult(3, 1, expects_callbacks, &try_catch);
17990 CompileRun("test_get(obj);");
17991 CheckInstanceCheckedResult(4, 1, expects_callbacks, &try_catch);
17992 CompileRun("function test_set(o) { o.foo = 23; }"
17993 "test_set(obj);");
17994 CheckInstanceCheckedResult(4, 2, expects_callbacks, &try_catch);
17995 CompileRun("test_set(obj);");
17996 CheckInstanceCheckedResult(4, 3, expects_callbacks, &try_catch);
17997 CompileRun("test_set(obj);");
17998 CheckInstanceCheckedResult(4, 4, expects_callbacks, &try_catch);
17999
18000 // Test path through optimized code.
18001 CompileRun("%OptimizeFunctionOnNextCall(test_get);"
18002 "test_get(obj);");
18003 CheckInstanceCheckedResult(5, 4, expects_callbacks, &try_catch);
18004 CompileRun("%OptimizeFunctionOnNextCall(test_set);"
18005 "test_set(obj);");
18006 CheckInstanceCheckedResult(5, 5, expects_callbacks, &try_catch);
18007
18008 // Cleanup so that closures start out fresh in next check.
18009 CompileRun("%DeoptimizeFunction(test_get);"
18010 "%ClearFunctionTypeFeedback(test_get);"
18011 "%DeoptimizeFunction(test_set);"
18012 "%ClearFunctionTypeFeedback(test_set);");
18013}
18014
18015
18016THREADED_TEST(InstanceCheckOnInstanceAccessor) {
18017 v8::internal::FLAG_allow_natives_syntax = true;
mmassi@chromium.org7028c052012-06-13 11:51:58 +000018018 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018019 v8::HandleScope scope(context->GetIsolate());
mmassi@chromium.org7028c052012-06-13 11:51:58 +000018020
18021 Local<FunctionTemplate> templ = FunctionTemplate::New();
18022 Local<ObjectTemplate> inst = templ->InstanceTemplate();
18023 inst->SetAccessor(v8_str("foo"),
18024 InstanceCheckedGetter, InstanceCheckedSetter,
18025 Handle<Value>(),
18026 v8::DEFAULT,
18027 v8::None,
18028 v8::AccessorSignature::New(templ));
18029 context->Global()->Set(v8_str("f"), templ->GetFunction());
18030
18031 printf("Testing positive ...\n");
18032 CompileRun("var obj = new f();");
18033 CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
18034 CheckInstanceCheckedAccessors(true);
18035
18036 printf("Testing negative ...\n");
18037 CompileRun("var obj = {};"
18038 "obj.__proto__ = new f();");
18039 CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
18040 CheckInstanceCheckedAccessors(false);
18041}
18042
18043
18044THREADED_TEST(InstanceCheckOnInstanceAccessorWithInterceptor) {
18045 v8::internal::FLAG_allow_natives_syntax = true;
mmassi@chromium.org7028c052012-06-13 11:51:58 +000018046 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018047 v8::HandleScope scope(context->GetIsolate());
mmassi@chromium.org7028c052012-06-13 11:51:58 +000018048
18049 Local<FunctionTemplate> templ = FunctionTemplate::New();
18050 Local<ObjectTemplate> inst = templ->InstanceTemplate();
18051 AddInterceptor(templ, EmptyInterceptorGetter, EmptyInterceptorSetter);
18052 inst->SetAccessor(v8_str("foo"),
18053 InstanceCheckedGetter, InstanceCheckedSetter,
18054 Handle<Value>(),
18055 v8::DEFAULT,
18056 v8::None,
18057 v8::AccessorSignature::New(templ));
18058 context->Global()->Set(v8_str("f"), templ->GetFunction());
18059
18060 printf("Testing positive ...\n");
18061 CompileRun("var obj = new f();");
18062 CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
18063 CheckInstanceCheckedAccessors(true);
18064
18065 printf("Testing negative ...\n");
18066 CompileRun("var obj = {};"
18067 "obj.__proto__ = new f();");
18068 CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
18069 CheckInstanceCheckedAccessors(false);
18070}
18071
18072
18073THREADED_TEST(InstanceCheckOnPrototypeAccessor) {
18074 v8::internal::FLAG_allow_natives_syntax = true;
mmassi@chromium.org7028c052012-06-13 11:51:58 +000018075 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018076 v8::HandleScope scope(context->GetIsolate());
mmassi@chromium.org7028c052012-06-13 11:51:58 +000018077
18078 Local<FunctionTemplate> templ = FunctionTemplate::New();
18079 Local<ObjectTemplate> proto = templ->PrototypeTemplate();
18080 proto->SetAccessor(v8_str("foo"),
18081 InstanceCheckedGetter, InstanceCheckedSetter,
18082 Handle<Value>(),
18083 v8::DEFAULT,
18084 v8::None,
18085 v8::AccessorSignature::New(templ));
18086 context->Global()->Set(v8_str("f"), templ->GetFunction());
18087
18088 printf("Testing positive ...\n");
18089 CompileRun("var obj = new f();");
18090 CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
18091 CheckInstanceCheckedAccessors(true);
18092
18093 printf("Testing negative ...\n");
18094 CompileRun("var obj = {};"
18095 "obj.__proto__ = new f();");
18096 CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
18097 CheckInstanceCheckedAccessors(false);
18098
18099 printf("Testing positive with modified prototype chain ...\n");
18100 CompileRun("var obj = new f();"
18101 "var pro = {};"
18102 "pro.__proto__ = obj.__proto__;"
18103 "obj.__proto__ = pro;");
18104 CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
18105 CheckInstanceCheckedAccessors(true);
18106}
18107
18108
18109TEST(TryFinallyMessage) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +000018110 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018111 v8::HandleScope scope(context->GetIsolate());
mmassi@chromium.org7028c052012-06-13 11:51:58 +000018112 {
18113 // Test that the original error message is not lost if there is a
18114 // recursive call into Javascript is done in the finally block, e.g. to
18115 // initialize an IC. (crbug.com/129171)
18116 TryCatch try_catch;
18117 const char* trigger_ic =
18118 "try { \n"
18119 " throw new Error('test'); \n"
18120 "} finally { \n"
18121 " var x = 0; \n"
18122 " x++; \n" // Trigger an IC initialization here.
18123 "} \n";
18124 CompileRun(trigger_ic);
18125 CHECK(try_catch.HasCaught());
18126 Local<Message> message = try_catch.Message();
18127 CHECK(!message.IsEmpty());
18128 CHECK_EQ(2, message->GetLineNumber());
18129 }
18130
18131 {
18132 // Test that the original exception message is indeed overwritten if
18133 // a new error is thrown in the finally block.
18134 TryCatch try_catch;
18135 const char* throw_again =
18136 "try { \n"
18137 " throw new Error('test'); \n"
18138 "} finally { \n"
18139 " var x = 0; \n"
18140 " x++; \n"
18141 " throw new Error('again'); \n" // This is the new uncaught error.
18142 "} \n";
18143 CompileRun(throw_again);
18144 CHECK(try_catch.HasCaught());
18145 Local<Message> message = try_catch.Message();
18146 CHECK(!message.IsEmpty());
18147 CHECK_EQ(6, message->GetLineNumber());
18148 }
18149}
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000018150
18151
erik.corry@gmail.com88767242012-08-08 14:43:45 +000018152static void Helper137002(bool do_store,
18153 bool polymorphic,
18154 bool remove_accessor,
18155 bool interceptor) {
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000018156 LocalContext context;
18157 Local<ObjectTemplate> templ = ObjectTemplate::New();
erik.corry@gmail.com88767242012-08-08 14:43:45 +000018158 if (interceptor) {
18159 templ->SetNamedPropertyHandler(FooGetInterceptor, FooSetInterceptor);
18160 } else {
18161 templ->SetAccessor(v8_str("foo"),
18162 GetterWhichReturns42,
18163 SetterWhichSetsYOnThisTo23);
18164 }
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000018165 context->Global()->Set(v8_str("obj"), templ->NewInstance());
18166
18167 // Turn monomorphic on slow object with native accessor, then turn
18168 // polymorphic, finally optimize to create negative lookup and fail.
erik.corry@gmail.com88767242012-08-08 14:43:45 +000018169 CompileRun(do_store ?
18170 "function f(x) { x.foo = void 0; }" :
18171 "function f(x) { return x.foo; }");
18172 CompileRun("obj.y = void 0;");
18173 if (!interceptor) {
18174 CompileRun("%OptimizeObjectForAddingMultipleProperties(obj, 1);");
18175 }
18176 CompileRun("obj.__proto__ = null;"
18177 "f(obj); f(obj); f(obj);");
18178 if (polymorphic) {
18179 CompileRun("f({});");
18180 }
18181 CompileRun("obj.y = void 0;"
18182 "%OptimizeFunctionOnNextCall(f);");
18183 if (remove_accessor) {
18184 CompileRun("delete obj.foo;");
18185 }
18186 CompileRun("var result = f(obj);");
18187 if (do_store) {
18188 CompileRun("result = obj.y;");
18189 }
18190 if (remove_accessor && !interceptor) {
18191 CHECK(context->Global()->Get(v8_str("result"))->IsUndefined());
18192 } else {
18193 CHECK_EQ(do_store ? 23 : 42,
18194 context->Global()->Get(v8_str("result"))->Int32Value());
18195 }
18196}
18197
18198
18199THREADED_TEST(Regress137002a) {
18200 i::FLAG_allow_natives_syntax = true;
18201 i::FLAG_compilation_cache = false;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018202 v8::HandleScope scope(v8::Isolate::GetCurrent());
erik.corry@gmail.com88767242012-08-08 14:43:45 +000018203 for (int i = 0; i < 16; i++) {
18204 Helper137002(i & 8, i & 4, i & 2, i & 1);
18205 }
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000018206}
18207
18208
18209THREADED_TEST(Regress137002b) {
18210 i::FLAG_allow_natives_syntax = true;
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000018211 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018212 v8::HandleScope scope(context->GetIsolate());
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000018213 Local<ObjectTemplate> templ = ObjectTemplate::New();
18214 templ->SetAccessor(v8_str("foo"),
18215 GetterWhichReturns42,
18216 SetterWhichSetsYOnThisTo23);
18217 context->Global()->Set(v8_str("obj"), templ->NewInstance());
18218
18219 // Turn monomorphic on slow object with native accessor, then just
18220 // delete the property and fail.
erik.corry@gmail.com88767242012-08-08 14:43:45 +000018221 CompileRun("function load(x) { return x.foo; }"
18222 "function store(x) { x.foo = void 0; }"
18223 "function keyed_load(x, key) { return x[key]; }"
18224 // Second version of function has a different source (add void 0)
18225 // so that it does not share code with the first version. This
18226 // ensures that the ICs are monomorphic.
18227 "function load2(x) { void 0; return x.foo; }"
18228 "function store2(x) { void 0; x.foo = void 0; }"
18229 "function keyed_load2(x, key) { void 0; return x[key]; }"
18230
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000018231 "obj.y = void 0;"
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000018232 "obj.__proto__ = null;"
erik.corry@gmail.com88767242012-08-08 14:43:45 +000018233 "var subobj = {};"
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000018234 "subobj.y = void 0;"
erik.corry@gmail.com88767242012-08-08 14:43:45 +000018235 "subobj.__proto__ = obj;"
18236 "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
18237
18238 // Make the ICs monomorphic.
18239 "load(obj); load(obj);"
18240 "load2(subobj); load2(subobj);"
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000018241 "store(obj); store(obj);"
18242 "store2(subobj); store2(subobj);"
erik.corry@gmail.com88767242012-08-08 14:43:45 +000018243 "keyed_load(obj, 'foo'); keyed_load(obj, 'foo');"
18244 "keyed_load2(subobj, 'foo'); keyed_load2(subobj, 'foo');"
18245
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000018246 // Actually test the shiny new ICs and better not crash. This
18247 // serves as a regression test for issue 142088 as well.
18248 "load(obj);"
18249 "load2(subobj);"
18250 "store(obj);"
18251 "store2(subobj);"
18252 "keyed_load(obj, 'foo');"
18253 "keyed_load2(subobj, 'foo');"
18254
erik.corry@gmail.com88767242012-08-08 14:43:45 +000018255 // Delete the accessor. It better not be called any more now.
18256 "delete obj.foo;"
18257 "obj.y = void 0;"
18258 "subobj.y = void 0;"
18259
18260 "var load_result = load(obj);"
18261 "var load_result2 = load2(subobj);"
18262 "var keyed_load_result = keyed_load(obj, 'foo');"
18263 "var keyed_load_result2 = keyed_load2(subobj, 'foo');"
18264 "store(obj);"
18265 "store2(subobj);"
18266 "var y_from_obj = obj.y;"
18267 "var y_from_subobj = subobj.y;");
18268 CHECK(context->Global()->Get(v8_str("load_result"))->IsUndefined());
18269 CHECK(context->Global()->Get(v8_str("load_result2"))->IsUndefined());
18270 CHECK(context->Global()->Get(v8_str("keyed_load_result"))->IsUndefined());
18271 CHECK(context->Global()->Get(v8_str("keyed_load_result2"))->IsUndefined());
18272 CHECK(context->Global()->Get(v8_str("y_from_obj"))->IsUndefined());
18273 CHECK(context->Global()->Get(v8_str("y_from_subobj"))->IsUndefined());
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000018274}
verwaest@chromium.org753aee42012-07-17 16:15:42 +000018275
18276
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000018277THREADED_TEST(Regress142088) {
18278 i::FLAG_allow_natives_syntax = true;
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000018279 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018280 v8::HandleScope scope(context->GetIsolate());
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000018281 Local<ObjectTemplate> templ = ObjectTemplate::New();
18282 templ->SetAccessor(v8_str("foo"),
18283 GetterWhichReturns42,
18284 SetterWhichSetsYOnThisTo23);
18285 context->Global()->Set(v8_str("obj"), templ->NewInstance());
18286
18287 CompileRun("function load(x) { return x.foo; }"
18288 "var o = Object.create(obj);"
18289 "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
18290 "load(o); load(o); load(o); load(o);");
18291}
18292
18293
verwaest@chromium.org753aee42012-07-17 16:15:42 +000018294THREADED_TEST(Regress137496) {
18295 i::FLAG_expose_gc = true;
verwaest@chromium.org753aee42012-07-17 16:15:42 +000018296 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018297 v8::HandleScope scope(context->GetIsolate());
verwaest@chromium.org753aee42012-07-17 16:15:42 +000018298
18299 // Compile a try-finally clause where the finally block causes a GC
18300 // while there still is a message pending for external reporting.
18301 TryCatch try_catch;
18302 try_catch.SetVerbose(true);
18303 CompileRun("try { throw new Error(); } finally { gc(); }");
18304 CHECK(try_catch.HasCaught());
18305}
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000018306
18307
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000018308THREADED_TEST(Regress149912) {
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000018309 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018310 v8::HandleScope scope(context->GetIsolate());
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000018311 Handle<FunctionTemplate> templ = FunctionTemplate::New();
18312 AddInterceptor(templ, EmptyInterceptorGetter, EmptyInterceptorSetter);
18313 context->Global()->Set(v8_str("Bug"), templ->GetFunction());
18314 CompileRun("Number.prototype.__proto__ = new Bug; var x = 0; x.foo();");
18315}
18316
18317
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000018318THREADED_TEST(Regress157124) {
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000018319 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018320 v8::HandleScope scope(context->GetIsolate());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000018321 Local<ObjectTemplate> templ = ObjectTemplate::New();
18322 Local<Object> obj = templ->NewInstance();
18323 obj->GetIdentityHash();
18324 obj->DeleteHiddenValue(v8_str("Bug"));
18325}
18326
18327
ulan@chromium.org6e196bf2013-03-13 09:38:22 +000018328THREADED_TEST(Regress2535) {
18329 i::FLAG_harmony_collections = true;
ulan@chromium.org6e196bf2013-03-13 09:38:22 +000018330 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018331 v8::HandleScope scope(context->GetIsolate());
ulan@chromium.org6e196bf2013-03-13 09:38:22 +000018332 Local<Value> set_value = CompileRun("new Set();");
18333 Local<Object> set_object(Object::Cast(*set_value));
18334 CHECK_EQ(0, set_object->InternalFieldCount());
18335 Local<Value> map_value = CompileRun("new Map();");
18336 Local<Object> map_object(Object::Cast(*map_value));
18337 CHECK_EQ(0, map_object->InternalFieldCount());
18338}
18339
18340
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000018341#ifndef WIN32
18342class ThreadInterruptTest {
18343 public:
18344 ThreadInterruptTest() : sem_(NULL), sem_value_(0) { }
18345 ~ThreadInterruptTest() { delete sem_; }
18346
18347 void RunTest() {
18348 sem_ = i::OS::CreateSemaphore(0);
18349
18350 InterruptThread i_thread(this);
18351 i_thread.Start();
18352
18353 sem_->Wait();
18354 CHECK_EQ(kExpectedValue, sem_value_);
18355 }
18356
18357 private:
18358 static const int kExpectedValue = 1;
18359
18360 class InterruptThread : public i::Thread {
18361 public:
18362 explicit InterruptThread(ThreadInterruptTest* test)
18363 : Thread("InterruptThread"), test_(test) {}
18364
18365 virtual void Run() {
18366 struct sigaction action;
18367
18368 // Ensure that we'll enter waiting condition
18369 i::OS::Sleep(100);
18370
18371 // Setup signal handler
18372 memset(&action, 0, sizeof(action));
18373 action.sa_handler = SignalHandler;
18374 sigaction(SIGCHLD, &action, NULL);
18375
18376 // Send signal
18377 kill(getpid(), SIGCHLD);
18378
18379 // Ensure that if wait has returned because of error
18380 i::OS::Sleep(100);
18381
18382 // Set value and signal semaphore
18383 test_->sem_value_ = 1;
18384 test_->sem_->Signal();
18385 }
18386
18387 static void SignalHandler(int signal) {
18388 }
18389
18390 private:
18391 ThreadInterruptTest* test_;
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000018392 };
18393
18394 i::Semaphore* sem_;
18395 volatile int sem_value_;
18396};
18397
18398
18399THREADED_TEST(SemaphoreInterruption) {
18400 ThreadInterruptTest().RunTest();
18401}
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000018402
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000018403#endif // WIN32