blob: 38c8ac78bc52eb577b675d1877b6c46445d81327 [file] [log] [blame]
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001// Copyright 2012 the V8 project authors. All rights reserved.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
verwaest@chromium.org662436e2013-08-28 08:41:27 +000028#include <climits>
29#include <csignal>
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000030#include <string>
31#include <map>
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000032
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000033#include "v8.h"
34
verwaest@chromium.org662436e2013-08-28 08:41:27 +000035#if V8_OS_POSIX
36#include <unistd.h> // NOLINT
37#endif
38
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000039#include "api.h"
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +000040#include "arguments.h"
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000041#include "cctest.h"
machenbach@chromium.orgc1789ee2013-07-05 07:09:57 +000042#include "compilation-cache.h"
43#include "cpu-profiler.h"
44#include "execution.h"
45#include "isolate.h"
46#include "objects.h"
ager@chromium.org5b2fbee2010-09-08 06:38:15 +000047#include "parser.h"
machenbach@chromium.orgc1789ee2013-07-05 07:09:57 +000048#include "platform.h"
49#include "snapshot.h"
erik.corry@gmail.com4a6c3272010-11-18 12:04:40 +000050#include "unicode-inl.h"
machenbach@chromium.orgc1789ee2013-07-05 07:09:57 +000051#include "utils.h"
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +000052#include "vm-state.h"
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000053
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +000054static const bool kLogThreading = false;
ager@chromium.orgc4c92722009-11-18 14:12:51 +000055
danno@chromium.orgd3c42102013-08-01 16:58:23 +000056using ::v8::Boolean;
57using ::v8::BooleanObject;
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +000058using ::v8::Context;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000059using ::v8::Extension;
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +000060using ::v8::Function;
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000061using ::v8::FunctionTemplate;
62using ::v8::Handle;
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +000063using ::v8::HandleScope;
64using ::v8::Local;
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000065using ::v8::Message;
66using ::v8::MessageCallback;
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +000067using ::v8::Object;
68using ::v8::ObjectTemplate;
69using ::v8::Persistent;
70using ::v8::Script;
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000071using ::v8::StackTrace;
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +000072using ::v8::String;
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000073using ::v8::TryCatch;
74using ::v8::Undefined;
danno@chromium.orgca29dd82013-04-26 11:59:48 +000075using ::v8::UniqueId;
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +000076using ::v8::V8;
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000077using ::v8::Value;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000078
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000079
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000080#define THREADED_PROFILED_TEST(Name) \
81 static void Test##Name(); \
82 TEST(Name##WithProfiler) { \
83 RunWithProfiler(&Test##Name); \
84 } \
85 THREADED_TEST(Name)
machenbach@chromium.org528ce022013-09-23 14:09:36 +000086
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000087
88void RunWithProfiler(void (*test)()) {
89 LocalContext env;
90 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000091 v8::Local<v8::String> profile_name =
92 v8::String::NewFromUtf8(env->GetIsolate(), "my_profile1");
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000093 v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler();
94
95 cpu_profiler->StartCpuProfiling(profile_name);
96 (*test)();
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000097 reinterpret_cast<i::CpuProfiler*>(cpu_profiler)->DeleteAllProfiles();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000098}
99
100
kasperl@chromium.orgeac059f2010-01-25 11:02:06 +0000101static void ExpectString(const char* code, const char* expected) {
102 Local<Value> result = CompileRun(code);
103 CHECK(result->IsString());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +0000104 String::Utf8Value utf8(result);
105 CHECK_EQ(expected, *utf8);
kasperl@chromium.orgeac059f2010-01-25 11:02:06 +0000106}
107
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000108
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000109static void ExpectInt32(const char* code, int expected) {
110 Local<Value> result = CompileRun(code);
111 CHECK(result->IsInt32());
112 CHECK_EQ(expected, result->Int32Value());
113}
kasperl@chromium.orgeac059f2010-01-25 11:02:06 +0000114
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000115
kasperl@chromium.orgeac059f2010-01-25 11:02:06 +0000116static void ExpectBoolean(const char* code, bool expected) {
117 Local<Value> result = CompileRun(code);
118 CHECK(result->IsBoolean());
119 CHECK_EQ(expected, result->BooleanValue());
120}
121
122
kmillikin@chromium.org9155e252010-05-26 13:27:57 +0000123static void ExpectTrue(const char* code) {
124 ExpectBoolean(code, true);
125}
126
127
ager@chromium.orgea4f62e2010-08-16 16:28:43 +0000128static void ExpectFalse(const char* code) {
129 ExpectBoolean(code, false);
130}
131
132
kasperl@chromium.orgeac059f2010-01-25 11:02:06 +0000133static void ExpectObject(const char* code, Local<Value> expected) {
134 Local<Value> result = CompileRun(code);
135 CHECK(result->Equals(expected));
136}
137
138
ager@chromium.orgea4f62e2010-08-16 16:28:43 +0000139static void ExpectUndefined(const char* code) {
140 Local<Value> result = CompileRun(code);
141 CHECK(result->IsUndefined());
142}
143
144
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000145static int signature_callback_count;
jkummerow@chromium.org2c9426b2013-09-05 16:31:13 +0000146static Local<Value> signature_expected_receiver;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000147static void IncrementingSignatureCallback(
148 const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000149 ApiTestFuzzer::Fuzz();
150 signature_callback_count++;
jkummerow@chromium.org2c9426b2013-09-05 16:31:13 +0000151 CHECK_EQ(signature_expected_receiver, args.Holder());
152 CHECK_EQ(signature_expected_receiver, args.This());
machenbach@chromium.org9f18d912013-11-28 13:42:41 +0000153 v8::Handle<v8::Array> result =
154 v8::Array::New(args.GetIsolate(), args.Length());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000155 for (int i = 0; i < args.Length(); i++)
ulan@chromium.org0f13e742014-01-03 15:51:11 +0000156 result->Set(v8::Integer::New(args.GetIsolate(), i), args[i]);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000157 args.GetReturnValue().Set(result);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000158}
159
160
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000161static void SignatureCallback(
162 const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000163 ApiTestFuzzer::Fuzz();
machenbach@chromium.org9f18d912013-11-28 13:42:41 +0000164 v8::Handle<v8::Array> result =
165 v8::Array::New(args.GetIsolate(), args.Length());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000166 for (int i = 0; i < args.Length(); i++) {
ulan@chromium.org0f13e742014-01-03 15:51:11 +0000167 result->Set(v8::Integer::New(args.GetIsolate(), i), args[i]);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000168 }
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000169 args.GetReturnValue().Set(result);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000170}
171
172
dslomov@chromium.org639bac02013-09-09 11:58:54 +0000173// Tests that call v8::V8::Dispose() cannot be threaded.
174TEST(InitializeAndDisposeOnce) {
175 CHECK(v8::V8::Initialize());
176 CHECK(v8::V8::Dispose());
177}
178
179
180// Tests that call v8::V8::Dispose() cannot be threaded.
181TEST(InitializeAndDisposeMultiple) {
182 for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
183 for (int i = 0; i < 3; ++i) CHECK(v8::V8::Initialize());
184 for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
185 // TODO(mstarzinger): This should fail gracefully instead of asserting.
186 // for (int i = 0; i < 3; ++i) CHECK(v8::V8::Initialize());
187 for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
188}
189
190
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000191THREADED_TEST(Handles) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000192 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000193 Local<Context> local_env;
194 {
195 LocalContext env;
196 local_env = env.local();
197 }
198
199 // Local context should still be live.
200 CHECK(!local_env.IsEmpty());
201 local_env->Enter();
202
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +0000203 v8::Handle<v8::Primitive> undef = v8::Undefined(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000204 CHECK(!undef.IsEmpty());
205 CHECK(undef->IsUndefined());
206
207 const char* c_source = "1 + 2 + 3";
machenbach@chromium.orgf9841892013-11-25 12:01:13 +0000208 Local<String> source = String::NewFromUtf8(CcTest::isolate(), c_source);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000209 Local<Script> script = Script::Compile(source);
210 CHECK_EQ(6, script->Run()->Int32Value());
211
212 local_env->Exit();
213}
214
215
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000216THREADED_TEST(IsolateOfContext) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000217 v8::HandleScope scope(CcTest::isolate());
218 v8::Handle<Context> env = Context::New(CcTest::isolate());
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000219
machenbach@chromium.orgf9841892013-11-25 12:01:13 +0000220 CHECK(!env->GetIsolate()->InContext());
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000221 CHECK(env->GetIsolate() == CcTest::isolate());
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000222 env->Enter();
machenbach@chromium.orgf9841892013-11-25 12:01:13 +0000223 CHECK(env->GetIsolate()->InContext());
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000224 CHECK(env->GetIsolate() == CcTest::isolate());
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000225 env->Exit();
machenbach@chromium.orgf9841892013-11-25 12:01:13 +0000226 CHECK(!env->GetIsolate()->InContext());
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000227 CHECK(env->GetIsolate() == CcTest::isolate());
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000228}
229
230
dslomov@chromium.org639bac02013-09-09 11:58:54 +0000231static void TestSignature(const char* loop_js, Local<Value> receiver) {
232 i::ScopedVector<char> source(200);
233 i::OS::SNPrintF(source,
234 "for (var i = 0; i < 10; i++) {"
235 " %s"
236 "}",
237 loop_js);
238 signature_callback_count = 0;
239 signature_expected_receiver = receiver;
240 bool expected_to_throw = receiver.IsEmpty();
241 v8::TryCatch try_catch;
242 CompileRun(source.start());
243 CHECK_EQ(expected_to_throw, try_catch.HasCaught());
244 if (!expected_to_throw) {
245 CHECK_EQ(10, signature_callback_count);
246 } else {
247 CHECK_EQ(v8_str("TypeError: Illegal invocation"),
248 try_catch.Exception()->ToString());
249 }
250}
251
252
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000253THREADED_TEST(ReceiverSignature) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000254 LocalContext env;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +0000255 v8::Isolate* isolate = env->GetIsolate();
256 v8::HandleScope scope(isolate);
dslomov@chromium.org639bac02013-09-09 11:58:54 +0000257 // Setup templates.
hpayer@chromium.org4f99be92013-12-18 16:23:55 +0000258 v8::Handle<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(isolate);
259 v8::Handle<v8::Signature> sig = v8::Signature::New(isolate, fun);
dslomov@chromium.org639bac02013-09-09 11:58:54 +0000260 v8::Handle<v8::FunctionTemplate> callback_sig =
261 v8::FunctionTemplate::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +0000262 isolate, IncrementingSignatureCallback, Local<Value>(), sig);
dslomov@chromium.org639bac02013-09-09 11:58:54 +0000263 v8::Handle<v8::FunctionTemplate> callback =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +0000264 v8::FunctionTemplate::New(isolate, IncrementingSignatureCallback);
265 v8::Handle<v8::FunctionTemplate> sub_fun = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000266 sub_fun->Inherit(fun);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +0000267 v8::Handle<v8::FunctionTemplate> unrel_fun =
268 v8::FunctionTemplate::New(isolate);
dslomov@chromium.org639bac02013-09-09 11:58:54 +0000269 // Install properties.
270 v8::Handle<v8::ObjectTemplate> fun_proto = fun->PrototypeTemplate();
271 fun_proto->Set(v8_str("prop_sig"), callback_sig);
272 fun_proto->Set(v8_str("prop"), callback);
273 fun_proto->SetAccessorProperty(
274 v8_str("accessor_sig"), callback_sig, callback_sig);
275 fun_proto->SetAccessorProperty(v8_str("accessor"), callback, callback);
276 // Instantiate templates.
277 Local<Value> fun_instance = fun->InstanceTemplate()->NewInstance();
278 Local<Value> sub_fun_instance = sub_fun->InstanceTemplate()->NewInstance();
279 // Setup global variables.
280 env->Global()->Set(v8_str("Fun"), fun->GetFunction());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000281 env->Global()->Set(v8_str("UnrelFun"), unrel_fun->GetFunction());
dslomov@chromium.org639bac02013-09-09 11:58:54 +0000282 env->Global()->Set(v8_str("fun_instance"), fun_instance);
283 env->Global()->Set(v8_str("sub_fun_instance"), sub_fun_instance);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000284 CompileRun(
dslomov@chromium.org639bac02013-09-09 11:58:54 +0000285 "var accessor_sig_key = 'accessor_sig';"
286 "var accessor_key = 'accessor';"
287 "var prop_sig_key = 'prop_sig';"
288 "var prop_key = 'prop';"
289 ""
290 "function copy_props(obj) {"
291 " var keys = [accessor_sig_key, accessor_key, prop_sig_key, prop_key];"
292 " var source = Fun.prototype;"
293 " for (var i in keys) {"
294 " var key = keys[i];"
295 " var desc = Object.getOwnPropertyDescriptor(source, key);"
296 " Object.defineProperty(obj, key, desc);"
297 " }"
298 "}"
299 ""
300 "var obj = {};"
301 "copy_props(obj);"
302 "var unrel = new UnrelFun();"
303 "copy_props(unrel);");
304 // Test with and without ICs
305 const char* test_objects[] = {
306 "fun_instance", "sub_fun_instance", "obj", "unrel" };
307 unsigned bad_signature_start_offset = 2;
308 for (unsigned i = 0; i < ARRAY_SIZE(test_objects); i++) {
309 i::ScopedVector<char> source(200);
310 i::OS::SNPrintF(
311 source, "var test_object = %s; test_object", test_objects[i]);
312 Local<Value> test_object = CompileRun(source.start());
313 TestSignature("test_object.prop();", test_object);
314 TestSignature("test_object.accessor;", test_object);
315 TestSignature("test_object[accessor_key];", test_object);
316 TestSignature("test_object.accessor = 1;", test_object);
317 TestSignature("test_object[accessor_key] = 1;", test_object);
318 if (i >= bad_signature_start_offset) test_object = Local<Value>();
319 TestSignature("test_object.prop_sig();", test_object);
320 TestSignature("test_object.accessor_sig;", test_object);
321 TestSignature("test_object[accessor_sig_key];", test_object);
322 TestSignature("test_object.accessor_sig = 1;", test_object);
323 TestSignature("test_object[accessor_sig_key] = 1;", test_object);
324 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000325}
326
327
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000328THREADED_TEST(ArgumentSignature) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000329 LocalContext env;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +0000330 v8::Isolate* isolate = env->GetIsolate();
331 v8::HandleScope scope(isolate);
332 v8::Handle<v8::FunctionTemplate> cons = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000333 cons->SetClassName(v8_str("Cons"));
machenbach@chromium.org9f18d912013-11-28 13:42:41 +0000334 v8::Handle<v8::Signature> sig = v8::Signature::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +0000335 isolate, v8::Handle<v8::FunctionTemplate>(), 1, &cons);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000336 v8::Handle<v8::FunctionTemplate> fun =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +0000337 v8::FunctionTemplate::New(isolate,
338 SignatureCallback,
339 v8::Handle<Value>(),
340 sig);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000341 env->Global()->Set(v8_str("Cons"), cons->GetFunction());
342 env->Global()->Set(v8_str("Fun1"), fun->GetFunction());
343
344 v8::Handle<Value> value1 = CompileRun("Fun1(4) == '';");
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000345 CHECK(value1->IsTrue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000346
347 v8::Handle<Value> value2 = CompileRun("Fun1(new Cons()) == '[object Cons]';");
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000348 CHECK(value2->IsTrue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000349
350 v8::Handle<Value> value3 = CompileRun("Fun1() == '';");
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000351 CHECK(value3->IsTrue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000352
hpayer@chromium.org4f99be92013-12-18 16:23:55 +0000353 v8::Handle<v8::FunctionTemplate> cons1 = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000354 cons1->SetClassName(v8_str("Cons1"));
hpayer@chromium.org4f99be92013-12-18 16:23:55 +0000355 v8::Handle<v8::FunctionTemplate> cons2 = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000356 cons2->SetClassName(v8_str("Cons2"));
hpayer@chromium.org4f99be92013-12-18 16:23:55 +0000357 v8::Handle<v8::FunctionTemplate> cons3 = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000358 cons3->SetClassName(v8_str("Cons3"));
359
360 v8::Handle<v8::FunctionTemplate> args[3] = { cons1, cons2, cons3 };
machenbach@chromium.org9f18d912013-11-28 13:42:41 +0000361 v8::Handle<v8::Signature> wsig = v8::Signature::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +0000362 isolate, v8::Handle<v8::FunctionTemplate>(), 3, args);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000363 v8::Handle<v8::FunctionTemplate> fun2 =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +0000364 v8::FunctionTemplate::New(isolate,
365 SignatureCallback,
366 v8::Handle<Value>(),
367 wsig);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000368
369 env->Global()->Set(v8_str("Cons1"), cons1->GetFunction());
370 env->Global()->Set(v8_str("Cons2"), cons2->GetFunction());
371 env->Global()->Set(v8_str("Cons3"), cons3->GetFunction());
372 env->Global()->Set(v8_str("Fun2"), fun2->GetFunction());
373 v8::Handle<Value> value4 = CompileRun(
374 "Fun2(new Cons1(), new Cons2(), new Cons3()) =="
375 "'[object Cons1],[object Cons2],[object Cons3]'");
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000376 CHECK(value4->IsTrue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000377
378 v8::Handle<Value> value5 = CompileRun(
379 "Fun2(new Cons1(), new Cons2(), 5) == '[object Cons1],[object Cons2],'");
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000380 CHECK(value5->IsTrue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000381
382 v8::Handle<Value> value6 = CompileRun(
383 "Fun2(new Cons3(), new Cons2(), new Cons1()) == ',[object Cons2],'");
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000384 CHECK(value6->IsTrue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000385
386 v8::Handle<Value> value7 = CompileRun(
387 "Fun2(new Cons1(), new Cons2(), new Cons3(), 'd') == "
388 "'[object Cons1],[object Cons2],[object Cons3],d';");
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000389 CHECK(value7->IsTrue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000390
391 v8::Handle<Value> value8 = CompileRun(
392 "Fun2(new Cons1(), new Cons2()) == '[object Cons1],[object Cons2]'");
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000393 CHECK(value8->IsTrue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000394}
395
396
397THREADED_TEST(HulIgennem) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000398 LocalContext env;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +0000399 v8::Isolate* isolate = env->GetIsolate();
400 v8::HandleScope scope(isolate);
401 v8::Handle<v8::Primitive> undef = v8::Undefined(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000402 Local<String> undef_str = undef->ToString();
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000403 char* value = i::NewArray<char>(undef_str->Utf8Length() + 1);
404 undef_str->WriteUtf8(value);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000405 CHECK_EQ(0, strcmp(value, "undefined"));
406 i::DeleteArray(value);
407}
408
409
410THREADED_TEST(Access) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000411 LocalContext env;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +0000412 v8::Isolate* isolate = env->GetIsolate();
413 v8::HandleScope scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +0000414 Local<v8::Object> obj = v8::Object::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000415 Local<Value> foo_before = obj->Get(v8_str("foo"));
416 CHECK(foo_before->IsUndefined());
417 Local<String> bar_str = v8_str("bar");
418 obj->Set(v8_str("foo"), bar_str);
419 Local<Value> foo_after = obj->Get(v8_str("foo"));
420 CHECK(!foo_after->IsUndefined());
421 CHECK(foo_after->IsString());
422 CHECK_EQ(bar_str, foo_after);
423}
424
425
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000426THREADED_TEST(AccessElement) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000427 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000428 v8::HandleScope scope(env->GetIsolate());
ulan@chromium.org0f13e742014-01-03 15:51:11 +0000429 Local<v8::Object> obj = v8::Object::New(env->GetIsolate());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000430 Local<Value> before = obj->Get(1);
431 CHECK(before->IsUndefined());
432 Local<String> bar_str = v8_str("bar");
433 obj->Set(1, bar_str);
434 Local<Value> after = obj->Get(1);
435 CHECK(!after->IsUndefined());
436 CHECK(after->IsString());
437 CHECK_EQ(bar_str, after);
438
439 Local<v8::Array> value = CompileRun("[\"a\", \"b\"]").As<v8::Array>();
440 CHECK_EQ(v8_str("a"), value->Get(0));
441 CHECK_EQ(v8_str("b"), value->Get(1));
442}
443
444
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000445THREADED_TEST(Script) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000446 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000447 v8::HandleScope scope(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000448 const char* c_source = "1 + 2 + 3";
machenbach@chromium.orgf9841892013-11-25 12:01:13 +0000449 Local<String> source = String::NewFromUtf8(env->GetIsolate(), c_source);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000450 Local<Script> script = Script::Compile(source);
451 CHECK_EQ(6, script->Run()->Int32Value());
452}
453
454
455static uint16_t* AsciiToTwoByteString(const char* source) {
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000456 int array_length = i::StrLength(source) + 1;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000457 uint16_t* converted = i::NewArray<uint16_t>(array_length);
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000458 for (int i = 0; i < array_length; i++) converted[i] = source[i];
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000459 return converted;
460}
461
462
463class TestResource: public String::ExternalStringResource {
464 public:
machenbach@chromium.org57a54ac2014-01-31 14:01:53 +0000465 TestResource(uint16_t* data, int* counter = NULL, bool owning_data = true)
466 : data_(data), length_(0), counter_(counter), owning_data_(owning_data) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000467 while (data[length_]) ++length_;
468 }
469
470 ~TestResource() {
machenbach@chromium.org57a54ac2014-01-31 14:01:53 +0000471 if (owning_data_) i::DeleteArray(data_);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000472 if (counter_ != NULL) ++*counter_;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000473 }
474
475 const uint16_t* data() const {
476 return data_;
477 }
478
479 size_t length() const {
480 return length_;
481 }
machenbach@chromium.org57a54ac2014-01-31 14:01:53 +0000482
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000483 private:
484 uint16_t* data_;
485 size_t length_;
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000486 int* counter_;
machenbach@chromium.org57a54ac2014-01-31 14:01:53 +0000487 bool owning_data_;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000488};
489
490
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000491class TestAsciiResource: public String::ExternalAsciiStringResource {
492 public:
machenbach@chromium.org57a54ac2014-01-31 14:01:53 +0000493 TestAsciiResource(const char* data, int* counter = NULL, size_t offset = 0)
494 : orig_data_(data),
495 data_(data + offset),
496 length_(strlen(data) - offset),
497 counter_(counter) { }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000498
499 ~TestAsciiResource() {
machenbach@chromium.org57a54ac2014-01-31 14:01:53 +0000500 i::DeleteArray(orig_data_);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000501 if (counter_ != NULL) ++*counter_;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000502 }
503
504 const char* data() const {
505 return data_;
506 }
507
508 size_t length() const {
509 return length_;
510 }
machenbach@chromium.org57a54ac2014-01-31 14:01:53 +0000511
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000512 private:
machenbach@chromium.org57a54ac2014-01-31 14:01:53 +0000513 const char* orig_data_;
ager@chromium.org5ec48922009-05-05 07:25:34 +0000514 const char* data_;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000515 size_t length_;
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000516 int* counter_;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000517};
518
519
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000520THREADED_TEST(ScriptUsingStringResource) {
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000521 int dispose_count = 0;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000522 const char* c_source = "1 + 2 * 3";
523 uint16_t* two_byte_source = AsciiToTwoByteString(c_source);
524 {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000525 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000526 v8::HandleScope scope(env->GetIsolate());
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000527 TestResource* resource = new TestResource(two_byte_source, &dispose_count);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +0000528 Local<String> source = String::NewExternal(env->GetIsolate(), resource);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000529 Local<Script> script = Script::Compile(source);
530 Local<Value> value = script->Run();
531 CHECK(value->IsNumber());
532 CHECK_EQ(7, value->Int32Value());
533 CHECK(source->IsExternal());
534 CHECK_EQ(resource,
535 static_cast<TestResource*>(source->GetExternalStringResource()));
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000536 String::Encoding encoding = String::UNKNOWN_ENCODING;
537 CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
538 source->GetExternalStringResourceBase(&encoding));
539 CHECK_EQ(String::TWO_BYTE_ENCODING, encoding);
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000540 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000541 CHECK_EQ(0, dispose_count);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000542 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000543 CcTest::i_isolate()->compilation_cache()->Clear();
544 CcTest::heap()->CollectAllAvailableGarbage();
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000545 CHECK_EQ(1, dispose_count);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000546}
547
548
549THREADED_TEST(ScriptUsingAsciiStringResource) {
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000550 int dispose_count = 0;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000551 const char* c_source = "1 + 2 * 3";
552 {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000553 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000554 v8::HandleScope scope(env->GetIsolate());
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000555 TestAsciiResource* resource = new TestAsciiResource(i::StrDup(c_source),
556 &dispose_count);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +0000557 Local<String> source = String::NewExternal(env->GetIsolate(), resource);
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000558 CHECK(source->IsExternalAscii());
559 CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
560 source->GetExternalAsciiStringResource());
561 String::Encoding encoding = String::UNKNOWN_ENCODING;
562 CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
563 source->GetExternalStringResourceBase(&encoding));
564 CHECK_EQ(String::ASCII_ENCODING, encoding);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000565 Local<Script> script = Script::Compile(source);
566 Local<Value> value = script->Run();
567 CHECK(value->IsNumber());
568 CHECK_EQ(7, value->Int32Value());
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000569 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000570 CHECK_EQ(0, dispose_count);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000571 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000572 CcTest::i_isolate()->compilation_cache()->Clear();
573 CcTest::heap()->CollectAllAvailableGarbage();
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000574 CHECK_EQ(1, dispose_count);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000575}
576
577
ager@chromium.org6f10e412009-02-13 10:11:16 +0000578THREADED_TEST(ScriptMakingExternalString) {
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000579 int dispose_count = 0;
ager@chromium.org6f10e412009-02-13 10:11:16 +0000580 uint16_t* two_byte_source = AsciiToTwoByteString("1 + 2 * 3");
581 {
ager@chromium.org6f10e412009-02-13 10:11:16 +0000582 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000583 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.orgf9841892013-11-25 12:01:13 +0000584 Local<String> source =
585 String::NewFromTwoByte(env->GetIsolate(), two_byte_source);
ager@chromium.org5c838252010-02-19 08:53:10 +0000586 // Trigger GCs so that the newly allocated string moves to old gen.
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000587 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
588 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
ulan@chromium.org56c14af2012-09-20 12:51:09 +0000589 CHECK_EQ(source->IsExternal(), false);
590 CHECK_EQ(source->IsExternalAscii(), false);
591 String::Encoding encoding = String::UNKNOWN_ENCODING;
592 CHECK_EQ(NULL, source->GetExternalStringResourceBase(&encoding));
593 CHECK_EQ(String::ASCII_ENCODING, encoding);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000594 bool success = source->MakeExternal(new TestResource(two_byte_source,
595 &dispose_count));
ager@chromium.org6f10e412009-02-13 10:11:16 +0000596 CHECK(success);
597 Local<Script> script = Script::Compile(source);
598 Local<Value> value = script->Run();
599 CHECK(value->IsNumber());
600 CHECK_EQ(7, value->Int32Value());
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000601 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000602 CHECK_EQ(0, dispose_count);
ager@chromium.org6f10e412009-02-13 10:11:16 +0000603 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000604 CcTest::i_isolate()->compilation_cache()->Clear();
605 CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000606 CHECK_EQ(1, dispose_count);
ager@chromium.org6f10e412009-02-13 10:11:16 +0000607}
608
609
610THREADED_TEST(ScriptMakingExternalAsciiString) {
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000611 int dispose_count = 0;
ager@chromium.org6f10e412009-02-13 10:11:16 +0000612 const char* c_source = "1 + 2 * 3";
613 {
ager@chromium.org6f10e412009-02-13 10:11:16 +0000614 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000615 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org6f10e412009-02-13 10:11:16 +0000616 Local<String> source = v8_str(c_source);
ager@chromium.org5c838252010-02-19 08:53:10 +0000617 // Trigger GCs so that the newly allocated string moves to old gen.
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000618 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
619 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
ager@chromium.org6f10e412009-02-13 10:11:16 +0000620 bool success = source->MakeExternal(
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000621 new TestAsciiResource(i::StrDup(c_source), &dispose_count));
ager@chromium.org6f10e412009-02-13 10:11:16 +0000622 CHECK(success);
623 Local<Script> script = Script::Compile(source);
624 Local<Value> value = script->Run();
625 CHECK(value->IsNumber());
626 CHECK_EQ(7, value->Int32Value());
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000627 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000628 CHECK_EQ(0, dispose_count);
ager@chromium.org6f10e412009-02-13 10:11:16 +0000629 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000630 CcTest::i_isolate()->compilation_cache()->Clear();
631 CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000632 CHECK_EQ(1, dispose_count);
ager@chromium.org6f10e412009-02-13 10:11:16 +0000633}
634
635
ager@chromium.org5c838252010-02-19 08:53:10 +0000636TEST(MakingExternalStringConditions) {
ager@chromium.org5c838252010-02-19 08:53:10 +0000637 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000638 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org5c838252010-02-19 08:53:10 +0000639
640 // Free some space in the new space so that we can check freshness.
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000641 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
642 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
ager@chromium.org5c838252010-02-19 08:53:10 +0000643
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000644 uint16_t* two_byte_string = AsciiToTwoByteString("s1");
machenbach@chromium.orgf9841892013-11-25 12:01:13 +0000645 Local<String> small_string =
646 String::NewFromTwoByte(env->GetIsolate(), two_byte_string);
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000647 i::DeleteArray(two_byte_string);
648
ager@chromium.org5c838252010-02-19 08:53:10 +0000649 // We should refuse to externalize newly created small string.
650 CHECK(!small_string->CanMakeExternal());
651 // Trigger GCs so that the newly allocated string moves to old gen.
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000652 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
653 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
ager@chromium.org5c838252010-02-19 08:53:10 +0000654 // Old space strings should be accepted.
655 CHECK(small_string->CanMakeExternal());
656
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000657 two_byte_string = AsciiToTwoByteString("small string 2");
machenbach@chromium.orgf9841892013-11-25 12:01:13 +0000658 small_string = String::NewFromTwoByte(env->GetIsolate(), two_byte_string);
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000659 i::DeleteArray(two_byte_string);
660
ager@chromium.org5c838252010-02-19 08:53:10 +0000661 // We should refuse externalizing newly created small string.
662 CHECK(!small_string->CanMakeExternal());
663 for (int i = 0; i < 100; i++) {
664 String::Value value(small_string);
665 }
666 // Frequently used strings should be accepted.
667 CHECK(small_string->CanMakeExternal());
668
669 const int buf_size = 10 * 1024;
670 char* buf = i::NewArray<char>(buf_size);
671 memset(buf, 'a', buf_size);
672 buf[buf_size - 1] = '\0';
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000673
674 two_byte_string = AsciiToTwoByteString(buf);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +0000675 Local<String> large_string =
676 String::NewFromTwoByte(env->GetIsolate(), two_byte_string);
ager@chromium.org5c838252010-02-19 08:53:10 +0000677 i::DeleteArray(buf);
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000678 i::DeleteArray(two_byte_string);
ager@chromium.org5c838252010-02-19 08:53:10 +0000679 // Large strings should be immediately accepted.
680 CHECK(large_string->CanMakeExternal());
681}
682
683
684TEST(MakingExternalAsciiStringConditions) {
ager@chromium.org5c838252010-02-19 08:53:10 +0000685 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000686 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org5c838252010-02-19 08:53:10 +0000687
688 // Free some space in the new space so that we can check freshness.
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000689 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
690 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
ager@chromium.org5c838252010-02-19 08:53:10 +0000691
machenbach@chromium.orgf9841892013-11-25 12:01:13 +0000692 Local<String> small_string = String::NewFromUtf8(env->GetIsolate(), "s1");
ager@chromium.org5c838252010-02-19 08:53:10 +0000693 // We should refuse to externalize newly created small string.
694 CHECK(!small_string->CanMakeExternal());
695 // Trigger GCs so that the newly allocated string moves to old gen.
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000696 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
697 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
ager@chromium.org5c838252010-02-19 08:53:10 +0000698 // Old space strings should be accepted.
699 CHECK(small_string->CanMakeExternal());
700
machenbach@chromium.orgf9841892013-11-25 12:01:13 +0000701 small_string = String::NewFromUtf8(env->GetIsolate(), "small string 2");
ager@chromium.org5c838252010-02-19 08:53:10 +0000702 // We should refuse externalizing newly created small string.
703 CHECK(!small_string->CanMakeExternal());
704 for (int i = 0; i < 100; i++) {
705 String::Value value(small_string);
706 }
707 // Frequently used strings should be accepted.
708 CHECK(small_string->CanMakeExternal());
709
710 const int buf_size = 10 * 1024;
711 char* buf = i::NewArray<char>(buf_size);
712 memset(buf, 'a', buf_size);
713 buf[buf_size - 1] = '\0';
machenbach@chromium.orgf9841892013-11-25 12:01:13 +0000714 Local<String> large_string = String::NewFromUtf8(env->GetIsolate(), buf);
ager@chromium.org5c838252010-02-19 08:53:10 +0000715 i::DeleteArray(buf);
716 // Large strings should be immediately accepted.
717 CHECK(large_string->CanMakeExternal());
718}
719
720
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000721TEST(MakingExternalUnalignedAsciiString) {
722 LocalContext env;
723 v8::HandleScope scope(env->GetIsolate());
724
725 CompileRun("function cons(a, b) { return a + b; }"
726 "function slice(a) { return a.substring(1); }");
727 // Create a cons string that will land in old pointer space.
728 Local<String> cons = Local<String>::Cast(CompileRun(
729 "cons('abcdefghijklm', 'nopqrstuvwxyz');"));
730 // Create a sliced string that will land in old pointer space.
731 Local<String> slice = Local<String>::Cast(CompileRun(
732 "slice('abcdefghijklmnopqrstuvwxyz');"));
733
734 // Trigger GCs so that the newly allocated string moves to old gen.
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000735 SimulateFullSpace(CcTest::heap()->old_pointer_space());
736 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
737 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000738
739 // Turn into external string with unaligned resource data.
740 int dispose_count = 0;
741 const char* c_cons = "_abcdefghijklmnopqrstuvwxyz";
742 bool success = cons->MakeExternal(
machenbach@chromium.org57a54ac2014-01-31 14:01:53 +0000743 new TestAsciiResource(i::StrDup(c_cons), &dispose_count, 1));
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000744 CHECK(success);
745 const char* c_slice = "_bcdefghijklmnopqrstuvwxyz";
746 success = slice->MakeExternal(
machenbach@chromium.org57a54ac2014-01-31 14:01:53 +0000747 new TestAsciiResource(i::StrDup(c_slice), &dispose_count, 1));
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000748 CHECK(success);
749
750 // Trigger GCs and force evacuation.
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000751 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
752 CcTest::heap()->CollectAllGarbage(i::Heap::kReduceMemoryFootprintMask);
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000753}
754
755
ager@chromium.org6f10e412009-02-13 10:11:16 +0000756THREADED_TEST(UsingExternalString) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000757 i::Factory* factory = CcTest::i_isolate()->factory();
ager@chromium.orge2902be2009-06-08 12:21:35 +0000758 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000759 v8::HandleScope scope(CcTest::isolate());
ager@chromium.orge2902be2009-06-08 12:21:35 +0000760 uint16_t* two_byte_string = AsciiToTwoByteString("test string");
machenbach@chromium.org9f18d912013-11-28 13:42:41 +0000761 Local<String> string = String::NewExternal(
762 CcTest::isolate(), new TestResource(two_byte_string));
ager@chromium.orge2902be2009-06-08 12:21:35 +0000763 i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
764 // Trigger GCs so that the newly allocated string moves to old gen.
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000765 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
766 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000767 i::Handle<i::String> isymbol =
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000768 factory->InternalizedStringFromString(istring);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000769 CHECK(isymbol->IsInternalizedString());
ager@chromium.orge2902be2009-06-08 12:21:35 +0000770 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000771 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
772 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org6f10e412009-02-13 10:11:16 +0000773}
774
775
776THREADED_TEST(UsingExternalAsciiString) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000777 i::Factory* factory = CcTest::i_isolate()->factory();
ager@chromium.orge2902be2009-06-08 12:21:35 +0000778 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000779 v8::HandleScope scope(CcTest::isolate());
ager@chromium.orge2902be2009-06-08 12:21:35 +0000780 const char* one_byte_string = "test string";
781 Local<String> string = String::NewExternal(
machenbach@chromium.org9f18d912013-11-28 13:42:41 +0000782 CcTest::isolate(), new TestAsciiResource(i::StrDup(one_byte_string)));
ager@chromium.orge2902be2009-06-08 12:21:35 +0000783 i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
784 // Trigger GCs so that the newly allocated string moves to old gen.
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000785 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
786 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000787 i::Handle<i::String> isymbol =
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000788 factory->InternalizedStringFromString(istring);
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000789 CHECK(isymbol->IsInternalizedString());
ager@chromium.orge2902be2009-06-08 12:21:35 +0000790 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000791 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
792 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org6f10e412009-02-13 10:11:16 +0000793}
794
795
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000796THREADED_TEST(ScavengeExternalString) {
svenpanne@chromium.org83130cf2012-11-30 10:13:25 +0000797 i::FLAG_stress_compaction = false;
798 i::FLAG_gc_global = false;
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000799 int dispose_count = 0;
lrn@chromium.orgc34f5802010-04-28 12:53:43 +0000800 bool in_new_space = false;
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000801 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000802 v8::HandleScope scope(CcTest::isolate());
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000803 uint16_t* two_byte_string = AsciiToTwoByteString("test string");
machenbach@chromium.org9f18d912013-11-28 13:42:41 +0000804 Local<String> string = String::NewExternal(
805 CcTest::isolate(), new TestResource(two_byte_string, &dispose_count));
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000806 i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000807 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
808 in_new_space = CcTest::heap()->InNewSpace(*istring);
809 CHECK(in_new_space || CcTest::heap()->old_data_space()->Contains(*istring));
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000810 CHECK_EQ(0, dispose_count);
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000811 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000812 CcTest::heap()->CollectGarbage(
813 in_new_space ? i::NEW_SPACE : i::OLD_DATA_SPACE);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000814 CHECK_EQ(1, dispose_count);
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000815}
816
817
818THREADED_TEST(ScavengeExternalAsciiString) {
svenpanne@chromium.org83130cf2012-11-30 10:13:25 +0000819 i::FLAG_stress_compaction = false;
820 i::FLAG_gc_global = false;
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000821 int dispose_count = 0;
lrn@chromium.orgc34f5802010-04-28 12:53:43 +0000822 bool in_new_space = false;
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000823 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000824 v8::HandleScope scope(CcTest::isolate());
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000825 const char* one_byte_string = "test string";
826 Local<String> string = String::NewExternal(
machenbach@chromium.org9f18d912013-11-28 13:42:41 +0000827 CcTest::isolate(),
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000828 new TestAsciiResource(i::StrDup(one_byte_string), &dispose_count));
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000829 i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000830 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
831 in_new_space = CcTest::heap()->InNewSpace(*istring);
832 CHECK(in_new_space || CcTest::heap()->old_data_space()->Contains(*istring));
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000833 CHECK_EQ(0, dispose_count);
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000834 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000835 CcTest::heap()->CollectGarbage(
836 in_new_space ? i::NEW_SPACE : i::OLD_DATA_SPACE);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000837 CHECK_EQ(1, dispose_count);
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000838}
839
840
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000841class TestAsciiResourceWithDisposeControl: public TestAsciiResource {
842 public:
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000843 // Only used by non-threaded tests, so it can use static fields.
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000844 static int dispose_calls;
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000845 static int dispose_count;
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000846
847 TestAsciiResourceWithDisposeControl(const char* data, bool dispose)
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000848 : TestAsciiResource(data, &dispose_count),
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000849 dispose_(dispose) { }
850
851 void Dispose() {
852 ++dispose_calls;
853 if (dispose_) delete this;
854 }
855 private:
856 bool dispose_;
857};
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000858
859
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000860int TestAsciiResourceWithDisposeControl::dispose_count = 0;
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000861int TestAsciiResourceWithDisposeControl::dispose_calls = 0;
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000862
863
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000864TEST(ExternalStringWithDisposeHandling) {
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000865 const char* c_source = "1 + 2 * 3";
866
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000867 // Use a stack allocated external string resource allocated object.
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000868 TestAsciiResourceWithDisposeControl::dispose_count = 0;
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000869 TestAsciiResourceWithDisposeControl::dispose_calls = 0;
870 TestAsciiResourceWithDisposeControl res_stack(i::StrDup(c_source), false);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000871 {
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000872 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000873 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org9f18d912013-11-28 13:42:41 +0000874 Local<String> source = String::NewExternal(env->GetIsolate(), &res_stack);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000875 Local<Script> script = Script::Compile(source);
876 Local<Value> value = script->Run();
877 CHECK(value->IsNumber());
878 CHECK_EQ(7, value->Int32Value());
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000879 CcTest::heap()->CollectAllAvailableGarbage();
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000880 CHECK_EQ(0, TestAsciiResourceWithDisposeControl::dispose_count);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000881 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000882 CcTest::i_isolate()->compilation_cache()->Clear();
883 CcTest::heap()->CollectAllAvailableGarbage();
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000884 CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_calls);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000885 CHECK_EQ(0, TestAsciiResourceWithDisposeControl::dispose_count);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000886
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000887 // Use a heap allocated external string resource allocated object.
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000888 TestAsciiResourceWithDisposeControl::dispose_count = 0;
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000889 TestAsciiResourceWithDisposeControl::dispose_calls = 0;
890 TestAsciiResource* res_heap =
891 new TestAsciiResourceWithDisposeControl(i::StrDup(c_source), true);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000892 {
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000893 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000894 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org9f18d912013-11-28 13:42:41 +0000895 Local<String> source = String::NewExternal(env->GetIsolate(), res_heap);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000896 Local<Script> script = Script::Compile(source);
897 Local<Value> value = script->Run();
898 CHECK(value->IsNumber());
899 CHECK_EQ(7, value->Int32Value());
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000900 CcTest::heap()->CollectAllAvailableGarbage();
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000901 CHECK_EQ(0, TestAsciiResourceWithDisposeControl::dispose_count);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000902 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000903 CcTest::i_isolate()->compilation_cache()->Clear();
904 CcTest::heap()->CollectAllAvailableGarbage();
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000905 CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_calls);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000906 CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_count);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000907}
908
909
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000910THREADED_TEST(StringConcat) {
911 {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000912 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000913 v8::HandleScope scope(env->GetIsolate());
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000914 const char* one_byte_string_1 = "function a_times_t";
915 const char* two_byte_string_1 = "wo_plus_b(a, b) {return ";
916 const char* one_byte_extern_1 = "a * 2 + b;} a_times_two_plus_b(4, 8) + ";
917 const char* two_byte_extern_1 = "a_times_two_plus_b(4, 8) + ";
918 const char* one_byte_string_2 = "a_times_two_plus_b(4, 8) + ";
919 const char* two_byte_string_2 = "a_times_two_plus_b(4, 8) + ";
920 const char* two_byte_extern_2 = "a_times_two_plus_b(1, 2);";
921 Local<String> left = v8_str(one_byte_string_1);
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000922
923 uint16_t* two_byte_source = AsciiToTwoByteString(two_byte_string_1);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +0000924 Local<String> right =
925 String::NewFromTwoByte(env->GetIsolate(), two_byte_source);
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000926 i::DeleteArray(two_byte_source);
927
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000928 Local<String> source = String::Concat(left, right);
929 right = String::NewExternal(
machenbach@chromium.org9f18d912013-11-28 13:42:41 +0000930 env->GetIsolate(), new TestAsciiResource(i::StrDup(one_byte_extern_1)));
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000931 source = String::Concat(source, right);
932 right = String::NewExternal(
machenbach@chromium.org9f18d912013-11-28 13:42:41 +0000933 env->GetIsolate(),
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000934 new TestResource(AsciiToTwoByteString(two_byte_extern_1)));
935 source = String::Concat(source, right);
936 right = v8_str(one_byte_string_2);
937 source = String::Concat(source, right);
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000938
939 two_byte_source = AsciiToTwoByteString(two_byte_string_2);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +0000940 right = String::NewFromTwoByte(env->GetIsolate(), two_byte_source);
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000941 i::DeleteArray(two_byte_source);
942
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000943 source = String::Concat(source, right);
944 right = String::NewExternal(
machenbach@chromium.org9f18d912013-11-28 13:42:41 +0000945 env->GetIsolate(),
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000946 new TestResource(AsciiToTwoByteString(two_byte_extern_2)));
947 source = String::Concat(source, right);
948 Local<Script> script = Script::Compile(source);
949 Local<Value> value = script->Run();
950 CHECK(value->IsNumber());
951 CHECK_EQ(68, value->Int32Value());
952 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000953 CcTest::i_isolate()->compilation_cache()->Clear();
954 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
955 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000956}
957
958
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000959THREADED_TEST(GlobalProperties) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000960 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000961 v8::HandleScope scope(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000962 v8::Handle<v8::Object> global = env->Global();
963 global->Set(v8_str("pi"), v8_num(3.1415926));
964 Local<Value> pi = global->Get(v8_str("pi"));
965 CHECK_EQ(3.1415926, pi->NumberValue());
966}
967
968
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +0000969template<typename T>
dslomov@chromium.orgb752d402013-06-18 11:54:54 +0000970static void CheckReturnValue(const T& t, i::Address callback) {
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +0000971 v8::ReturnValue<v8::Value> rv = t.GetReturnValue();
972 i::Object** o = *reinterpret_cast<i::Object***>(&rv);
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000973 CHECK_EQ(CcTest::isolate(), t.GetIsolate());
svenpanne@chromium.org53ad1752013-05-27 12:20:38 +0000974 CHECK_EQ(t.GetIsolate(), rv.GetIsolate());
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +0000975 CHECK((*o)->IsTheHole() || (*o)->IsUndefined());
verwaest@chromium.org8a00e822013-06-10 15:11:22 +0000976 // Verify reset
977 bool is_runtime = (*o)->IsTheHole();
978 rv.Set(true);
979 CHECK(!(*o)->IsTheHole() && !(*o)->IsUndefined());
980 rv.Set(v8::Handle<v8::Object>());
981 CHECK((*o)->IsTheHole() || (*o)->IsUndefined());
982 CHECK_EQ(is_runtime, (*o)->IsTheHole());
dslomov@chromium.orgb752d402013-06-18 11:54:54 +0000983
984 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(t.GetIsolate());
985 // If CPU profiler is active check that when API callback is invoked
986 // VMState is set to EXTERNAL.
987 if (isolate->cpu_profiler()->is_profiling()) {
988 CHECK_EQ(i::EXTERNAL, isolate->current_vm_state());
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +0000989 CHECK(isolate->external_callback_scope());
990 CHECK_EQ(callback, isolate->external_callback_scope()->callback());
dslomov@chromium.orgb752d402013-06-18 11:54:54 +0000991 }
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +0000992}
993
dslomov@chromium.orgb752d402013-06-18 11:54:54 +0000994
995static void handle_callback_impl(const v8::FunctionCallbackInfo<Value>& info,
996 i::Address callback) {
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +0000997 ApiTestFuzzer::Fuzz();
dslomov@chromium.orgb752d402013-06-18 11:54:54 +0000998 CheckReturnValue(info, callback);
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +0000999 info.GetReturnValue().Set(v8_str("bad value"));
1000 info.GetReturnValue().Set(v8_num(102));
1001}
1002
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001003
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001004static void handle_callback(const v8::FunctionCallbackInfo<Value>& info) {
1005 return handle_callback_impl(info, FUNCTION_ADDR(handle_callback));
1006}
1007
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001008
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00001009static void handle_callback_2(const v8::FunctionCallbackInfo<Value>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001010 return handle_callback_impl(info, FUNCTION_ADDR(handle_callback_2));
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00001011}
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001012
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001013static void construct_callback(
1014 const v8::FunctionCallbackInfo<Value>& info) {
1015 ApiTestFuzzer::Fuzz();
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001016 CheckReturnValue(info, FUNCTION_ADDR(construct_callback));
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001017 info.This()->Set(v8_str("x"), v8_num(1));
1018 info.This()->Set(v8_str("y"), v8_num(2));
1019 info.GetReturnValue().Set(v8_str("bad value"));
1020 info.GetReturnValue().Set(info.This());
ager@chromium.orgb61a0d12010-10-13 08:35:23 +00001021}
1022
1023
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001024static void Return239Callback(
1025 Local<String> name, const v8::PropertyCallbackInfo<Value>& info) {
1026 ApiTestFuzzer::Fuzz();
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001027 CheckReturnValue(info, FUNCTION_ADDR(Return239Callback));
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001028 info.GetReturnValue().Set(v8_str("bad value"));
1029 info.GetReturnValue().Set(v8_num(239));
1030}
1031
1032
1033template<typename Handler>
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00001034static void TestFunctionTemplateInitializer(Handler handler,
1035 Handler handler_2) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001036 // Test constructor calls.
1037 {
1038 LocalContext env;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001039 v8::Isolate* isolate = env->GetIsolate();
1040 v8::HandleScope scope(isolate);
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001041
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001042 Local<v8::FunctionTemplate> fun_templ =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001043 v8::FunctionTemplate::New(isolate, handler);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001044 Local<Function> fun = fun_templ->GetFunction();
1045 env->Global()->Set(v8_str("obj"), fun);
1046 Local<Script> script = v8_compile("obj()");
1047 for (int i = 0; i < 30; i++) {
1048 CHECK_EQ(102, script->Run()->Int32Value());
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001049 }
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001050 }
1051 // Use SetCallHandler to initialize a function template, should work like
1052 // the previous one.
1053 {
1054 LocalContext env;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001055 v8::Isolate* isolate = env->GetIsolate();
1056 v8::HandleScope scope(isolate);
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001057
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001058 Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(isolate);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001059 fun_templ->SetCallHandler(handler_2);
1060 Local<Function> fun = fun_templ->GetFunction();
1061 env->Global()->Set(v8_str("obj"), fun);
1062 Local<Script> script = v8_compile("obj()");
1063 for (int i = 0; i < 30; i++) {
1064 CHECK_EQ(102, script->Run()->Int32Value());
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001065 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001066 }
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001067}
1068
1069
1070template<typename Constructor, typename Accessor>
1071static void TestFunctionTemplateAccessor(Constructor constructor,
1072 Accessor accessor) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001073 LocalContext env;
1074 v8::HandleScope scope(env->GetIsolate());
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001075
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001076 Local<v8::FunctionTemplate> fun_templ =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001077 v8::FunctionTemplate::New(env->GetIsolate(), constructor);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001078 fun_templ->SetClassName(v8_str("funky"));
1079 fun_templ->InstanceTemplate()->SetAccessor(v8_str("m"), accessor);
1080 Local<Function> fun = fun_templ->GetFunction();
1081 env->Global()->Set(v8_str("obj"), fun);
1082 Local<Value> result = v8_compile("(new obj()).toString()")->Run();
1083 CHECK_EQ(v8_str("[object funky]"), result);
1084 CompileRun("var obj_instance = new obj();");
1085 Local<Script> script;
1086 script = v8_compile("obj_instance.x");
1087 for (int i = 0; i < 30; i++) {
1088 CHECK_EQ(1, script->Run()->Int32Value());
1089 }
1090 script = v8_compile("obj_instance.m");
1091 for (int i = 0; i < 30; i++) {
1092 CHECK_EQ(239, script->Run()->Int32Value());
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001093 }
1094}
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001095
ager@chromium.orgb61a0d12010-10-13 08:35:23 +00001096
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001097THREADED_PROFILED_TEST(FunctionTemplate) {
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00001098 TestFunctionTemplateInitializer(handle_callback, handle_callback_2);
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001099 TestFunctionTemplateAccessor(construct_callback, Return239Callback);
1100}
1101
1102
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001103static void SimpleCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
1104 ApiTestFuzzer::Fuzz();
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001105 CheckReturnValue(info, FUNCTION_ADDR(SimpleCallback));
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001106 info.GetReturnValue().Set(v8_num(51423 + info.Length()));
1107}
1108
1109
1110template<typename Callback>
1111static void TestSimpleCallback(Callback callback) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001112 LocalContext env;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00001113 v8::Isolate* isolate = env->GetIsolate();
1114 v8::HandleScope scope(isolate);
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001115
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00001116 v8::Handle<v8::ObjectTemplate> object_template =
1117 v8::ObjectTemplate::New(isolate);
1118 object_template->Set(isolate, "callback",
1119 v8::FunctionTemplate::New(isolate, callback));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001120 v8::Local<v8::Object> object = object_template->NewInstance();
1121 (*env)->Global()->Set(v8_str("callback_object"), object);
1122 v8::Handle<v8::Script> script;
1123 script = v8_compile("callback_object.callback(17)");
1124 for (int i = 0; i < 30; i++) {
1125 CHECK_EQ(51424, script->Run()->Int32Value());
1126 }
1127 script = v8_compile("callback_object.callback(17, 24)");
1128 for (int i = 0; i < 30; i++) {
1129 CHECK_EQ(51425, script->Run()->Int32Value());
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001130 }
1131}
1132
1133
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001134THREADED_PROFILED_TEST(SimpleCallback) {
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001135 TestSimpleCallback(SimpleCallback);
1136}
1137
1138
1139template<typename T>
1140void FastReturnValueCallback(const v8::FunctionCallbackInfo<v8::Value>& info);
1141
1142// constant return values
danno@chromium.org1fd77d52013-06-07 16:01:45 +00001143static int32_t fast_return_value_int32 = 471;
1144static uint32_t fast_return_value_uint32 = 571;
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001145static const double kFastReturnValueDouble = 2.7;
1146// variable return values
1147static bool fast_return_value_bool = false;
ulan@chromium.org837a67e2013-06-11 15:39:48 +00001148enum ReturnValueOddball {
1149 kNullReturnValue,
1150 kUndefinedReturnValue,
1151 kEmptyStringReturnValue
1152};
1153static ReturnValueOddball fast_return_value_void;
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00001154static bool fast_return_value_object_is_empty = false;
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001155
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001156// Helper function to avoid compiler error: insufficient contextual information
1157// to determine type when applying FUNCTION_ADDR to a template function.
1158static i::Address address_of(v8::FunctionCallback callback) {
1159 return FUNCTION_ADDR(callback);
1160}
1161
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001162template<>
1163void FastReturnValueCallback<int32_t>(
1164 const v8::FunctionCallbackInfo<v8::Value>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001165 CheckReturnValue(info, address_of(FastReturnValueCallback<int32_t>));
danno@chromium.org1fd77d52013-06-07 16:01:45 +00001166 info.GetReturnValue().Set(fast_return_value_int32);
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001167}
1168
1169template<>
1170void FastReturnValueCallback<uint32_t>(
1171 const v8::FunctionCallbackInfo<v8::Value>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001172 CheckReturnValue(info, address_of(FastReturnValueCallback<uint32_t>));
danno@chromium.org1fd77d52013-06-07 16:01:45 +00001173 info.GetReturnValue().Set(fast_return_value_uint32);
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001174}
1175
1176template<>
1177void FastReturnValueCallback<double>(
1178 const v8::FunctionCallbackInfo<v8::Value>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001179 CheckReturnValue(info, address_of(FastReturnValueCallback<double>));
svenpanne@chromium.org53ad1752013-05-27 12:20:38 +00001180 info.GetReturnValue().Set(kFastReturnValueDouble);
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001181}
1182
1183template<>
1184void FastReturnValueCallback<bool>(
1185 const v8::FunctionCallbackInfo<v8::Value>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001186 CheckReturnValue(info, address_of(FastReturnValueCallback<bool>));
svenpanne@chromium.org53ad1752013-05-27 12:20:38 +00001187 info.GetReturnValue().Set(fast_return_value_bool);
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001188}
1189
1190template<>
1191void FastReturnValueCallback<void>(
1192 const v8::FunctionCallbackInfo<v8::Value>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00001193 CheckReturnValue(info, address_of(FastReturnValueCallback<void>));
ulan@chromium.org837a67e2013-06-11 15:39:48 +00001194 switch (fast_return_value_void) {
1195 case kNullReturnValue:
1196 info.GetReturnValue().SetNull();
1197 break;
1198 case kUndefinedReturnValue:
1199 info.GetReturnValue().SetUndefined();
1200 break;
1201 case kEmptyStringReturnValue:
1202 info.GetReturnValue().SetEmptyString();
1203 break;
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001204 }
1205}
1206
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +00001207template<>
1208void FastReturnValueCallback<Object>(
1209 const v8::FunctionCallbackInfo<v8::Value>& info) {
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00001210 v8::Handle<v8::Object> object;
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001211 if (!fast_return_value_object_is_empty) {
1212 object = Object::New(info.GetIsolate());
1213 }
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00001214 info.GetReturnValue().Set(object);
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +00001215}
1216
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001217template<typename T>
1218Handle<Value> TestFastReturnValues() {
1219 LocalContext env;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00001220 v8::Isolate* isolate = env->GetIsolate();
1221 v8::EscapableHandleScope scope(isolate);
1222 v8::Handle<v8::ObjectTemplate> object_template =
1223 v8::ObjectTemplate::New(isolate);
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001224 v8::FunctionCallback callback = &FastReturnValueCallback<T>;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00001225 object_template->Set(isolate, "callback",
1226 v8::FunctionTemplate::New(isolate, callback));
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001227 v8::Local<v8::Object> object = object_template->NewInstance();
1228 (*env)->Global()->Set(v8_str("callback_object"), object);
machenbach@chromium.orgafbdadc2013-12-09 16:12:18 +00001229 return scope.Escape(CompileRun("callback_object.callback()"));
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001230}
1231
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001232
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001233THREADED_PROFILED_TEST(FastReturnValues) {
danno@chromium.org1fd77d52013-06-07 16:01:45 +00001234 LocalContext env;
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001235 v8::HandleScope scope(CcTest::isolate());
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001236 v8::Handle<v8::Value> value;
danno@chromium.org1fd77d52013-06-07 16:01:45 +00001237 // check int32_t and uint32_t
1238 int32_t int_values[] = {
1239 0, 234, -723,
1240 i::Smi::kMinValue, i::Smi::kMaxValue
1241 };
1242 for (size_t i = 0; i < ARRAY_SIZE(int_values); i++) {
1243 for (int modifier = -1; modifier <= 1; modifier++) {
1244 int int_value = int_values[i] + modifier;
1245 // check int32_t
1246 fast_return_value_int32 = int_value;
1247 value = TestFastReturnValues<int32_t>();
1248 CHECK(value->IsInt32());
1249 CHECK(fast_return_value_int32 == value->Int32Value());
1250 // check uint32_t
1251 fast_return_value_uint32 = static_cast<uint32_t>(int_value);
1252 value = TestFastReturnValues<uint32_t>();
1253 CHECK(value->IsUint32());
1254 CHECK(fast_return_value_uint32 == value->Uint32Value());
1255 }
1256 }
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001257 // check double
1258 value = TestFastReturnValues<double>();
1259 CHECK(value->IsNumber());
1260 CHECK_EQ(kFastReturnValueDouble, value->ToNumber()->Value());
1261 // check bool values
1262 for (int i = 0; i < 2; i++) {
1263 fast_return_value_bool = i == 0;
1264 value = TestFastReturnValues<bool>();
1265 CHECK(value->IsBoolean());
1266 CHECK_EQ(fast_return_value_bool, value->ToBoolean()->Value());
1267 }
1268 // check oddballs
ulan@chromium.org837a67e2013-06-11 15:39:48 +00001269 ReturnValueOddball oddballs[] = {
1270 kNullReturnValue,
1271 kUndefinedReturnValue,
1272 kEmptyStringReturnValue
1273 };
1274 for (size_t i = 0; i < ARRAY_SIZE(oddballs); i++) {
1275 fast_return_value_void = oddballs[i];
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001276 value = TestFastReturnValues<void>();
ulan@chromium.org837a67e2013-06-11 15:39:48 +00001277 switch (fast_return_value_void) {
1278 case kNullReturnValue:
1279 CHECK(value->IsNull());
1280 break;
1281 case kUndefinedReturnValue:
1282 CHECK(value->IsUndefined());
1283 break;
1284 case kEmptyStringReturnValue:
1285 CHECK(value->IsString());
1286 CHECK_EQ(0, v8::String::Cast(*value)->Length());
1287 break;
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001288 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001289 }
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00001290 // check handles
1291 fast_return_value_object_is_empty = false;
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +00001292 value = TestFastReturnValues<Object>();
1293 CHECK(value->IsObject());
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00001294 fast_return_value_object_is_empty = true;
1295 value = TestFastReturnValues<Object>();
1296 CHECK(value->IsUndefined());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001297}
1298
1299
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001300THREADED_TEST(FunctionTemplateSetLength) {
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001301 LocalContext env;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001302 v8::Isolate* isolate = env->GetIsolate();
1303 v8::HandleScope scope(isolate);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001304 {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001305 Local<v8::FunctionTemplate> fun_templ =
1306 v8::FunctionTemplate::New(isolate,
1307 handle_callback,
1308 Handle<v8::Value>(),
1309 Handle<v8::Signature>(),
1310 23);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001311 Local<Function> fun = fun_templ->GetFunction();
1312 env->Global()->Set(v8_str("obj"), fun);
1313 Local<Script> script = v8_compile("obj.length");
1314 CHECK_EQ(23, script->Run()->Int32Value());
1315 }
1316 {
1317 Local<v8::FunctionTemplate> fun_templ =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001318 v8::FunctionTemplate::New(isolate, handle_callback);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001319 fun_templ->SetLength(22);
1320 Local<Function> fun = fun_templ->GetFunction();
1321 env->Global()->Set(v8_str("obj"), fun);
1322 Local<Script> script = v8_compile("obj.length");
1323 CHECK_EQ(22, script->Run()->Int32Value());
1324 }
1325 {
1326 // Without setting length it defaults to 0.
1327 Local<v8::FunctionTemplate> fun_templ =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001328 v8::FunctionTemplate::New(isolate, handle_callback);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +00001329 Local<Function> fun = fun_templ->GetFunction();
1330 env->Global()->Set(v8_str("obj"), fun);
1331 Local<Script> script = v8_compile("obj.length");
1332 CHECK_EQ(0, script->Run()->Int32Value());
1333 }
1334}
1335
1336
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001337static void* expected_ptr;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001338static void callback(const v8::FunctionCallbackInfo<v8::Value>& args) {
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00001339 void* ptr = v8::External::Cast(*args.Data())->Value();
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001340 CHECK_EQ(expected_ptr, ptr);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001341 args.GetReturnValue().Set(true);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001342}
1343
1344
1345static void TestExternalPointerWrapping() {
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001346 LocalContext env;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001347 v8::Isolate* isolate = env->GetIsolate();
1348 v8::HandleScope scope(isolate);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001349
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00001350 v8::Handle<v8::Value> data =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001351 v8::External::New(isolate, expected_ptr);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001352
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001353 v8::Handle<v8::Object> obj = v8::Object::New(isolate);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001354 obj->Set(v8_str("func"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001355 v8::FunctionTemplate::New(isolate, callback, data)->GetFunction());
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001356 env->Global()->Set(v8_str("obj"), obj);
1357
1358 CHECK(CompileRun(
1359 "function foo() {\n"
1360 " for (var i = 0; i < 13; i++) obj.func();\n"
1361 "}\n"
1362 "foo(), true")->BooleanValue());
1363}
1364
1365
1366THREADED_TEST(ExternalWrap) {
1367 // Check heap allocated object.
1368 int* ptr = new int;
1369 expected_ptr = ptr;
1370 TestExternalPointerWrapping();
1371 delete ptr;
1372
1373 // Check stack allocated object.
1374 int foo;
1375 expected_ptr = &foo;
1376 TestExternalPointerWrapping();
1377
1378 // Check not aligned addresses.
1379 const int n = 100;
1380 char* s = new char[n];
1381 for (int i = 0; i < n; i++) {
1382 expected_ptr = s + i;
1383 TestExternalPointerWrapping();
1384 }
1385
1386 delete[] s;
1387
1388 // Check several invalid addresses.
1389 expected_ptr = reinterpret_cast<void*>(1);
1390 TestExternalPointerWrapping();
1391
1392 expected_ptr = reinterpret_cast<void*>(0xdeadbeef);
1393 TestExternalPointerWrapping();
1394
1395 expected_ptr = reinterpret_cast<void*>(0xdeadbeef + 1);
1396 TestExternalPointerWrapping();
1397
1398#if defined(V8_HOST_ARCH_X64)
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001399 // Check a value with a leading 1 bit in x64 Smi encoding.
1400 expected_ptr = reinterpret_cast<void*>(0x400000000);
1401 TestExternalPointerWrapping();
1402
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00001403 expected_ptr = reinterpret_cast<void*>(0xdeadbeefdeadbeef);
1404 TestExternalPointerWrapping();
1405
1406 expected_ptr = reinterpret_cast<void*>(0xdeadbeefdeadbeef + 1);
1407 TestExternalPointerWrapping();
1408#endif
1409}
1410
1411
sgjesse@chromium.org900d3b72009-08-07 11:24:25 +00001412THREADED_TEST(FindInstanceInPrototypeChain) {
sgjesse@chromium.org900d3b72009-08-07 11:24:25 +00001413 LocalContext env;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001414 v8::Isolate* isolate = env->GetIsolate();
1415 v8::HandleScope scope(isolate);
sgjesse@chromium.org900d3b72009-08-07 11:24:25 +00001416
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001417 Local<v8::FunctionTemplate> base = v8::FunctionTemplate::New(isolate);
1418 Local<v8::FunctionTemplate> derived = v8::FunctionTemplate::New(isolate);
1419 Local<v8::FunctionTemplate> other = v8::FunctionTemplate::New(isolate);
sgjesse@chromium.org900d3b72009-08-07 11:24:25 +00001420 derived->Inherit(base);
1421
1422 Local<v8::Function> base_function = base->GetFunction();
1423 Local<v8::Function> derived_function = derived->GetFunction();
1424 Local<v8::Function> other_function = other->GetFunction();
1425
1426 Local<v8::Object> base_instance = base_function->NewInstance();
1427 Local<v8::Object> derived_instance = derived_function->NewInstance();
1428 Local<v8::Object> derived_instance2 = derived_function->NewInstance();
1429 Local<v8::Object> other_instance = other_function->NewInstance();
1430 derived_instance2->Set(v8_str("__proto__"), derived_instance);
1431 other_instance->Set(v8_str("__proto__"), derived_instance2);
1432
1433 // base_instance is only an instance of base.
1434 CHECK_EQ(base_instance,
1435 base_instance->FindInstanceInPrototypeChain(base));
1436 CHECK(base_instance->FindInstanceInPrototypeChain(derived).IsEmpty());
1437 CHECK(base_instance->FindInstanceInPrototypeChain(other).IsEmpty());
1438
1439 // derived_instance is an instance of base and derived.
1440 CHECK_EQ(derived_instance,
1441 derived_instance->FindInstanceInPrototypeChain(base));
1442 CHECK_EQ(derived_instance,
1443 derived_instance->FindInstanceInPrototypeChain(derived));
1444 CHECK(derived_instance->FindInstanceInPrototypeChain(other).IsEmpty());
1445
1446 // other_instance is an instance of other and its immediate
1447 // prototype derived_instance2 is an instance of base and derived.
1448 // Note, derived_instance is an instance of base and derived too,
1449 // but it comes after derived_instance2 in the prototype chain of
1450 // other_instance.
1451 CHECK_EQ(derived_instance2,
1452 other_instance->FindInstanceInPrototypeChain(base));
1453 CHECK_EQ(derived_instance2,
1454 other_instance->FindInstanceInPrototypeChain(derived));
1455 CHECK_EQ(other_instance,
1456 other_instance->FindInstanceInPrototypeChain(other));
1457}
1458
1459
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001460THREADED_TEST(TinyInteger) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001461 LocalContext env;
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001462 v8::Isolate* isolate = env->GetIsolate();
1463 v8::HandleScope scope(isolate);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001464
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001465 int32_t value = 239;
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001466 Local<v8::Integer> value_obj = v8::Integer::New(isolate, value);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001467 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001468
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001469 value_obj = v8::Integer::New(isolate, value);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001470 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001471}
1472
1473
1474THREADED_TEST(BigSmiInteger) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001475 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001476 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001477 v8::Isolate* isolate = CcTest::isolate();
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001478
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001479 int32_t value = i::Smi::kMaxValue;
1480 // We cannot add one to a Smi::kMaxValue without wrapping.
verwaest@chromium.org662436e2013-08-28 08:41:27 +00001481 if (i::SmiValuesAre31Bits()) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001482 CHECK(i::Smi::IsValid(value));
1483 CHECK(!i::Smi::IsValid(value + 1));
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001484
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001485 Local<v8::Integer> value_obj = v8::Integer::New(isolate, value);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001486 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001487
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001488 value_obj = v8::Integer::New(isolate, value);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001489 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001490 }
1491}
1492
1493
1494THREADED_TEST(BigInteger) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001495 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001496 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001497 v8::Isolate* isolate = CcTest::isolate();
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001498
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001499 // We cannot add one to a Smi::kMaxValue without wrapping.
verwaest@chromium.org662436e2013-08-28 08:41:27 +00001500 if (i::SmiValuesAre31Bits()) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001501 // The casts allow this to compile, even if Smi::kMaxValue is 2^31-1.
1502 // The code will not be run in that case, due to the "if" guard.
1503 int32_t value =
1504 static_cast<int32_t>(static_cast<uint32_t>(i::Smi::kMaxValue) + 1);
1505 CHECK(value > i::Smi::kMaxValue);
1506 CHECK(!i::Smi::IsValid(value));
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001507
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001508 Local<v8::Integer> value_obj = v8::Integer::New(isolate, value);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001509 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001510
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001511 value_obj = v8::Integer::New(isolate, value);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001512 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001513 }
1514}
1515
1516
1517THREADED_TEST(TinyUnsignedInteger) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001518 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001519 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001520 v8::Isolate* isolate = CcTest::isolate();
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001521
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001522 uint32_t value = 239;
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001523
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001524 Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001525 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001526
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001527 value_obj = v8::Integer::NewFromUnsigned(isolate, value);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001528 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001529}
1530
1531
1532THREADED_TEST(BigUnsignedSmiInteger) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001533 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001534 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001535 v8::Isolate* isolate = CcTest::isolate();
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001536
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001537 uint32_t value = static_cast<uint32_t>(i::Smi::kMaxValue);
1538 CHECK(i::Smi::IsValid(value));
1539 CHECK(!i::Smi::IsValid(value + 1));
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001540
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001541 Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001542 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001543
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001544 value_obj = v8::Integer::NewFromUnsigned(isolate, value);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001545 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001546}
1547
1548
1549THREADED_TEST(BigUnsignedInteger) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001550 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001551 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001552 v8::Isolate* isolate = CcTest::isolate();
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001553
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001554 uint32_t value = static_cast<uint32_t>(i::Smi::kMaxValue) + 1;
1555 CHECK(value > static_cast<uint32_t>(i::Smi::kMaxValue));
1556 CHECK(!i::Smi::IsValid(value));
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001557
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001558 Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001559 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001560
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001561 value_obj = v8::Integer::NewFromUnsigned(isolate, value);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001562 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001563}
1564
1565
1566THREADED_TEST(OutOfSignedRangeUnsignedInteger) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001567 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001568 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001569 v8::Isolate* isolate = CcTest::isolate();
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001570
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001571 uint32_t INT32_MAX_AS_UINT = (1U << 31) - 1;
1572 uint32_t value = INT32_MAX_AS_UINT + 1;
1573 CHECK(value > INT32_MAX_AS_UINT); // No overflow.
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001574
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001575 Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001576 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001577
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001578 value_obj = v8::Integer::NewFromUnsigned(isolate, value);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001579 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001580}
1581
1582
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001583THREADED_TEST(IsNativeError) {
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001584 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001585 v8::HandleScope scope(env->GetIsolate());
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001586 v8::Handle<Value> syntax_error = CompileRun(
1587 "var out = 0; try { eval(\"#\"); } catch(x) { out = x; } out; ");
1588 CHECK(syntax_error->IsNativeError());
1589 v8::Handle<Value> not_error = CompileRun("{a:42}");
1590 CHECK(!not_error->IsNativeError());
1591 v8::Handle<Value> not_object = CompileRun("42");
1592 CHECK(!not_object->IsNativeError());
1593}
1594
1595
1596THREADED_TEST(StringObject) {
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001597 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001598 v8::HandleScope scope(env->GetIsolate());
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001599 v8::Handle<Value> boxed_string = CompileRun("new String(\"test\")");
1600 CHECK(boxed_string->IsStringObject());
1601 v8::Handle<Value> unboxed_string = CompileRun("\"test\"");
1602 CHECK(!unboxed_string->IsStringObject());
1603 v8::Handle<Value> boxed_not_string = CompileRun("new Number(42)");
1604 CHECK(!boxed_not_string->IsStringObject());
1605 v8::Handle<Value> not_object = CompileRun("0");
1606 CHECK(!not_object->IsStringObject());
1607 v8::Handle<v8::StringObject> as_boxed = boxed_string.As<v8::StringObject>();
1608 CHECK(!as_boxed.IsEmpty());
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001609 Local<v8::String> the_string = as_boxed->ValueOf();
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001610 CHECK(!the_string.IsEmpty());
1611 ExpectObject("\"test\"", the_string);
1612 v8::Handle<v8::Value> new_boxed_string = v8::StringObject::New(the_string);
1613 CHECK(new_boxed_string->IsStringObject());
1614 as_boxed = new_boxed_string.As<v8::StringObject>();
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001615 the_string = as_boxed->ValueOf();
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001616 CHECK(!the_string.IsEmpty());
1617 ExpectObject("\"test\"", the_string);
1618}
1619
1620
1621THREADED_TEST(NumberObject) {
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001622 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001623 v8::HandleScope scope(env->GetIsolate());
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001624 v8::Handle<Value> boxed_number = CompileRun("new Number(42)");
1625 CHECK(boxed_number->IsNumberObject());
1626 v8::Handle<Value> unboxed_number = CompileRun("42");
1627 CHECK(!unboxed_number->IsNumberObject());
1628 v8::Handle<Value> boxed_not_number = CompileRun("new Boolean(false)");
1629 CHECK(!boxed_not_number->IsNumberObject());
1630 v8::Handle<v8::NumberObject> as_boxed = boxed_number.As<v8::NumberObject>();
1631 CHECK(!as_boxed.IsEmpty());
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001632 double the_number = as_boxed->ValueOf();
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001633 CHECK_EQ(42.0, the_number);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +00001634 v8::Handle<v8::Value> new_boxed_number =
1635 v8::NumberObject::New(env->GetIsolate(), 43);
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001636 CHECK(new_boxed_number->IsNumberObject());
1637 as_boxed = new_boxed_number.As<v8::NumberObject>();
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001638 the_number = as_boxed->ValueOf();
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001639 CHECK_EQ(43.0, the_number);
1640}
1641
1642
1643THREADED_TEST(BooleanObject) {
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001644 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001645 v8::HandleScope scope(env->GetIsolate());
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001646 v8::Handle<Value> boxed_boolean = CompileRun("new Boolean(true)");
1647 CHECK(boxed_boolean->IsBooleanObject());
1648 v8::Handle<Value> unboxed_boolean = CompileRun("true");
1649 CHECK(!unboxed_boolean->IsBooleanObject());
1650 v8::Handle<Value> boxed_not_boolean = CompileRun("new Number(42)");
1651 CHECK(!boxed_not_boolean->IsBooleanObject());
1652 v8::Handle<v8::BooleanObject> as_boxed =
1653 boxed_boolean.As<v8::BooleanObject>();
1654 CHECK(!as_boxed.IsEmpty());
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001655 bool the_boolean = as_boxed->ValueOf();
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001656 CHECK_EQ(true, the_boolean);
1657 v8::Handle<v8::Value> boxed_true = v8::BooleanObject::New(true);
1658 v8::Handle<v8::Value> boxed_false = v8::BooleanObject::New(false);
1659 CHECK(boxed_true->IsBooleanObject());
1660 CHECK(boxed_false->IsBooleanObject());
1661 as_boxed = boxed_true.As<v8::BooleanObject>();
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001662 CHECK_EQ(true, as_boxed->ValueOf());
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001663 as_boxed = boxed_false.As<v8::BooleanObject>();
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001664 CHECK_EQ(false, as_boxed->ValueOf());
1665}
1666
1667
1668THREADED_TEST(PrimitiveAndWrappedBooleans) {
1669 LocalContext env;
1670 v8::HandleScope scope(env->GetIsolate());
1671
machenbach@chromium.org37be4082013-11-26 13:50:38 +00001672 Local<Value> primitive_false = Boolean::New(env->GetIsolate(), false);
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001673 CHECK(primitive_false->IsBoolean());
1674 CHECK(!primitive_false->IsBooleanObject());
1675 CHECK(!primitive_false->BooleanValue());
1676 CHECK(!primitive_false->IsTrue());
1677 CHECK(primitive_false->IsFalse());
1678
1679 Local<Value> false_value = BooleanObject::New(false);
1680 CHECK(!false_value->IsBoolean());
1681 CHECK(false_value->IsBooleanObject());
1682 CHECK(false_value->BooleanValue());
1683 CHECK(!false_value->IsTrue());
1684 CHECK(!false_value->IsFalse());
1685
1686 Local<BooleanObject> false_boolean_object = false_value.As<BooleanObject>();
1687 CHECK(!false_boolean_object->IsBoolean());
1688 CHECK(false_boolean_object->IsBooleanObject());
1689 // TODO(svenpanne) Uncomment when BooleanObject::BooleanValue() is deleted.
1690 // CHECK(false_boolean_object->BooleanValue());
1691 CHECK(!false_boolean_object->ValueOf());
1692 CHECK(!false_boolean_object->IsTrue());
1693 CHECK(!false_boolean_object->IsFalse());
1694
machenbach@chromium.org37be4082013-11-26 13:50:38 +00001695 Local<Value> primitive_true = Boolean::New(env->GetIsolate(), true);
danno@chromium.orgd3c42102013-08-01 16:58:23 +00001696 CHECK(primitive_true->IsBoolean());
1697 CHECK(!primitive_true->IsBooleanObject());
1698 CHECK(primitive_true->BooleanValue());
1699 CHECK(primitive_true->IsTrue());
1700 CHECK(!primitive_true->IsFalse());
1701
1702 Local<Value> true_value = BooleanObject::New(true);
1703 CHECK(!true_value->IsBoolean());
1704 CHECK(true_value->IsBooleanObject());
1705 CHECK(true_value->BooleanValue());
1706 CHECK(!true_value->IsTrue());
1707 CHECK(!true_value->IsFalse());
1708
1709 Local<BooleanObject> true_boolean_object = true_value.As<BooleanObject>();
1710 CHECK(!true_boolean_object->IsBoolean());
1711 CHECK(true_boolean_object->IsBooleanObject());
1712 // TODO(svenpanne) Uncomment when BooleanObject::BooleanValue() is deleted.
1713 // CHECK(true_boolean_object->BooleanValue());
1714 CHECK(true_boolean_object->ValueOf());
1715 CHECK(!true_boolean_object->IsTrue());
1716 CHECK(!true_boolean_object->IsFalse());
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +00001717}
1718
1719
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001720THREADED_TEST(Number) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001721 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001722 v8::HandleScope scope(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001723 double PI = 3.1415926;
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001724 Local<v8::Number> pi_obj = v8::Number::New(env->GetIsolate(), PI);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001725 CHECK_EQ(PI, pi_obj->NumberValue());
1726}
1727
1728
1729THREADED_TEST(ToNumber) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001730 LocalContext env;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00001731 v8::Isolate* isolate = CcTest::isolate();
1732 v8::HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001733 Local<String> str = v8_str("3.1415926");
1734 CHECK_EQ(3.1415926, str->NumberValue());
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00001735 v8::Handle<v8::Boolean> t = v8::True(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001736 CHECK_EQ(1.0, t->NumberValue());
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00001737 v8::Handle<v8::Boolean> f = v8::False(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001738 CHECK_EQ(0.0, f->NumberValue());
1739}
1740
1741
1742THREADED_TEST(Date) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001743 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00001744 v8::HandleScope scope(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001745 double PI = 3.1415926;
machenbach@chromium.org9f18d912013-11-28 13:42:41 +00001746 Local<Value> date = v8::Date::New(env->GetIsolate(), PI);
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +00001747 CHECK_EQ(3.0, date->NumberValue());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001748 date.As<v8::Date>()->Set(v8_str("property"),
1749 v8::Integer::New(env->GetIsolate(), 42));
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +00001750 CHECK_EQ(42, date.As<v8::Date>()->Get(v8_str("property"))->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001751}
1752
1753
1754THREADED_TEST(Boolean) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001755 LocalContext env;
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001756 v8::Isolate* isolate = env->GetIsolate();
1757 v8::HandleScope scope(isolate);
1758 v8::Handle<v8::Boolean> t = v8::True(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001759 CHECK(t->Value());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001760 v8::Handle<v8::Boolean> f = v8::False(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001761 CHECK(!f->Value());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001762 v8::Handle<v8::Primitive> u = v8::Undefined(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001763 CHECK(!u->BooleanValue());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001764 v8::Handle<v8::Primitive> n = v8::Null(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001765 CHECK(!n->BooleanValue());
1766 v8::Handle<String> str1 = v8_str("");
1767 CHECK(!str1->BooleanValue());
1768 v8::Handle<String> str2 = v8_str("x");
1769 CHECK(str2->BooleanValue());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00001770 CHECK(!v8::Number::New(isolate, 0)->BooleanValue());
1771 CHECK(v8::Number::New(isolate, -1)->BooleanValue());
1772 CHECK(v8::Number::New(isolate, 1)->BooleanValue());
1773 CHECK(v8::Number::New(isolate, 42)->BooleanValue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001774 CHECK(!v8_compile("NaN")->Run()->BooleanValue());
1775}
1776
1777
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001778static void DummyCallHandler(const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001779 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001780 args.GetReturnValue().Set(v8_num(13.4));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001781}
1782
1783
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001784static void GetM(Local<String> name,
1785 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001786 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001787 info.GetReturnValue().Set(v8_num(876));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001788}
1789
1790
1791THREADED_TEST(GlobalPrototype) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001792 v8::Isolate* isolate = CcTest::isolate();
1793 v8::HandleScope scope(isolate);
1794 v8::Handle<v8::FunctionTemplate> func_templ =
1795 v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001796 func_templ->PrototypeTemplate()->Set(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001797 isolate, "dummy", v8::FunctionTemplate::New(isolate, DummyCallHandler));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001798 v8::Handle<ObjectTemplate> templ = func_templ->InstanceTemplate();
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001799 templ->Set(isolate, "x", v8_num(200));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001800 templ->SetAccessor(v8_str("m"), GetM);
1801 LocalContext env(0, templ);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +00001802 v8::Handle<Script> script(v8_compile("dummy()"));
1803 v8::Handle<Value> result(script->Run());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001804 CHECK_EQ(13.4, result->NumberValue());
1805 CHECK_EQ(200, v8_compile("x")->Run()->Int32Value());
1806 CHECK_EQ(876, v8_compile("m")->Run()->Int32Value());
1807}
1808
1809
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001810THREADED_TEST(ObjectTemplate) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001811 v8::Isolate* isolate = CcTest::isolate();
1812 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00001813 Local<ObjectTemplate> templ1 = ObjectTemplate::New(isolate);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001814 templ1->Set(isolate, "x", v8_num(10));
1815 templ1->Set(isolate, "y", v8_num(13));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001816 LocalContext env;
1817 Local<v8::Object> instance1 = templ1->NewInstance();
1818 env->Global()->Set(v8_str("p"), instance1);
1819 CHECK(v8_compile("(p.x == 10)")->Run()->BooleanValue());
1820 CHECK(v8_compile("(p.y == 13)")->Run()->BooleanValue());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001821 Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(isolate);
1822 fun->PrototypeTemplate()->Set(isolate, "nirk", v8_num(123));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001823 Local<ObjectTemplate> templ2 = fun->InstanceTemplate();
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001824 templ2->Set(isolate, "a", v8_num(12));
1825 templ2->Set(isolate, "b", templ1);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001826 Local<v8::Object> instance2 = templ2->NewInstance();
1827 env->Global()->Set(v8_str("q"), instance2);
1828 CHECK(v8_compile("(q.nirk == 123)")->Run()->BooleanValue());
1829 CHECK(v8_compile("(q.a == 12)")->Run()->BooleanValue());
1830 CHECK(v8_compile("(q.b.x == 10)")->Run()->BooleanValue());
1831 CHECK(v8_compile("(q.b.y == 13)")->Run()->BooleanValue());
1832}
1833
1834
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001835static void GetFlabby(const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001836 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001837 args.GetReturnValue().Set(v8_num(17.2));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001838}
1839
1840
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001841static void GetKnurd(Local<String> property,
1842 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001843 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001844 info.GetReturnValue().Set(v8_num(15.2));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001845}
1846
1847
1848THREADED_TEST(DescriptorInheritance) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001849 v8::Isolate* isolate = CcTest::isolate();
1850 v8::HandleScope scope(isolate);
1851 v8::Handle<v8::FunctionTemplate> super = v8::FunctionTemplate::New(isolate);
1852 super->PrototypeTemplate()->Set(isolate, "flabby",
1853 v8::FunctionTemplate::New(isolate,
1854 GetFlabby));
1855 super->PrototypeTemplate()->Set(isolate, "PI", v8_num(3.14));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001856
1857 super->InstanceTemplate()->SetAccessor(v8_str("knurd"), GetKnurd);
1858
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001859 v8::Handle<v8::FunctionTemplate> base1 = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001860 base1->Inherit(super);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001861 base1->PrototypeTemplate()->Set(isolate, "v1", v8_num(20.1));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001862
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001863 v8::Handle<v8::FunctionTemplate> base2 = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001864 base2->Inherit(super);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001865 base2->PrototypeTemplate()->Set(isolate, "v2", v8_num(10.1));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001866
1867 LocalContext env;
1868
1869 env->Global()->Set(v8_str("s"), super->GetFunction());
1870 env->Global()->Set(v8_str("base1"), base1->GetFunction());
1871 env->Global()->Set(v8_str("base2"), base2->GetFunction());
1872
1873 // Checks right __proto__ chain.
1874 CHECK(CompileRun("base1.prototype.__proto__ == s.prototype")->BooleanValue());
1875 CHECK(CompileRun("base2.prototype.__proto__ == s.prototype")->BooleanValue());
1876
1877 CHECK(v8_compile("s.prototype.PI == 3.14")->Run()->BooleanValue());
1878
1879 // Instance accessor should not be visible on function object or its prototype
1880 CHECK(CompileRun("s.knurd == undefined")->BooleanValue());
1881 CHECK(CompileRun("s.prototype.knurd == undefined")->BooleanValue());
1882 CHECK(CompileRun("base1.prototype.knurd == undefined")->BooleanValue());
1883
1884 env->Global()->Set(v8_str("obj"),
1885 base1->GetFunction()->NewInstance());
1886 CHECK_EQ(17.2, v8_compile("obj.flabby()")->Run()->NumberValue());
1887 CHECK(v8_compile("'flabby' in obj")->Run()->BooleanValue());
1888 CHECK_EQ(15.2, v8_compile("obj.knurd")->Run()->NumberValue());
1889 CHECK(v8_compile("'knurd' in obj")->Run()->BooleanValue());
1890 CHECK_EQ(20.1, v8_compile("obj.v1")->Run()->NumberValue());
1891
1892 env->Global()->Set(v8_str("obj2"),
1893 base2->GetFunction()->NewInstance());
1894 CHECK_EQ(17.2, v8_compile("obj2.flabby()")->Run()->NumberValue());
1895 CHECK(v8_compile("'flabby' in obj2")->Run()->BooleanValue());
1896 CHECK_EQ(15.2, v8_compile("obj2.knurd")->Run()->NumberValue());
1897 CHECK(v8_compile("'knurd' in obj2")->Run()->BooleanValue());
1898 CHECK_EQ(10.1, v8_compile("obj2.v2")->Run()->NumberValue());
1899
1900 // base1 and base2 cannot cross reference to each's prototype
1901 CHECK(v8_compile("obj.v2")->Run()->IsUndefined());
1902 CHECK(v8_compile("obj2.v1")->Run()->IsUndefined());
1903}
1904
1905
1906int echo_named_call_count;
1907
1908
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001909static void EchoNamedProperty(Local<String> name,
1910 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001911 ApiTestFuzzer::Fuzz();
1912 CHECK_EQ(v8_str("data"), info.Data());
1913 echo_named_call_count++;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001914 info.GetReturnValue().Set(name);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001915}
1916
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001917
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001918// Helper functions for Interceptor/Accessor interaction tests
1919
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001920void SimpleAccessorGetter(Local<String> name,
1921 const v8::PropertyCallbackInfo<v8::Value>& info) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001922 Handle<Object> self = info.This();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001923 info.GetReturnValue().Set(
1924 self->Get(String::Concat(v8_str("accessor_"), name)));
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001925}
1926
1927void SimpleAccessorSetter(Local<String> name, Local<Value> value,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001928 const v8::PropertyCallbackInfo<void>& info) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001929 Handle<Object> self = info.This();
1930 self->Set(String::Concat(v8_str("accessor_"), name), value);
1931}
1932
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001933void EmptyInterceptorGetter(Local<String> name,
1934 const v8::PropertyCallbackInfo<v8::Value>& info) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001935}
1936
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001937void EmptyInterceptorSetter(Local<String> name,
1938 Local<Value> value,
1939 const v8::PropertyCallbackInfo<v8::Value>& info) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001940}
1941
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001942void InterceptorGetter(Local<String> name,
1943 const v8::PropertyCallbackInfo<v8::Value>& info) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001944 // Intercept names that start with 'interceptor_'.
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00001945 String::Utf8Value utf8(name);
1946 char* name_str = *utf8;
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001947 char prefix[] = "interceptor_";
1948 int i;
1949 for (i = 0; name_str[i] && prefix[i]; ++i) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001950 if (name_str[i] != prefix[i]) return;
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001951 }
1952 Handle<Object> self = info.This();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001953 info.GetReturnValue().Set(self->GetHiddenValue(v8_str(name_str + i)));
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001954}
1955
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001956void InterceptorSetter(Local<String> name,
1957 Local<Value> value,
1958 const v8::PropertyCallbackInfo<v8::Value>& info) {
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +00001959 // Intercept accesses that set certain integer values, for which the name does
1960 // not start with 'accessor_'.
1961 String::Utf8Value utf8(name);
1962 char* name_str = *utf8;
1963 char prefix[] = "accessor_";
1964 int i;
1965 for (i = 0; name_str[i] && prefix[i]; ++i) {
1966 if (name_str[i] != prefix[i]) break;
1967 }
1968 if (!prefix[i]) return;
1969
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001970 if (value->IsInt32() && value->Int32Value() < 10000) {
1971 Handle<Object> self = info.This();
1972 self->SetHiddenValue(name, value);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001973 info.GetReturnValue().Set(value);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001974 }
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001975}
1976
1977void AddAccessor(Handle<FunctionTemplate> templ,
1978 Handle<String> name,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001979 v8::AccessorGetterCallback getter,
1980 v8::AccessorSetterCallback setter) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001981 templ->PrototypeTemplate()->SetAccessor(name, getter, setter);
1982}
1983
1984void AddInterceptor(Handle<FunctionTemplate> templ,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001985 v8::NamedPropertyGetterCallback getter,
1986 v8::NamedPropertySetterCallback setter) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001987 templ->InstanceTemplate()->SetNamedPropertyHandler(getter, setter);
1988}
1989
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001990
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001991THREADED_TEST(EmptyInterceptorDoesNotShadowAccessors) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00001992 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00001993 Handle<FunctionTemplate> parent = FunctionTemplate::New(CcTest::isolate());
1994 Handle<FunctionTemplate> child = FunctionTemplate::New(CcTest::isolate());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001995 child->Inherit(parent);
1996 AddAccessor(parent, v8_str("age"),
1997 SimpleAccessorGetter, SimpleAccessorSetter);
1998 AddInterceptor(child, EmptyInterceptorGetter, EmptyInterceptorSetter);
1999 LocalContext env;
2000 env->Global()->Set(v8_str("Child"), child->GetFunction());
2001 CompileRun("var child = new Child;"
2002 "child.age = 10;");
2003 ExpectBoolean("child.hasOwnProperty('age')", false);
2004 ExpectInt32("child.age", 10);
2005 ExpectInt32("child.accessor_age", 10);
2006}
2007
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002008
machenbach@chromium.orgbbbda922014-01-23 09:38:20 +00002009THREADED_TEST(EmptyInterceptorBreakTransitions) {
2010 v8::HandleScope scope(CcTest::isolate());
2011 Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
2012 AddInterceptor(templ, EmptyInterceptorGetter, EmptyInterceptorSetter);
2013 LocalContext env;
2014 env->Global()->Set(v8_str("Constructor"), templ->GetFunction());
2015 CompileRun("var o1 = new Constructor;"
2016 "o1.a = 1;" // Ensure a and x share the descriptor array.
2017 "Object.defineProperty(o1, 'x', {value: 10});");
2018 CompileRun("var o2 = new Constructor;"
2019 "o2.a = 1;"
2020 "Object.defineProperty(o2, 'x', {value: 10});");
2021}
2022
2023
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002024THREADED_TEST(EmptyInterceptorDoesNotShadowJSAccessors) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002025 v8::Isolate* isolate = CcTest::isolate();
2026 v8::HandleScope scope(isolate);
2027 Handle<FunctionTemplate> parent = FunctionTemplate::New(isolate);
2028 Handle<FunctionTemplate> child = FunctionTemplate::New(isolate);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002029 child->Inherit(parent);
2030 AddInterceptor(child, EmptyInterceptorGetter, EmptyInterceptorSetter);
2031 LocalContext env;
2032 env->Global()->Set(v8_str("Child"), child->GetFunction());
2033 CompileRun("var child = new Child;"
2034 "var parent = child.__proto__;"
2035 "Object.defineProperty(parent, 'age', "
2036 " {get: function(){ return this.accessor_age; }, "
2037 " set: function(v){ this.accessor_age = v; }, "
2038 " enumerable: true, configurable: true});"
2039 "child.age = 10;");
2040 ExpectBoolean("child.hasOwnProperty('age')", false);
2041 ExpectInt32("child.age", 10);
2042 ExpectInt32("child.accessor_age", 10);
2043}
2044
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002045
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002046THREADED_TEST(EmptyInterceptorDoesNotAffectJSProperties) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002047 v8::Isolate* isolate = CcTest::isolate();
2048 v8::HandleScope scope(isolate);
2049 Handle<FunctionTemplate> parent = FunctionTemplate::New(isolate);
2050 Handle<FunctionTemplate> child = FunctionTemplate::New(isolate);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002051 child->Inherit(parent);
2052 AddInterceptor(child, EmptyInterceptorGetter, EmptyInterceptorSetter);
2053 LocalContext env;
2054 env->Global()->Set(v8_str("Child"), child->GetFunction());
2055 CompileRun("var child = new Child;"
2056 "var parent = child.__proto__;"
2057 "parent.name = 'Alice';");
2058 ExpectBoolean("child.hasOwnProperty('name')", false);
2059 ExpectString("child.name", "Alice");
2060 CompileRun("child.name = 'Bob';");
2061 ExpectString("child.name", "Bob");
2062 ExpectBoolean("child.hasOwnProperty('name')", true);
2063 ExpectString("parent.name", "Alice");
2064}
2065
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002066
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002067THREADED_TEST(SwitchFromInterceptorToAccessor) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002068 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002069 Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
danno@chromium.orgbf0c8202011-12-27 10:09:42 +00002070 AddAccessor(templ, v8_str("age"),
2071 SimpleAccessorGetter, SimpleAccessorSetter);
2072 AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
2073 LocalContext env;
2074 env->Global()->Set(v8_str("Obj"), templ->GetFunction());
2075 CompileRun("var obj = new Obj;"
2076 "function setAge(i){ obj.age = i; };"
2077 "for(var i = 0; i <= 10000; i++) setAge(i);");
2078 // All i < 10000 go to the interceptor.
2079 ExpectInt32("obj.interceptor_age", 9999);
2080 // The last i goes to the accessor.
2081 ExpectInt32("obj.accessor_age", 10000);
2082}
2083
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002084
danno@chromium.orgbf0c8202011-12-27 10:09:42 +00002085THREADED_TEST(SwitchFromAccessorToInterceptor) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002086 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002087 Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
danno@chromium.orgbf0c8202011-12-27 10:09:42 +00002088 AddAccessor(templ, v8_str("age"),
2089 SimpleAccessorGetter, SimpleAccessorSetter);
2090 AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
2091 LocalContext env;
2092 env->Global()->Set(v8_str("Obj"), templ->GetFunction());
2093 CompileRun("var obj = new Obj;"
2094 "function setAge(i){ obj.age = i; };"
2095 "for(var i = 20000; i >= 9999; i--) setAge(i);");
2096 // All i >= 10000 go to the accessor.
2097 ExpectInt32("obj.accessor_age", 10000);
2098 // The last i goes to the interceptor.
2099 ExpectInt32("obj.interceptor_age", 9999);
2100}
2101
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002102
danno@chromium.orgbf0c8202011-12-27 10:09:42 +00002103THREADED_TEST(SwitchFromInterceptorToAccessorWithInheritance) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002104 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002105 Handle<FunctionTemplate> parent = FunctionTemplate::New(CcTest::isolate());
2106 Handle<FunctionTemplate> child = FunctionTemplate::New(CcTest::isolate());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002107 child->Inherit(parent);
2108 AddAccessor(parent, v8_str("age"),
2109 SimpleAccessorGetter, SimpleAccessorSetter);
2110 AddInterceptor(child, InterceptorGetter, InterceptorSetter);
2111 LocalContext env;
2112 env->Global()->Set(v8_str("Child"), child->GetFunction());
2113 CompileRun("var child = new Child;"
2114 "function setAge(i){ child.age = i; };"
2115 "for(var i = 0; i <= 10000; i++) setAge(i);");
2116 // All i < 10000 go to the interceptor.
2117 ExpectInt32("child.interceptor_age", 9999);
2118 // The last i goes to the accessor.
2119 ExpectInt32("child.accessor_age", 10000);
2120}
2121
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002122
danno@chromium.orgbf0c8202011-12-27 10:09:42 +00002123THREADED_TEST(SwitchFromAccessorToInterceptorWithInheritance) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002124 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002125 Handle<FunctionTemplate> parent = FunctionTemplate::New(CcTest::isolate());
2126 Handle<FunctionTemplate> child = FunctionTemplate::New(CcTest::isolate());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002127 child->Inherit(parent);
2128 AddAccessor(parent, v8_str("age"),
2129 SimpleAccessorGetter, SimpleAccessorSetter);
2130 AddInterceptor(child, InterceptorGetter, InterceptorSetter);
2131 LocalContext env;
2132 env->Global()->Set(v8_str("Child"), child->GetFunction());
2133 CompileRun("var child = new Child;"
2134 "function setAge(i){ child.age = i; };"
2135 "for(var i = 20000; i >= 9999; i--) setAge(i);");
2136 // All i >= 10000 go to the accessor.
2137 ExpectInt32("child.accessor_age", 10000);
2138 // The last i goes to the interceptor.
2139 ExpectInt32("child.interceptor_age", 9999);
2140}
2141
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002142
danno@chromium.orgbf0c8202011-12-27 10:09:42 +00002143THREADED_TEST(SwitchFromInterceptorToJSAccessor) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002144 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002145 Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
danno@chromium.orgbf0c8202011-12-27 10:09:42 +00002146 AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
2147 LocalContext env;
2148 env->Global()->Set(v8_str("Obj"), templ->GetFunction());
2149 CompileRun("var obj = new Obj;"
2150 "function setter(i) { this.accessor_age = i; };"
2151 "function getter() { return this.accessor_age; };"
2152 "function setAge(i) { obj.age = i; };"
2153 "Object.defineProperty(obj, 'age', { get:getter, set:setter });"
2154 "for(var i = 0; i <= 10000; i++) setAge(i);");
2155 // All i < 10000 go to the interceptor.
2156 ExpectInt32("obj.interceptor_age", 9999);
2157 // The last i goes to the JavaScript accessor.
2158 ExpectInt32("obj.accessor_age", 10000);
2159 // The installed JavaScript getter is still intact.
2160 // This last part is a regression test for issue 1651 and relies on the fact
2161 // that both interceptor and accessor are being installed on the same object.
2162 ExpectInt32("obj.age", 10000);
2163 ExpectBoolean("obj.hasOwnProperty('age')", true);
2164 ExpectUndefined("Object.getOwnPropertyDescriptor(obj, 'age').value");
2165}
2166
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002167
danno@chromium.orgbf0c8202011-12-27 10:09:42 +00002168THREADED_TEST(SwitchFromJSAccessorToInterceptor) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002169 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002170 Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
danno@chromium.orgbf0c8202011-12-27 10:09:42 +00002171 AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
2172 LocalContext env;
2173 env->Global()->Set(v8_str("Obj"), templ->GetFunction());
2174 CompileRun("var obj = new Obj;"
2175 "function setter(i) { this.accessor_age = i; };"
2176 "function getter() { return this.accessor_age; };"
2177 "function setAge(i) { obj.age = i; };"
2178 "Object.defineProperty(obj, 'age', { get:getter, set:setter });"
2179 "for(var i = 20000; i >= 9999; i--) setAge(i);");
2180 // All i >= 10000 go to the accessor.
2181 ExpectInt32("obj.accessor_age", 10000);
2182 // The last i goes to the interceptor.
2183 ExpectInt32("obj.interceptor_age", 9999);
2184 // The installed JavaScript getter is still intact.
2185 // This last part is a regression test for issue 1651 and relies on the fact
2186 // that both interceptor and accessor are being installed on the same object.
2187 ExpectInt32("obj.age", 10000);
2188 ExpectBoolean("obj.hasOwnProperty('age')", true);
2189 ExpectUndefined("Object.getOwnPropertyDescriptor(obj, 'age').value");
2190}
2191
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002192
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002193THREADED_TEST(SwitchFromInterceptorToProperty) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002194 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002195 Handle<FunctionTemplate> parent = FunctionTemplate::New(CcTest::isolate());
2196 Handle<FunctionTemplate> child = FunctionTemplate::New(CcTest::isolate());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002197 child->Inherit(parent);
2198 AddInterceptor(child, InterceptorGetter, InterceptorSetter);
2199 LocalContext env;
2200 env->Global()->Set(v8_str("Child"), child->GetFunction());
2201 CompileRun("var child = new Child;"
2202 "function setAge(i){ child.age = i; };"
2203 "for(var i = 0; i <= 10000; i++) setAge(i);");
2204 // All i < 10000 go to the interceptor.
2205 ExpectInt32("child.interceptor_age", 9999);
2206 // The last i goes to child's own property.
2207 ExpectInt32("child.age", 10000);
2208}
2209
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002210
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002211THREADED_TEST(SwitchFromPropertyToInterceptor) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002212 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002213 Handle<FunctionTemplate> parent = FunctionTemplate::New(CcTest::isolate());
2214 Handle<FunctionTemplate> child = FunctionTemplate::New(CcTest::isolate());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00002215 child->Inherit(parent);
2216 AddInterceptor(child, InterceptorGetter, InterceptorSetter);
2217 LocalContext env;
2218 env->Global()->Set(v8_str("Child"), child->GetFunction());
2219 CompileRun("var child = new Child;"
2220 "function setAge(i){ child.age = i; };"
2221 "for(var i = 20000; i >= 9999; i--) setAge(i);");
2222 // All i >= 10000 go to child's own property.
2223 ExpectInt32("child.age", 10000);
2224 // The last i goes to the interceptor.
2225 ExpectInt32("child.interceptor_age", 9999);
2226}
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002227
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002228
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002229THREADED_TEST(NamedPropertyHandlerGetter) {
2230 echo_named_call_count = 0;
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002231 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002232 v8::Handle<v8::FunctionTemplate> templ =
2233 v8::FunctionTemplate::New(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002234 templ->InstanceTemplate()->SetNamedPropertyHandler(EchoNamedProperty,
2235 0, 0, 0, 0,
2236 v8_str("data"));
2237 LocalContext env;
2238 env->Global()->Set(v8_str("obj"),
2239 templ->GetFunction()->NewInstance());
2240 CHECK_EQ(echo_named_call_count, 0);
2241 v8_compile("obj.x")->Run();
2242 CHECK_EQ(echo_named_call_count, 1);
2243 const char* code = "var str = 'oddle'; obj[str] + obj.poddle;";
2244 v8::Handle<Value> str = CompileRun(code);
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00002245 String::Utf8Value value(str);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002246 CHECK_EQ(*value, "oddlepoddle");
2247 // Check default behavior
2248 CHECK_EQ(v8_compile("obj.flob = 10;")->Run()->Int32Value(), 10);
2249 CHECK(v8_compile("'myProperty' in obj")->Run()->BooleanValue());
2250 CHECK(v8_compile("delete obj.myProperty")->Run()->BooleanValue());
2251}
2252
2253
2254int echo_indexed_call_count = 0;
2255
2256
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002257static void EchoIndexedProperty(
2258 uint32_t index,
2259 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002260 ApiTestFuzzer::Fuzz();
2261 CHECK_EQ(v8_num(637), info.Data());
2262 echo_indexed_call_count++;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002263 info.GetReturnValue().Set(v8_num(index));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002264}
2265
2266
2267THREADED_TEST(IndexedPropertyHandlerGetter) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002268 v8::Isolate* isolate = CcTest::isolate();
2269 v8::HandleScope scope(isolate);
2270 v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002271 templ->InstanceTemplate()->SetIndexedPropertyHandler(EchoIndexedProperty,
2272 0, 0, 0, 0,
2273 v8_num(637));
2274 LocalContext env;
2275 env->Global()->Set(v8_str("obj"),
2276 templ->GetFunction()->NewInstance());
2277 Local<Script> script = v8_compile("obj[900]");
2278 CHECK_EQ(script->Run()->Int32Value(), 900);
2279}
2280
2281
2282v8::Handle<v8::Object> bottom;
2283
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002284static void CheckThisIndexedPropertyHandler(
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002285 uint32_t index,
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002286 const v8::PropertyCallbackInfo<v8::Value>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00002287 CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertyHandler));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002288 ApiTestFuzzer::Fuzz();
2289 CHECK(info.This()->Equals(bottom));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002290}
2291
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002292static void CheckThisNamedPropertyHandler(
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002293 Local<String> name,
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002294 const v8::PropertyCallbackInfo<v8::Value>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00002295 CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertyHandler));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002296 ApiTestFuzzer::Fuzz();
2297 CHECK(info.This()->Equals(bottom));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002298}
2299
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002300void CheckThisIndexedPropertySetter(
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002301 uint32_t index,
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002302 Local<Value> value,
2303 const v8::PropertyCallbackInfo<v8::Value>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00002304 CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertySetter));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002305 ApiTestFuzzer::Fuzz();
2306 CHECK(info.This()->Equals(bottom));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002307}
2308
2309
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002310void CheckThisNamedPropertySetter(
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002311 Local<String> property,
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002312 Local<Value> value,
2313 const v8::PropertyCallbackInfo<v8::Value>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00002314 CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertySetter));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002315 ApiTestFuzzer::Fuzz();
2316 CHECK(info.This()->Equals(bottom));
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002317}
2318
2319void CheckThisIndexedPropertyQuery(
2320 uint32_t index,
2321 const v8::PropertyCallbackInfo<v8::Integer>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00002322 CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertyQuery));
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002323 ApiTestFuzzer::Fuzz();
2324 CHECK(info.This()->Equals(bottom));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002325}
2326
2327
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002328void CheckThisNamedPropertyQuery(
2329 Local<String> property,
2330 const v8::PropertyCallbackInfo<v8::Integer>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00002331 CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertyQuery));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002332 ApiTestFuzzer::Fuzz();
2333 CHECK(info.This()->Equals(bottom));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002334}
2335
2336
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002337void CheckThisIndexedPropertyDeleter(
2338 uint32_t index,
2339 const v8::PropertyCallbackInfo<v8::Boolean>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00002340 CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertyDeleter));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002341 ApiTestFuzzer::Fuzz();
2342 CHECK(info.This()->Equals(bottom));
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002343}
2344
2345
2346void CheckThisNamedPropertyDeleter(
2347 Local<String> property,
2348 const v8::PropertyCallbackInfo<v8::Boolean>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00002349 CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertyDeleter));
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002350 ApiTestFuzzer::Fuzz();
2351 CHECK(info.This()->Equals(bottom));
2352}
2353
2354
2355void CheckThisIndexedPropertyEnumerator(
2356 const v8::PropertyCallbackInfo<v8::Array>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00002357 CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertyEnumerator));
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002358 ApiTestFuzzer::Fuzz();
2359 CHECK(info.This()->Equals(bottom));
2360}
2361
2362
2363void CheckThisNamedPropertyEnumerator(
2364 const v8::PropertyCallbackInfo<v8::Array>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +00002365 CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertyEnumerator));
ulan@chromium.orgdfe53072013-06-06 14:14:51 +00002366 ApiTestFuzzer::Fuzz();
2367 CHECK(info.This()->Equals(bottom));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002368}
2369
2370
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002371THREADED_PROFILED_TEST(PropertyHandlerInPrototype) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002372 LocalContext env;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002373 v8::Isolate* isolate = env->GetIsolate();
2374 v8::HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002375
2376 // Set up a prototype chain with three interceptors.
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002377 v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002378 templ->InstanceTemplate()->SetIndexedPropertyHandler(
2379 CheckThisIndexedPropertyHandler,
2380 CheckThisIndexedPropertySetter,
2381 CheckThisIndexedPropertyQuery,
2382 CheckThisIndexedPropertyDeleter,
2383 CheckThisIndexedPropertyEnumerator);
2384
2385 templ->InstanceTemplate()->SetNamedPropertyHandler(
2386 CheckThisNamedPropertyHandler,
2387 CheckThisNamedPropertySetter,
2388 CheckThisNamedPropertyQuery,
2389 CheckThisNamedPropertyDeleter,
2390 CheckThisNamedPropertyEnumerator);
2391
2392 bottom = templ->GetFunction()->NewInstance();
2393 Local<v8::Object> top = templ->GetFunction()->NewInstance();
2394 Local<v8::Object> middle = templ->GetFunction()->NewInstance();
2395
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +00002396 bottom->SetPrototype(middle);
2397 middle->SetPrototype(top);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002398 env->Global()->Set(v8_str("obj"), bottom);
2399
2400 // Indexed and named get.
2401 Script::Compile(v8_str("obj[0]"))->Run();
2402 Script::Compile(v8_str("obj.x"))->Run();
2403
2404 // Indexed and named set.
2405 Script::Compile(v8_str("obj[1] = 42"))->Run();
2406 Script::Compile(v8_str("obj.y = 42"))->Run();
2407
2408 // Indexed and named query.
2409 Script::Compile(v8_str("0 in obj"))->Run();
2410 Script::Compile(v8_str("'x' in obj"))->Run();
2411
2412 // Indexed and named deleter.
2413 Script::Compile(v8_str("delete obj[0]"))->Run();
2414 Script::Compile(v8_str("delete obj.x"))->Run();
2415
2416 // Enumerators.
2417 Script::Compile(v8_str("for (var p in obj) ;"))->Run();
2418}
2419
2420
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002421static void PrePropertyHandlerGet(
2422 Local<String> key,
2423 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002424 ApiTestFuzzer::Fuzz();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002425 if (v8_str("pre")->Equals(key)) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002426 info.GetReturnValue().Set(v8_str("PrePropertyHandler: pre"));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002427 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002428}
2429
2430
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002431static void PrePropertyHandlerQuery(
2432 Local<String> key,
2433 const v8::PropertyCallbackInfo<v8::Integer>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002434 if (v8_str("pre")->Equals(key)) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002435 info.GetReturnValue().Set(static_cast<int32_t>(v8::None));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002436 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002437}
2438
2439
2440THREADED_TEST(PrePropertyHandler) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002441 v8::Isolate* isolate = CcTest::isolate();
2442 v8::HandleScope scope(isolate);
2443 v8::Handle<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002444 desc->InstanceTemplate()->SetNamedPropertyHandler(PrePropertyHandlerGet,
2445 0,
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +00002446 PrePropertyHandlerQuery);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002447 LocalContext env(NULL, desc->InstanceTemplate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002448 Script::Compile(v8_str(
2449 "var pre = 'Object: pre'; var on = 'Object: on';"))->Run();
2450 v8::Handle<Value> result_pre = Script::Compile(v8_str("pre"))->Run();
2451 CHECK_EQ(v8_str("PrePropertyHandler: pre"), result_pre);
2452 v8::Handle<Value> result_on = Script::Compile(v8_str("on"))->Run();
2453 CHECK_EQ(v8_str("Object: on"), result_on);
2454 v8::Handle<Value> result_post = Script::Compile(v8_str("post"))->Run();
2455 CHECK(result_post.IsEmpty());
2456}
2457
2458
ager@chromium.org870a0b62008-11-04 11:43:05 +00002459THREADED_TEST(UndefinedIsNotEnumerable) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00002460 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00002461 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org870a0b62008-11-04 11:43:05 +00002462 v8::Handle<Value> result = Script::Compile(v8_str(
2463 "this.propertyIsEnumerable(undefined)"))->Run();
2464 CHECK(result->IsFalse());
2465}
2466
2467
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002468v8::Handle<Script> call_recursively_script;
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00002469static const int kTargetRecursionDepth = 200; // near maximum
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002470
2471
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002472static void CallScriptRecursivelyCall(
2473 const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002474 ApiTestFuzzer::Fuzz();
2475 int depth = args.This()->Get(v8_str("depth"))->Int32Value();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002476 if (depth == kTargetRecursionDepth) return;
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002477 args.This()->Set(v8_str("depth"),
2478 v8::Integer::New(args.GetIsolate(), depth + 1));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002479 args.GetReturnValue().Set(call_recursively_script->Run());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002480}
2481
2482
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002483static void CallFunctionRecursivelyCall(
2484 const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002485 ApiTestFuzzer::Fuzz();
2486 int depth = args.This()->Get(v8_str("depth"))->Int32Value();
2487 if (depth == kTargetRecursionDepth) {
2488 printf("[depth = %d]\n", depth);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002489 return;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002490 }
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002491 args.This()->Set(v8_str("depth"),
2492 v8::Integer::New(args.GetIsolate(), depth + 1));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002493 v8::Handle<Value> function =
2494 args.This()->Get(v8_str("callFunctionRecursively"));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002495 args.GetReturnValue().Set(
2496 function.As<Function>()->Call(args.This(), 0, NULL));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002497}
2498
2499
2500THREADED_TEST(DeepCrossLanguageRecursion) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002501 v8::Isolate* isolate = CcTest::isolate();
2502 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00002503 v8::Handle<v8::ObjectTemplate> global = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002504 global->Set(v8_str("callScriptRecursively"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002505 v8::FunctionTemplate::New(isolate, CallScriptRecursivelyCall));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002506 global->Set(v8_str("callFunctionRecursively"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002507 v8::FunctionTemplate::New(isolate, CallFunctionRecursivelyCall));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002508 LocalContext env(NULL, global);
2509
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002510 env->Global()->Set(v8_str("depth"), v8::Integer::New(isolate, 0));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002511 call_recursively_script = v8_compile("callScriptRecursively()");
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00002512 call_recursively_script->Run();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002513 call_recursively_script = v8::Handle<Script>();
2514
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002515 env->Global()->Set(v8_str("depth"), v8::Integer::New(isolate, 0));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002516 Script::Compile(v8_str("callFunctionRecursively()"))->Run();
2517}
2518
2519
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002520static void ThrowingPropertyHandlerGet(
2521 Local<String> key,
2522 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002523 ApiTestFuzzer::Fuzz();
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00002524 info.GetReturnValue().Set(info.GetIsolate()->ThrowException(key));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002525}
2526
2527
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002528static void ThrowingPropertyHandlerSet(
2529 Local<String> key,
2530 Local<Value>,
2531 const v8::PropertyCallbackInfo<v8::Value>& info) {
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00002532 info.GetIsolate()->ThrowException(key);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00002533 info.GetReturnValue().SetUndefined(); // not the same as empty handle
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002534}
2535
2536
2537THREADED_TEST(CallbackExceptionRegression) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00002538 v8::Isolate* isolate = CcTest::isolate();
2539 v8::HandleScope scope(isolate);
2540 v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002541 obj->SetNamedPropertyHandler(ThrowingPropertyHandlerGet,
2542 ThrowingPropertyHandlerSet);
2543 LocalContext env;
2544 env->Global()->Set(v8_str("obj"), obj->NewInstance());
2545 v8::Handle<Value> otto = Script::Compile(v8_str(
2546 "try { with (obj) { otto; } } catch (e) { e; }"))->Run();
2547 CHECK_EQ(v8_str("otto"), otto);
2548 v8::Handle<Value> netto = Script::Compile(v8_str(
2549 "try { with (obj) { netto = 4; } } catch (e) { e; }"))->Run();
2550 CHECK_EQ(v8_str("netto"), netto);
2551}
2552
2553
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002554THREADED_TEST(FunctionPrototype) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002555 v8::Isolate* isolate = CcTest::isolate();
2556 v8::HandleScope scope(isolate);
2557 Local<v8::FunctionTemplate> Foo = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002558 Foo->PrototypeTemplate()->Set(v8_str("plak"), v8_num(321));
2559 LocalContext env;
2560 env->Global()->Set(v8_str("Foo"), Foo->GetFunction());
2561 Local<Script> script = Script::Compile(v8_str("Foo.prototype.plak"));
2562 CHECK_EQ(script->Run()->Int32Value(), 321);
2563}
2564
2565
2566THREADED_TEST(InternalFields) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002567 LocalContext env;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002568 v8::Isolate* isolate = env->GetIsolate();
2569 v8::HandleScope scope(isolate);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00002570
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002571 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002572 Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
2573 instance_templ->SetInternalFieldCount(1);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002574 Local<v8::Object> obj = templ->GetFunction()->NewInstance();
2575 CHECK_EQ(1, obj->InternalFieldCount());
2576 CHECK(obj->GetInternalField(0)->IsUndefined());
2577 obj->SetInternalField(0, v8_num(17));
2578 CHECK_EQ(17, obj->GetInternalField(0)->Int32Value());
2579}
2580
2581
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002582THREADED_TEST(GlobalObjectInternalFields) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00002583 v8::Isolate* isolate = CcTest::isolate();
2584 v8::HandleScope scope(isolate);
2585 Local<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New(isolate);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00002586 global_template->SetInternalFieldCount(1);
2587 LocalContext env(NULL, global_template);
2588 v8::Handle<v8::Object> global_proxy = env->Global();
2589 v8::Handle<v8::Object> global = global_proxy->GetPrototype().As<v8::Object>();
2590 CHECK_EQ(1, global->InternalFieldCount());
2591 CHECK(global->GetInternalField(0)->IsUndefined());
2592 global->SetInternalField(0, v8_num(17));
2593 CHECK_EQ(17, global->GetInternalField(0)->Int32Value());
2594}
2595
2596
danno@chromium.org169691d2013-07-15 08:01:13 +00002597THREADED_TEST(GlobalObjectHasRealIndexedProperty) {
2598 LocalContext env;
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002599 v8::HandleScope scope(CcTest::isolate());
danno@chromium.org169691d2013-07-15 08:01:13 +00002600
2601 v8::Local<v8::Object> global = env->Global();
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00002602 global->Set(0, v8::String::NewFromUtf8(CcTest::isolate(), "value"));
danno@chromium.org169691d2013-07-15 08:01:13 +00002603 CHECK(global->HasRealIndexedProperty(0));
2604}
2605
2606
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002607static void CheckAlignedPointerInInternalField(Handle<v8::Object> obj,
2608 void* value) {
2609 CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(value) & 0x1));
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00002610 obj->SetAlignedPointerInInternalField(0, value);
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002611 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00002612 CHECK_EQ(value, obj->GetAlignedPointerFromInternalField(0));
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002613}
2614
2615
2616THREADED_TEST(InternalFieldsAlignedPointers) {
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002617 LocalContext env;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002618 v8::Isolate* isolate = env->GetIsolate();
2619 v8::HandleScope scope(isolate);
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002620
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00002621 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002622 Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
2623 instance_templ->SetInternalFieldCount(1);
2624 Local<v8::Object> obj = templ->GetFunction()->NewInstance();
2625 CHECK_EQ(1, obj->InternalFieldCount());
2626
2627 CheckAlignedPointerInInternalField(obj, NULL);
2628
2629 int* heap_allocated = new int[100];
2630 CheckAlignedPointerInInternalField(obj, heap_allocated);
2631 delete[] heap_allocated;
2632
2633 int stack_allocated[100];
2634 CheckAlignedPointerInInternalField(obj, stack_allocated);
2635
2636 void* huge = reinterpret_cast<void*>(~static_cast<uintptr_t>(1));
2637 CheckAlignedPointerInInternalField(obj, huge);
2638}
2639
2640
2641static void CheckAlignedPointerInEmbedderData(LocalContext* env,
2642 int index,
2643 void* value) {
2644 CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(value) & 0x1));
2645 (*env)->SetAlignedPointerInEmbedderData(index, value);
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002646 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002647 CHECK_EQ(value, (*env)->GetAlignedPointerFromEmbedderData(index));
2648}
2649
2650
2651static void* AlignedTestPointer(int i) {
2652 return reinterpret_cast<void*>(i * 1234);
2653}
2654
2655
2656THREADED_TEST(EmbedderDataAlignedPointers) {
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002657 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00002658 v8::HandleScope scope(env->GetIsolate());
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002659
2660 CheckAlignedPointerInEmbedderData(&env, 0, NULL);
2661
2662 int* heap_allocated = new int[100];
2663 CheckAlignedPointerInEmbedderData(&env, 1, heap_allocated);
2664 delete[] heap_allocated;
2665
2666 int stack_allocated[100];
2667 CheckAlignedPointerInEmbedderData(&env, 2, stack_allocated);
2668
2669 void* huge = reinterpret_cast<void*>(~static_cast<uintptr_t>(1));
2670 CheckAlignedPointerInEmbedderData(&env, 3, huge);
2671
2672 // Test growing of the embedder data's backing store.
2673 for (int i = 0; i < 100; i++) {
2674 env->SetAlignedPointerInEmbedderData(i, AlignedTestPointer(i));
2675 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002676 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002677 for (int i = 0; i < 100; i++) {
2678 CHECK_EQ(AlignedTestPointer(i), env->GetAlignedPointerFromEmbedderData(i));
2679 }
2680}
2681
2682
2683static void CheckEmbedderData(LocalContext* env,
2684 int index,
2685 v8::Handle<Value> data) {
2686 (*env)->SetEmbedderData(index, data);
2687 CHECK((*env)->GetEmbedderData(index)->StrictEquals(data));
2688}
2689
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002690
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002691THREADED_TEST(EmbedderData) {
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002692 LocalContext env;
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002693 v8::Isolate* isolate = env->GetIsolate();
2694 v8::HandleScope scope(isolate);
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002695
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00002696 CheckEmbedderData(
2697 &env, 3,
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002698 v8::String::NewFromUtf8(isolate, "The quick brown fox jumps"));
2699 CheckEmbedderData(&env, 2, v8::String::NewFromUtf8(isolate,
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00002700 "over the lazy dog."));
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002701 CheckEmbedderData(&env, 1, v8::Number::New(isolate, 1.2345));
2702 CheckEmbedderData(&env, 0, v8::Boolean::New(isolate, true));
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00002703}
2704
2705
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002706THREADED_TEST(IdentityHash) {
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002707 LocalContext env;
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002708 v8::Isolate* isolate = env->GetIsolate();
2709 v8::HandleScope scope(isolate);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002710
2711 // Ensure that the test starts with an fresh heap to test whether the hash
2712 // code is based on the address.
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002713 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002714 Local<v8::Object> obj = v8::Object::New(isolate);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002715 int hash = obj->GetIdentityHash();
2716 int hash1 = obj->GetIdentityHash();
2717 CHECK_EQ(hash, hash1);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002718 int hash2 = v8::Object::New(isolate)->GetIdentityHash();
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002719 // Since the identity hash is essentially a random number two consecutive
2720 // objects should not be assigned the same hash code. If the test below fails
2721 // the random number generator should be evaluated.
2722 CHECK_NE(hash, hash2);
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002723 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002724 int hash3 = v8::Object::New(isolate)->GetIdentityHash();
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002725 // Make sure that the identity hash is not based on the initial address of
2726 // the object alone. If the test below fails the random number generator
2727 // should be evaluated.
2728 CHECK_NE(hash, hash3);
2729 int hash4 = obj->GetIdentityHash();
2730 CHECK_EQ(hash, hash4);
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002731
2732 // Check identity hashes behaviour in the presence of JS accessors.
2733 // Put a getter for 'v8::IdentityHash' on the Object's prototype:
2734 {
2735 CompileRun("Object.prototype['v8::IdentityHash'] = 42;\n");
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002736 Local<v8::Object> o1 = v8::Object::New(isolate);
2737 Local<v8::Object> o2 = v8::Object::New(isolate);
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002738 CHECK_NE(o1->GetIdentityHash(), o2->GetIdentityHash());
2739 }
2740 {
2741 CompileRun(
2742 "function cnst() { return 42; };\n"
2743 "Object.prototype.__defineGetter__('v8::IdentityHash', cnst);\n");
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002744 Local<v8::Object> o1 = v8::Object::New(isolate);
2745 Local<v8::Object> o2 = v8::Object::New(isolate);
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00002746 CHECK_NE(o1->GetIdentityHash(), o2->GetIdentityHash());
2747 }
ager@chromium.org3b45ab52009-03-19 22:21:34 +00002748}
2749
2750
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002751THREADED_TEST(SymbolProperties) {
2752 i::FLAG_harmony_symbols = true;
2753
2754 LocalContext env;
2755 v8::Isolate* isolate = env->GetIsolate();
2756 v8::HandleScope scope(isolate);
2757
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002758 v8::Local<v8::Object> obj = v8::Object::New(isolate);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002759 v8::Local<v8::Symbol> sym1 = v8::Symbol::New(isolate);
2760 v8::Local<v8::Symbol> sym2 = v8::Symbol::New(isolate, "my-symbol");
2761
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002762 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002763
2764 // Check basic symbol functionality.
2765 CHECK(sym1->IsSymbol());
2766 CHECK(sym2->IsSymbol());
2767 CHECK(!obj->IsSymbol());
2768
2769 CHECK(sym1->Equals(sym1));
2770 CHECK(sym2->Equals(sym2));
2771 CHECK(!sym1->Equals(sym2));
2772 CHECK(!sym2->Equals(sym1));
2773 CHECK(sym1->StrictEquals(sym1));
2774 CHECK(sym2->StrictEquals(sym2));
2775 CHECK(!sym1->StrictEquals(sym2));
2776 CHECK(!sym2->StrictEquals(sym1));
2777
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00002778 CHECK(sym2->Name()->Equals(v8::String::NewFromUtf8(isolate, "my-symbol")));
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002779
2780 v8::Local<v8::Value> sym_val = sym2;
2781 CHECK(sym_val->IsSymbol());
2782 CHECK(sym_val->Equals(sym2));
2783 CHECK(sym_val->StrictEquals(sym2));
2784 CHECK(v8::Symbol::Cast(*sym_val)->Equals(sym2));
2785
2786 v8::Local<v8::Value> sym_obj = v8::SymbolObject::New(isolate, sym2);
2787 CHECK(sym_obj->IsSymbolObject());
2788 CHECK(!sym2->IsSymbolObject());
2789 CHECK(!obj->IsSymbolObject());
2790 CHECK(sym_obj->Equals(sym2));
2791 CHECK(!sym_obj->StrictEquals(sym2));
2792 CHECK(v8::SymbolObject::Cast(*sym_obj)->Equals(sym_obj));
danno@chromium.orgd3c42102013-08-01 16:58:23 +00002793 CHECK(v8::SymbolObject::Cast(*sym_obj)->ValueOf()->Equals(sym2));
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002794
2795 // Make sure delete of a non-existent symbol property works.
2796 CHECK(obj->Delete(sym1));
2797 CHECK(!obj->Has(sym1));
2798
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002799 CHECK(obj->Set(sym1, v8::Integer::New(isolate, 1503)));
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002800 CHECK(obj->Has(sym1));
2801 CHECK_EQ(1503, obj->Get(sym1)->Int32Value());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002802 CHECK(obj->Set(sym1, v8::Integer::New(isolate, 2002)));
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002803 CHECK(obj->Has(sym1));
2804 CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
2805 CHECK_EQ(v8::None, obj->GetPropertyAttributes(sym1));
2806
2807 CHECK_EQ(0, obj->GetOwnPropertyNames()->Length());
2808 int num_props = obj->GetPropertyNames()->Length();
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002809 CHECK(obj->Set(v8::String::NewFromUtf8(isolate, "bla"),
2810 v8::Integer::New(isolate, 20)));
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002811 CHECK_EQ(1, obj->GetOwnPropertyNames()->Length());
2812 CHECK_EQ(num_props + 1, obj->GetPropertyNames()->Length());
2813
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002814 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002815
2816 // Add another property and delete it afterwards to force the object in
2817 // slow case.
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002818 CHECK(obj->Set(sym2, v8::Integer::New(isolate, 2008)));
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002819 CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
2820 CHECK_EQ(2008, obj->Get(sym2)->Int32Value());
2821 CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
2822 CHECK_EQ(1, obj->GetOwnPropertyNames()->Length());
2823
2824 CHECK(obj->Has(sym1));
2825 CHECK(obj->Has(sym2));
2826 CHECK(obj->Delete(sym2));
2827 CHECK(obj->Has(sym1));
2828 CHECK(!obj->Has(sym2));
2829 CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
2830 CHECK_EQ(1, obj->GetOwnPropertyNames()->Length());
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00002831
2832 // Symbol properties are inherited.
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002833 v8::Local<v8::Object> child = v8::Object::New(isolate);
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00002834 child->SetPrototype(obj);
2835 CHECK(child->Has(sym1));
2836 CHECK_EQ(2002, child->Get(sym1)->Int32Value());
2837 CHECK_EQ(0, child->GetOwnPropertyNames()->Length());
2838}
2839
2840
2841THREADED_TEST(PrivateProperties) {
2842 LocalContext env;
2843 v8::Isolate* isolate = env->GetIsolate();
2844 v8::HandleScope scope(isolate);
2845
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002846 v8::Local<v8::Object> obj = v8::Object::New(isolate);
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00002847 v8::Local<v8::Private> priv1 = v8::Private::New(isolate);
2848 v8::Local<v8::Private> priv2 = v8::Private::New(isolate, "my-private");
2849
2850 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
2851
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00002852 CHECK(priv2->Name()->Equals(v8::String::NewFromUtf8(isolate, "my-private")));
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00002853
2854 // Make sure delete of a non-existent private symbol property works.
2855 CHECK(obj->DeletePrivate(priv1));
2856 CHECK(!obj->HasPrivate(priv1));
2857
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002858 CHECK(obj->SetPrivate(priv1, v8::Integer::New(isolate, 1503)));
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00002859 CHECK(obj->HasPrivate(priv1));
2860 CHECK_EQ(1503, obj->GetPrivate(priv1)->Int32Value());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002861 CHECK(obj->SetPrivate(priv1, v8::Integer::New(isolate, 2002)));
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00002862 CHECK(obj->HasPrivate(priv1));
2863 CHECK_EQ(2002, obj->GetPrivate(priv1)->Int32Value());
2864
2865 CHECK_EQ(0, obj->GetOwnPropertyNames()->Length());
2866 int num_props = obj->GetPropertyNames()->Length();
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002867 CHECK(obj->Set(v8::String::NewFromUtf8(isolate, "bla"),
2868 v8::Integer::New(isolate, 20)));
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00002869 CHECK_EQ(1, obj->GetOwnPropertyNames()->Length());
2870 CHECK_EQ(num_props + 1, obj->GetPropertyNames()->Length());
2871
2872 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
2873
2874 // Add another property and delete it afterwards to force the object in
2875 // slow case.
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002876 CHECK(obj->SetPrivate(priv2, v8::Integer::New(isolate, 2008)));
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00002877 CHECK_EQ(2002, obj->GetPrivate(priv1)->Int32Value());
2878 CHECK_EQ(2008, obj->GetPrivate(priv2)->Int32Value());
2879 CHECK_EQ(2002, obj->GetPrivate(priv1)->Int32Value());
2880 CHECK_EQ(1, obj->GetOwnPropertyNames()->Length());
2881
2882 CHECK(obj->HasPrivate(priv1));
2883 CHECK(obj->HasPrivate(priv2));
2884 CHECK(obj->DeletePrivate(priv2));
2885 CHECK(obj->HasPrivate(priv1));
2886 CHECK(!obj->HasPrivate(priv2));
2887 CHECK_EQ(2002, obj->GetPrivate(priv1)->Int32Value());
2888 CHECK_EQ(1, obj->GetOwnPropertyNames()->Length());
2889
2890 // Private properties are inherited (for the time being).
ulan@chromium.org0f13e742014-01-03 15:51:11 +00002891 v8::Local<v8::Object> child = v8::Object::New(isolate);
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00002892 child->SetPrototype(obj);
2893 CHECK(child->HasPrivate(priv1));
2894 CHECK_EQ(2002, child->GetPrivate(priv1)->Int32Value());
2895 CHECK_EQ(0, child->GetOwnPropertyNames()->Length());
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00002896}
2897
2898
ulan@chromium.org837a67e2013-06-11 15:39:48 +00002899class ScopedArrayBufferContents {
2900 public:
2901 explicit ScopedArrayBufferContents(
2902 const v8::ArrayBuffer::Contents& contents)
2903 : contents_(contents) {}
2904 ~ScopedArrayBufferContents() { free(contents_.Data()); }
2905 void* Data() const { return contents_.Data(); }
2906 size_t ByteLength() const { return contents_.ByteLength(); }
2907 private:
2908 const v8::ArrayBuffer::Contents contents_;
2909};
2910
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002911template <typename T>
2912static void CheckInternalFieldsAreZero(v8::Handle<T> value) {
2913 CHECK_EQ(T::kInternalFieldCount, value->InternalFieldCount());
2914 for (int i = 0; i < value->InternalFieldCount(); i++) {
2915 CHECK_EQ(0, value->GetInternalField(i)->Int32Value());
2916 }
2917}
2918
ulan@chromium.org837a67e2013-06-11 15:39:48 +00002919
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002920THREADED_TEST(ArrayBuffer_ApiInternalToExternal) {
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002921 LocalContext env;
2922 v8::Isolate* isolate = env->GetIsolate();
2923 v8::HandleScope handle_scope(isolate);
2924
machenbach@chromium.org9f18d912013-11-28 13:42:41 +00002925 Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, 1024);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002926 CheckInternalFieldsAreZero(ab);
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002927 CHECK_EQ(1024, static_cast<int>(ab->ByteLength()));
2928 CHECK(!ab->IsExternal());
machenbach@chromium.org528ce022013-09-23 14:09:36 +00002929 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002930
ulan@chromium.org837a67e2013-06-11 15:39:48 +00002931 ScopedArrayBufferContents ab_contents(ab->Externalize());
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002932 CHECK(ab->IsExternal());
2933
2934 CHECK_EQ(1024, static_cast<int>(ab_contents.ByteLength()));
2935 uint8_t* data = static_cast<uint8_t*>(ab_contents.Data());
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002936 ASSERT(data != NULL);
2937 env->Global()->Set(v8_str("ab"), ab);
2938
2939 v8::Handle<v8::Value> result = CompileRun("ab.byteLength");
2940 CHECK_EQ(1024, result->Int32Value());
2941
danno@chromium.orgf005df62013-04-30 16:36:45 +00002942 result = CompileRun("var u8 = new Uint8Array(ab);"
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002943 "u8[0] = 0xFF;"
2944 "u8[1] = 0xAA;"
2945 "u8.length");
2946 CHECK_EQ(1024, result->Int32Value());
2947 CHECK_EQ(0xFF, data[0]);
2948 CHECK_EQ(0xAA, data[1]);
2949 data[0] = 0xCC;
2950 data[1] = 0x11;
2951 result = CompileRun("u8[0] + u8[1]");
2952 CHECK_EQ(0xDD, result->Int32Value());
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002953}
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002954
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002955
2956THREADED_TEST(ArrayBuffer_JSInternalToExternal) {
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002957 LocalContext env;
2958 v8::Isolate* isolate = env->GetIsolate();
2959 v8::HandleScope handle_scope(isolate);
2960
2961
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00002962 v8::Local<v8::Value> result =
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002963 CompileRun("var ab1 = new ArrayBuffer(2);"
2964 "var u8_a = new Uint8Array(ab1);"
2965 "u8_a[0] = 0xAA;"
2966 "u8_a[1] = 0xFF; u8_a.buffer");
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00002967 Local<v8::ArrayBuffer> ab1 = Local<v8::ArrayBuffer>::Cast(result);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00002968 CheckInternalFieldsAreZero(ab1);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002969 CHECK_EQ(2, static_cast<int>(ab1->ByteLength()));
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002970 CHECK(!ab1->IsExternal());
ulan@chromium.org837a67e2013-06-11 15:39:48 +00002971 ScopedArrayBufferContents ab1_contents(ab1->Externalize());
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002972 CHECK(ab1->IsExternal());
2973
2974 result = CompileRun("ab1.byteLength");
2975 CHECK_EQ(2, result->Int32Value());
2976 result = CompileRun("u8_a[0]");
2977 CHECK_EQ(0xAA, result->Int32Value());
2978 result = CompileRun("u8_a[1]");
2979 CHECK_EQ(0xFF, result->Int32Value());
2980 result = CompileRun("var u8_b = new Uint8Array(ab1);"
2981 "u8_b[0] = 0xBB;"
2982 "u8_a[0]");
2983 CHECK_EQ(0xBB, result->Int32Value());
2984 result = CompileRun("u8_b[1]");
2985 CHECK_EQ(0xFF, result->Int32Value());
2986
2987 CHECK_EQ(2, static_cast<int>(ab1_contents.ByteLength()));
2988 uint8_t* ab1_data = static_cast<uint8_t*>(ab1_contents.Data());
2989 CHECK_EQ(0xBB, ab1_data[0]);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002990 CHECK_EQ(0xFF, ab1_data[1]);
2991 ab1_data[0] = 0xCC;
2992 ab1_data[1] = 0x11;
2993 result = CompileRun("u8_a[0] + u8_a[1]");
2994 CHECK_EQ(0xDD, result->Int32Value());
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002995}
danno@chromium.orgca29dd82013-04-26 11:59:48 +00002996
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002997
2998THREADED_TEST(ArrayBuffer_External) {
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00002999 LocalContext env;
3000 v8::Isolate* isolate = env->GetIsolate();
3001 v8::HandleScope handle_scope(isolate);
3002
3003 i::ScopedVector<uint8_t> my_data(100);
3004 memset(my_data.start(), 0, 100);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +00003005 Local<v8::ArrayBuffer> ab3 =
3006 v8::ArrayBuffer::New(isolate, my_data.start(), 100);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00003007 CheckInternalFieldsAreZero(ab3);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003008 CHECK_EQ(100, static_cast<int>(ab3->ByteLength()));
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00003009 CHECK(ab3->IsExternal());
3010
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003011 env->Global()->Set(v8_str("ab3"), ab3);
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +00003012
3013 v8::Handle<v8::Value> result = CompileRun("ab3.byteLength");
3014 CHECK_EQ(100, result->Int32Value());
3015
danno@chromium.orgf005df62013-04-30 16:36:45 +00003016 result = CompileRun("var u8_b = new Uint8Array(ab3);"
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003017 "u8_b[0] = 0xBB;"
3018 "u8_b[1] = 0xCC;"
3019 "u8_b.length");
3020 CHECK_EQ(100, result->Int32Value());
3021 CHECK_EQ(0xBB, my_data[0]);
3022 CHECK_EQ(0xCC, my_data[1]);
3023 my_data[0] = 0xCC;
3024 my_data[1] = 0x11;
3025 result = CompileRun("u8_b[0] + u8_b[1]");
3026 CHECK_EQ(0xDD, result->Int32Value());
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003027}
3028
3029
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003030static void CheckDataViewIsNeutered(v8::Handle<v8::DataView> dv) {
3031 CHECK_EQ(0, static_cast<int>(dv->ByteLength()));
3032 CHECK_EQ(0, static_cast<int>(dv->ByteOffset()));
3033}
3034
3035
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003036static void CheckIsNeutered(v8::Handle<v8::TypedArray> ta) {
3037 CHECK_EQ(0, static_cast<int>(ta->ByteLength()));
3038 CHECK_EQ(0, static_cast<int>(ta->Length()));
3039 CHECK_EQ(0, static_cast<int>(ta->ByteOffset()));
3040}
3041
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003042
3043static void CheckIsTypedArrayVarNeutered(const char* name) {
3044 i::ScopedVector<char> source(1024);
3045 i::OS::SNPrintF(source,
3046 "%s.byteLength == 0 && %s.byteOffset == 0 && %s.length == 0",
3047 name, name, name);
3048 CHECK(CompileRun(source.start())->IsTrue());
3049 v8::Handle<v8::TypedArray> ta =
3050 v8::Handle<v8::TypedArray>::Cast(CompileRun(name));
3051 CheckIsNeutered(ta);
3052}
3053
3054
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003055template <typename TypedArray, int kElementSize>
3056static Handle<TypedArray> CreateAndCheck(Handle<v8::ArrayBuffer> ab,
3057 int byteOffset,
3058 int length) {
3059 v8::Handle<TypedArray> ta = TypedArray::New(ab, byteOffset, length);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00003060 CheckInternalFieldsAreZero<v8::ArrayBufferView>(ta);
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003061 CHECK_EQ(byteOffset, static_cast<int>(ta->ByteOffset()));
3062 CHECK_EQ(length, static_cast<int>(ta->Length()));
3063 CHECK_EQ(length * kElementSize, static_cast<int>(ta->ByteLength()));
3064 return ta;
3065}
3066
3067
3068THREADED_TEST(ArrayBuffer_NeuteringApi) {
3069 LocalContext env;
3070 v8::Isolate* isolate = env->GetIsolate();
3071 v8::HandleScope handle_scope(isolate);
3072
machenbach@chromium.org9f18d912013-11-28 13:42:41 +00003073 v8::Handle<v8::ArrayBuffer> buffer = v8::ArrayBuffer::New(isolate, 1024);
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003074
3075 v8::Handle<v8::Uint8Array> u8a =
3076 CreateAndCheck<v8::Uint8Array, 1>(buffer, 1, 1023);
3077 v8::Handle<v8::Uint8ClampedArray> u8c =
3078 CreateAndCheck<v8::Uint8ClampedArray, 1>(buffer, 1, 1023);
3079 v8::Handle<v8::Int8Array> i8a =
3080 CreateAndCheck<v8::Int8Array, 1>(buffer, 1, 1023);
3081
3082 v8::Handle<v8::Uint16Array> u16a =
3083 CreateAndCheck<v8::Uint16Array, 2>(buffer, 2, 511);
3084 v8::Handle<v8::Int16Array> i16a =
3085 CreateAndCheck<v8::Int16Array, 2>(buffer, 2, 511);
3086
3087 v8::Handle<v8::Uint32Array> u32a =
3088 CreateAndCheck<v8::Uint32Array, 4>(buffer, 4, 255);
3089 v8::Handle<v8::Int32Array> i32a =
3090 CreateAndCheck<v8::Int32Array, 4>(buffer, 4, 255);
3091
3092 v8::Handle<v8::Float32Array> f32a =
3093 CreateAndCheck<v8::Float32Array, 4>(buffer, 4, 255);
3094 v8::Handle<v8::Float64Array> f64a =
3095 CreateAndCheck<v8::Float64Array, 8>(buffer, 8, 127);
3096
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003097 v8::Handle<v8::DataView> dv = v8::DataView::New(buffer, 1, 1023);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00003098 CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003099 CHECK_EQ(1, static_cast<int>(dv->ByteOffset()));
3100 CHECK_EQ(1023, static_cast<int>(dv->ByteLength()));
3101
ulan@chromium.org837a67e2013-06-11 15:39:48 +00003102 ScopedArrayBufferContents contents(buffer->Externalize());
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003103 buffer->Neuter();
3104 CHECK_EQ(0, static_cast<int>(buffer->ByteLength()));
3105 CheckIsNeutered(u8a);
3106 CheckIsNeutered(u8c);
3107 CheckIsNeutered(i8a);
3108 CheckIsNeutered(u16a);
3109 CheckIsNeutered(i16a);
3110 CheckIsNeutered(u32a);
3111 CheckIsNeutered(i32a);
3112 CheckIsNeutered(f32a);
3113 CheckIsNeutered(f64a);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003114 CheckDataViewIsNeutered(dv);
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003115}
3116
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00003117
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003118THREADED_TEST(ArrayBuffer_NeuteringScript) {
3119 LocalContext env;
3120 v8::Isolate* isolate = env->GetIsolate();
3121 v8::HandleScope handle_scope(isolate);
3122
3123 CompileRun(
3124 "var ab = new ArrayBuffer(1024);"
3125 "var u8a = new Uint8Array(ab, 1, 1023);"
3126 "var u8c = new Uint8ClampedArray(ab, 1, 1023);"
3127 "var i8a = new Int8Array(ab, 1, 1023);"
3128 "var u16a = new Uint16Array(ab, 2, 511);"
3129 "var i16a = new Int16Array(ab, 2, 511);"
3130 "var u32a = new Uint32Array(ab, 4, 255);"
3131 "var i32a = new Int32Array(ab, 4, 255);"
3132 "var f32a = new Float32Array(ab, 4, 255);"
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003133 "var f64a = new Float64Array(ab, 8, 127);"
3134 "var dv = new DataView(ab, 1, 1023);");
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003135
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00003136 v8::Handle<v8::ArrayBuffer> ab =
3137 Local<v8::ArrayBuffer>::Cast(CompileRun("ab"));
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003138
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003139 v8::Handle<v8::DataView> dv =
3140 v8::Handle<v8::DataView>::Cast(CompileRun("dv"));
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003141
ulan@chromium.org837a67e2013-06-11 15:39:48 +00003142 ScopedArrayBufferContents contents(ab->Externalize());
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003143 ab->Neuter();
3144 CHECK_EQ(0, static_cast<int>(ab->ByteLength()));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003145 CHECK_EQ(0, CompileRun("ab.byteLength")->Int32Value());
3146
3147 CheckIsTypedArrayVarNeutered("u8a");
3148 CheckIsTypedArrayVarNeutered("u8c");
3149 CheckIsTypedArrayVarNeutered("i8a");
3150 CheckIsTypedArrayVarNeutered("u16a");
3151 CheckIsTypedArrayVarNeutered("i16a");
3152 CheckIsTypedArrayVarNeutered("u32a");
3153 CheckIsTypedArrayVarNeutered("i32a");
3154 CheckIsTypedArrayVarNeutered("f32a");
3155 CheckIsTypedArrayVarNeutered("f64a");
3156
3157 CHECK(CompileRun("dv.byteLength == 0 && dv.byteOffset == 0")->IsTrue());
3158 CheckDataViewIsNeutered(dv);
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003159}
3160
3161
3162
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003163THREADED_TEST(HiddenProperties) {
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003164 LocalContext env;
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003165 v8::Isolate* isolate = env->GetIsolate();
3166 v8::HandleScope scope(isolate);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003167
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003168 v8::Local<v8::Object> obj = v8::Object::New(env->GetIsolate());
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003169 v8::Local<v8::String> key = v8_str("api-test::hidden-key");
3170 v8::Local<v8::String> empty = v8_str("");
3171 v8::Local<v8::String> prop_name = v8_str("prop_name");
3172
machenbach@chromium.org528ce022013-09-23 14:09:36 +00003173 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003174
kasperl@chromium.orgacae3782009-04-11 09:17:08 +00003175 // Make sure delete of a non-existent hidden value works
3176 CHECK(obj->DeleteHiddenValue(key));
3177
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003178 CHECK(obj->SetHiddenValue(key, v8::Integer::New(isolate, 1503)));
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003179 CHECK_EQ(1503, obj->GetHiddenValue(key)->Int32Value());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003180 CHECK(obj->SetHiddenValue(key, v8::Integer::New(isolate, 2002)));
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003181 CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
3182
machenbach@chromium.org528ce022013-09-23 14:09:36 +00003183 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003184
3185 // Make sure we do not find the hidden property.
3186 CHECK(!obj->Has(empty));
3187 CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
3188 CHECK(obj->Get(empty)->IsUndefined());
3189 CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003190 CHECK(obj->Set(empty, v8::Integer::New(isolate, 2003)));
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003191 CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
3192 CHECK_EQ(2003, obj->Get(empty)->Int32Value());
3193
machenbach@chromium.org528ce022013-09-23 14:09:36 +00003194 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003195
3196 // Add another property and delete it afterwards to force the object in
3197 // slow case.
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003198 CHECK(obj->Set(prop_name, v8::Integer::New(isolate, 2008)));
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003199 CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
3200 CHECK_EQ(2008, obj->Get(prop_name)->Int32Value());
3201 CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
3202 CHECK(obj->Delete(prop_name));
3203 CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
3204
machenbach@chromium.org528ce022013-09-23 14:09:36 +00003205 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003206
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00003207 CHECK(obj->SetHiddenValue(key, Handle<Value>()));
3208 CHECK(obj->GetHiddenValue(key).IsEmpty());
3209
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003210 CHECK(obj->SetHiddenValue(key, v8::Integer::New(isolate, 2002)));
ager@chromium.org3b45ab52009-03-19 22:21:34 +00003211 CHECK(obj->DeleteHiddenValue(key));
3212 CHECK(obj->GetHiddenValue(key).IsEmpty());
3213}
3214
3215
ricow@chromium.org9fe9cdf2011-09-27 08:04:16 +00003216THREADED_TEST(Regress97784) {
3217 // Regression test for crbug.com/97784
3218 // Messing with the Object.prototype should not have effect on
3219 // hidden properties.
ricow@chromium.org9fe9cdf2011-09-27 08:04:16 +00003220 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003221 v8::HandleScope scope(env->GetIsolate());
ricow@chromium.org9fe9cdf2011-09-27 08:04:16 +00003222
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003223 v8::Local<v8::Object> obj = v8::Object::New(env->GetIsolate());
ricow@chromium.org9fe9cdf2011-09-27 08:04:16 +00003224 v8::Local<v8::String> key = v8_str("hidden");
3225
3226 CompileRun(
3227 "set_called = false;"
3228 "Object.defineProperty("
3229 " Object.prototype,"
3230 " 'hidden',"
3231 " {get: function() { return 45; },"
3232 " set: function() { set_called = true; }})");
3233
3234 CHECK(obj->GetHiddenValue(key).IsEmpty());
3235 // Make sure that the getter and setter from Object.prototype is not invoked.
3236 // If it did we would have full access to the hidden properties in
3237 // the accessor.
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003238 CHECK(obj->SetHiddenValue(key, v8::Integer::New(env->GetIsolate(), 42)));
ricow@chromium.org9fe9cdf2011-09-27 08:04:16 +00003239 ExpectFalse("set_called");
3240 CHECK_EQ(42, obj->GetHiddenValue(key)->Int32Value());
3241}
3242
3243
ager@chromium.orgc4c92722009-11-18 14:12:51 +00003244static bool interceptor_for_hidden_properties_called;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003245static void InterceptorForHiddenProperties(
3246 Local<String> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.orgc4c92722009-11-18 14:12:51 +00003247 interceptor_for_hidden_properties_called = true;
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00003248}
3249
3250
3251THREADED_TEST(HiddenPropertiesWithInterceptors) {
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00003252 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00003253 v8::Isolate* isolate = context->GetIsolate();
3254 v8::HandleScope scope(isolate);
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00003255
ager@chromium.orgc4c92722009-11-18 14:12:51 +00003256 interceptor_for_hidden_properties_called = false;
3257
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00003258 v8::Local<v8::String> key = v8_str("api-test::hidden-key");
3259
3260 // Associate an interceptor with an object and start setting hidden values.
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00003261 Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(isolate);
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00003262 Local<v8::ObjectTemplate> instance_templ = fun_templ->InstanceTemplate();
3263 instance_templ->SetNamedPropertyHandler(InterceptorForHiddenProperties);
3264 Local<v8::Function> function = fun_templ->GetFunction();
3265 Local<v8::Object> obj = function->NewInstance();
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003266 CHECK(obj->SetHiddenValue(key, v8::Integer::New(isolate, 2302)));
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00003267 CHECK_EQ(2302, obj->GetHiddenValue(key)->Int32Value());
ager@chromium.orgc4c92722009-11-18 14:12:51 +00003268 CHECK(!interceptor_for_hidden_properties_called);
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00003269}
3270
3271
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003272THREADED_TEST(External) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00003273 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003274 int x = 3;
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00003275 Local<v8::External> ext = v8::External::New(CcTest::isolate(), &x);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003276 LocalContext env;
3277 env->Global()->Set(v8_str("ext"), ext);
3278 Local<Value> reext_obj = Script::Compile(v8_str("this.ext"))->Run();
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00003279 v8::Handle<v8::External> reext = reext_obj.As<v8::External>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003280 int* ptr = static_cast<int*>(reext->Value());
3281 CHECK_EQ(x, 3);
3282 *ptr = 10;
3283 CHECK_EQ(x, 10);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00003284
3285 // Make sure unaligned pointers are wrapped properly.
3286 char* data = i::StrDup("0123456789");
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00003287 Local<v8::Value> zero = v8::External::New(CcTest::isolate(), &data[0]);
3288 Local<v8::Value> one = v8::External::New(CcTest::isolate(), &data[1]);
3289 Local<v8::Value> two = v8::External::New(CcTest::isolate(), &data[2]);
3290 Local<v8::Value> three = v8::External::New(CcTest::isolate(), &data[3]);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00003291
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00003292 char* char_ptr = reinterpret_cast<char*>(v8::External::Cast(*zero)->Value());
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00003293 CHECK_EQ('0', *char_ptr);
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00003294 char_ptr = reinterpret_cast<char*>(v8::External::Cast(*one)->Value());
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00003295 CHECK_EQ('1', *char_ptr);
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00003296 char_ptr = reinterpret_cast<char*>(v8::External::Cast(*two)->Value());
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00003297 CHECK_EQ('2', *char_ptr);
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00003298 char_ptr = reinterpret_cast<char*>(v8::External::Cast(*three)->Value());
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00003299 CHECK_EQ('3', *char_ptr);
3300 i::DeleteArray(data);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003301}
3302
3303
3304THREADED_TEST(GlobalHandle) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00003305 v8::Isolate* isolate = CcTest::isolate();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003306 v8::Persistent<String> global;
3307 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003308 v8::HandleScope scope(isolate);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003309 global.Reset(isolate, v8_str("str"));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003310 }
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00003311 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003312 v8::HandleScope scope(isolate);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003313 CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00003314 }
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00003315 global.Reset();
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003316 {
3317 v8::HandleScope scope(isolate);
3318 global.Reset(isolate, v8_str("str"));
3319 }
3320 {
3321 v8::HandleScope scope(isolate);
3322 CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
3323 }
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00003324 global.Reset();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003325}
3326
3327
ulan@chromium.org57ff8812013-05-10 08:16:55 +00003328THREADED_TEST(ResettingGlobalHandle) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00003329 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00003330 v8::Persistent<String> global;
3331 {
3332 v8::HandleScope scope(isolate);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003333 global.Reset(isolate, v8_str("str"));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00003334 }
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003335 v8::internal::GlobalHandles* global_handles =
3336 reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003337 int initial_handle_count = global_handles->global_handles_count();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00003338 {
3339 v8::HandleScope scope(isolate);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003340 CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00003341 }
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003342 {
3343 v8::HandleScope scope(isolate);
3344 global.Reset(isolate, v8_str("longer"));
3345 }
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003346 CHECK_EQ(global_handles->global_handles_count(), initial_handle_count);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003347 {
3348 v8::HandleScope scope(isolate);
3349 CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 6);
3350 }
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00003351 global.Reset();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003352 CHECK_EQ(global_handles->global_handles_count(), initial_handle_count - 1);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00003353}
3354
3355
3356THREADED_TEST(ResettingGlobalHandleToEmpty) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00003357 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00003358 v8::Persistent<String> global;
3359 {
3360 v8::HandleScope scope(isolate);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003361 global.Reset(isolate, v8_str("str"));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00003362 }
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003363 v8::internal::GlobalHandles* global_handles =
3364 reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003365 int initial_handle_count = global_handles->global_handles_count();
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003366 {
3367 v8::HandleScope scope(isolate);
3368 CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
3369 }
ulan@chromium.org57ff8812013-05-10 08:16:55 +00003370 {
3371 v8::HandleScope scope(isolate);
3372 Local<String> empty;
3373 global.Reset(isolate, empty);
3374 }
3375 CHECK(global.IsEmpty());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00003376 CHECK_EQ(global_handles->global_handles_count(), initial_handle_count - 1);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00003377}
3378
3379
machenbach@chromium.orgc86e8c22013-11-27 15:11:04 +00003380template<class T>
3381static v8::UniquePersistent<T> PassUnique(v8::UniquePersistent<T> unique) {
3382 return unique.Pass();
3383}
3384
3385
3386template<class T>
3387static v8::UniquePersistent<T> ReturnUnique(v8::Isolate* isolate,
3388 const v8::Persistent<T> & global) {
3389 v8::UniquePersistent<String> unique(isolate, global);
3390 return unique.Pass();
3391}
3392
3393
3394THREADED_TEST(UniquePersistent) {
3395 v8::Isolate* isolate = CcTest::isolate();
3396 v8::Persistent<String> global;
3397 {
3398 v8::HandleScope scope(isolate);
3399 global.Reset(isolate, v8_str("str"));
3400 }
3401 v8::internal::GlobalHandles* global_handles =
3402 reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
3403 int initial_handle_count = global_handles->global_handles_count();
3404 {
3405 v8::UniquePersistent<String> unique(isolate, global);
3406 CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
3407 // Test assignment via Pass
3408 {
3409 v8::UniquePersistent<String> copy = unique.Pass();
3410 CHECK(unique.IsEmpty());
3411 CHECK(copy == global);
3412 CHECK_EQ(initial_handle_count + 1,
3413 global_handles->global_handles_count());
3414 unique = copy.Pass();
3415 }
3416 // Test ctor via Pass
3417 {
3418 v8::UniquePersistent<String> copy(unique.Pass());
3419 CHECK(unique.IsEmpty());
3420 CHECK(copy == global);
3421 CHECK_EQ(initial_handle_count + 1,
3422 global_handles->global_handles_count());
3423 unique = copy.Pass();
3424 }
3425 // Test pass through function call
3426 {
3427 v8::UniquePersistent<String> copy = PassUnique(unique.Pass());
3428 CHECK(unique.IsEmpty());
3429 CHECK(copy == global);
3430 CHECK_EQ(initial_handle_count + 1,
3431 global_handles->global_handles_count());
3432 unique = copy.Pass();
3433 }
3434 CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
3435 }
3436 // Test pass from function call
3437 {
3438 v8::UniquePersistent<String> unique = ReturnUnique(isolate, global);
3439 CHECK(unique == global);
3440 CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
3441 }
3442 CHECK_EQ(initial_handle_count, global_handles->global_handles_count());
3443 global.Reset();
3444}
3445
3446
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003447THREADED_TEST(GlobalHandleUpcast) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00003448 v8::Isolate* isolate = CcTest::isolate();
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003449 v8::HandleScope scope(isolate);
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00003450 v8::Local<String> local = v8::Local<String>::New(isolate, v8_str("str"));
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003451 v8::Persistent<String> global_string(isolate, local);
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003452 v8::Persistent<Value>& global_value =
3453 v8::Persistent<Value>::Cast(global_string);
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003454 CHECK(v8::Local<v8::Value>::New(isolate, global_value)->IsString());
3455 CHECK(global_string == v8::Persistent<String>::Cast(global_value));
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00003456 global_string.Reset();
danno@chromium.org1fd77d52013-06-07 16:01:45 +00003457}
3458
3459
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +00003460THREADED_TEST(HandleEquality) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00003461 v8::Isolate* isolate = CcTest::isolate();
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +00003462 v8::Persistent<String> global1;
3463 v8::Persistent<String> global2;
3464 {
3465 v8::HandleScope scope(isolate);
3466 global1.Reset(isolate, v8_str("str"));
3467 global2.Reset(isolate, v8_str("str2"));
3468 }
3469 CHECK_EQ(global1 == global1, true);
3470 CHECK_EQ(global1 != global1, false);
3471 {
3472 v8::HandleScope scope(isolate);
3473 Local<String> local1 = Local<String>::New(isolate, global1);
3474 Local<String> local2 = Local<String>::New(isolate, global2);
3475
3476 CHECK_EQ(global1 == local1, true);
3477 CHECK_EQ(global1 != local1, false);
3478 CHECK_EQ(local1 == global1, true);
3479 CHECK_EQ(local1 != global1, false);
3480
3481 CHECK_EQ(global1 == local2, false);
3482 CHECK_EQ(global1 != local2, true);
3483 CHECK_EQ(local2 == global1, false);
3484 CHECK_EQ(local2 != global1, true);
3485
3486 CHECK_EQ(local1 == local2, false);
3487 CHECK_EQ(local1 != local2, true);
3488
3489 Local<String> anotherLocal1 = Local<String>::New(isolate, global1);
3490 CHECK_EQ(local1 == anotherLocal1, true);
3491 CHECK_EQ(local1 != anotherLocal1, false);
3492 }
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00003493 global1.Reset();
3494 global2.Reset();
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +00003495}
3496
3497
mstarzinger@chromium.org32280cf2012-12-06 17:32:37 +00003498THREADED_TEST(LocalHandle) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00003499 v8::HandleScope scope(CcTest::isolate());
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00003500 v8::Local<String> local =
3501 v8::Local<String>::New(CcTest::isolate(), v8_str("str"));
mstarzinger@chromium.org32280cf2012-12-06 17:32:37 +00003502 CHECK_EQ(local->Length(), 3);
3503}
3504
3505
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00003506class WeakCallCounter {
3507 public:
3508 explicit WeakCallCounter(int id) : id_(id), number_of_weak_calls_(0) { }
3509 int id() { return id_; }
3510 void increment() { number_of_weak_calls_++; }
3511 int NumberOfWeakCalls() { return number_of_weak_calls_; }
3512 private:
3513 int id_;
3514 int number_of_weak_calls_;
3515};
3516
3517
mstarzinger@chromium.org69008382013-10-18 10:34:25 +00003518template<typename T>
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003519struct WeakCallCounterAndPersistent {
3520 explicit WeakCallCounterAndPersistent(WeakCallCounter* counter)
3521 : counter(counter) {}
3522 WeakCallCounter* counter;
3523 v8::Persistent<T> handle;
3524};
3525
3526
3527template <typename T>
3528static void WeakPointerCallback(
3529 const v8::WeakCallbackData<T, WeakCallCounterAndPersistent<T> >& data) {
3530 CHECK_EQ(1234, data.GetParameter()->counter->id());
3531 data.GetParameter()->counter->increment();
3532 data.GetParameter()->handle.Reset();
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00003533}
3534
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00003535
mstarzinger@chromium.org69008382013-10-18 10:34:25 +00003536template<typename T>
3537static UniqueId MakeUniqueId(const Persistent<T>& p) {
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00003538 return UniqueId(reinterpret_cast<uintptr_t>(*v8::Utils::OpenPersistent(p)));
3539}
3540
3541
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003542THREADED_TEST(ApiObjectGroups) {
3543 LocalContext env;
3544 v8::Isolate* iso = env->GetIsolate();
3545 HandleScope scope(iso);
3546
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003547 WeakCallCounter counter(1234);
3548
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003549 WeakCallCounterAndPersistent<Value> g1s1(&counter);
3550 WeakCallCounterAndPersistent<Value> g1s2(&counter);
3551 WeakCallCounterAndPersistent<Value> g1c1(&counter);
3552 WeakCallCounterAndPersistent<Value> g2s1(&counter);
3553 WeakCallCounterAndPersistent<Value> g2s2(&counter);
3554 WeakCallCounterAndPersistent<Value> g2c1(&counter);
3555
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003556 {
3557 HandleScope scope(iso);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003558 g1s1.handle.Reset(iso, Object::New(iso));
3559 g1s2.handle.Reset(iso, Object::New(iso));
3560 g1c1.handle.Reset(iso, Object::New(iso));
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003561 g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback);
3562 g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback);
3563 g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003564
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003565 g2s1.handle.Reset(iso, Object::New(iso));
3566 g2s2.handle.Reset(iso, Object::New(iso));
3567 g2c1.handle.Reset(iso, Object::New(iso));
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003568 g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback);
3569 g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback);
3570 g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003571 }
3572
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003573 WeakCallCounterAndPersistent<Value> root(&counter);
3574 root.handle.Reset(iso, g1s1.handle); // make a root.
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003575
3576 // Connect group 1 and 2, make a cycle.
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003577 {
3578 HandleScope scope(iso);
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003579 CHECK(Local<Object>::New(iso, g1s2.handle.As<Object>())->
3580 Set(0, Local<Value>::New(iso, g2s2.handle)));
3581 CHECK(Local<Object>::New(iso, g2s1.handle.As<Object>())->
3582 Set(0, Local<Value>::New(iso, g1s1.handle)));
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003583 }
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003584
3585 {
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003586 UniqueId id1 = MakeUniqueId(g1s1.handle);
3587 UniqueId id2 = MakeUniqueId(g2s2.handle);
3588 iso->SetObjectGroupId(g1s1.handle, id1);
3589 iso->SetObjectGroupId(g1s2.handle, id1);
3590 iso->SetReferenceFromGroup(id1, g1c1.handle);
3591 iso->SetObjectGroupId(g2s1.handle, id2);
3592 iso->SetObjectGroupId(g2s2.handle, id2);
3593 iso->SetReferenceFromGroup(id2, g2c1.handle);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003594 }
3595 // Do a single full GC, ensure incremental marking is stopped.
3596 v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>(
3597 iso)->heap();
3598 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
3599
3600 // All object should be alive.
3601 CHECK_EQ(0, counter.NumberOfWeakCalls());
3602
3603 // Weaken the root.
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003604 root.handle.SetWeak(&root, &WeakPointerCallback);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003605 // But make children strong roots---all the objects (except for children)
3606 // should be collectable now.
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003607 g1c1.handle.ClearWeak();
3608 g2c1.handle.ClearWeak();
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003609
3610 // Groups are deleted, rebuild groups.
3611 {
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003612 UniqueId id1 = MakeUniqueId(g1s1.handle);
3613 UniqueId id2 = MakeUniqueId(g2s2.handle);
3614 iso->SetObjectGroupId(g1s1.handle, id1);
3615 iso->SetObjectGroupId(g1s2.handle, id1);
3616 iso->SetReferenceFromGroup(id1, g1c1.handle);
3617 iso->SetObjectGroupId(g2s1.handle, id2);
3618 iso->SetObjectGroupId(g2s2.handle, id2);
3619 iso->SetReferenceFromGroup(id2, g2c1.handle);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003620 }
3621
3622 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
3623
3624 // All objects should be gone. 5 global handles in total.
3625 CHECK_EQ(5, counter.NumberOfWeakCalls());
3626
3627 // And now make children weak again and collect them.
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003628 g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback);
3629 g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003630
3631 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
3632 CHECK_EQ(7, counter.NumberOfWeakCalls());
3633}
3634
3635
mstarzinger@chromium.org69008382013-10-18 10:34:25 +00003636THREADED_TEST(ApiObjectGroupsForSubtypes) {
3637 LocalContext env;
3638 v8::Isolate* iso = env->GetIsolate();
3639 HandleScope scope(iso);
3640
mstarzinger@chromium.org69008382013-10-18 10:34:25 +00003641 WeakCallCounter counter(1234);
3642
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003643 WeakCallCounterAndPersistent<Object> g1s1(&counter);
3644 WeakCallCounterAndPersistent<String> g1s2(&counter);
3645 WeakCallCounterAndPersistent<String> g1c1(&counter);
3646 WeakCallCounterAndPersistent<Object> g2s1(&counter);
3647 WeakCallCounterAndPersistent<String> g2s2(&counter);
3648 WeakCallCounterAndPersistent<String> g2c1(&counter);
3649
mstarzinger@chromium.org69008382013-10-18 10:34:25 +00003650 {
3651 HandleScope scope(iso);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003652 g1s1.handle.Reset(iso, Object::New(iso));
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003653 g1s2.handle.Reset(iso, String::NewFromUtf8(iso, "foo1"));
3654 g1c1.handle.Reset(iso, String::NewFromUtf8(iso, "foo2"));
3655 g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback);
3656 g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback);
3657 g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback);
mstarzinger@chromium.org69008382013-10-18 10:34:25 +00003658
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003659 g2s1.handle.Reset(iso, Object::New(iso));
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003660 g2s2.handle.Reset(iso, String::NewFromUtf8(iso, "foo3"));
3661 g2c1.handle.Reset(iso, String::NewFromUtf8(iso, "foo4"));
3662 g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback);
3663 g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback);
3664 g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback);
mstarzinger@chromium.org69008382013-10-18 10:34:25 +00003665 }
3666
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003667 WeakCallCounterAndPersistent<Value> root(&counter);
3668 root.handle.Reset(iso, g1s1.handle); // make a root.
mstarzinger@chromium.org69008382013-10-18 10:34:25 +00003669
3670 // Connect group 1 and 2, make a cycle.
3671 {
3672 HandleScope scope(iso);
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003673 CHECK(Local<Object>::New(iso, g1s1.handle)
3674 ->Set(0, Local<Object>::New(iso, g2s1.handle)));
3675 CHECK(Local<Object>::New(iso, g2s1.handle)
3676 ->Set(0, Local<Object>::New(iso, g1s1.handle)));
mstarzinger@chromium.org69008382013-10-18 10:34:25 +00003677 }
3678
3679 {
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003680 UniqueId id1 = MakeUniqueId(g1s1.handle);
3681 UniqueId id2 = MakeUniqueId(g2s2.handle);
3682 iso->SetObjectGroupId(g1s1.handle, id1);
3683 iso->SetObjectGroupId(g1s2.handle, id1);
3684 iso->SetReference(g1s1.handle, g1c1.handle);
3685 iso->SetObjectGroupId(g2s1.handle, id2);
3686 iso->SetObjectGroupId(g2s2.handle, id2);
3687 iso->SetReferenceFromGroup(id2, g2c1.handle);
mstarzinger@chromium.org69008382013-10-18 10:34:25 +00003688 }
3689 // Do a single full GC, ensure incremental marking is stopped.
3690 v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>(
3691 iso)->heap();
3692 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
3693
3694 // All object should be alive.
3695 CHECK_EQ(0, counter.NumberOfWeakCalls());
3696
3697 // Weaken the root.
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003698 root.handle.SetWeak(&root, &WeakPointerCallback);
mstarzinger@chromium.org69008382013-10-18 10:34:25 +00003699 // But make children strong roots---all the objects (except for children)
3700 // should be collectable now.
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003701 g1c1.handle.ClearWeak();
3702 g2c1.handle.ClearWeak();
mstarzinger@chromium.org69008382013-10-18 10:34:25 +00003703
3704 // Groups are deleted, rebuild groups.
3705 {
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003706 UniqueId id1 = MakeUniqueId(g1s1.handle);
3707 UniqueId id2 = MakeUniqueId(g2s2.handle);
3708 iso->SetObjectGroupId(g1s1.handle, id1);
3709 iso->SetObjectGroupId(g1s2.handle, id1);
3710 iso->SetReference(g1s1.handle, g1c1.handle);
3711 iso->SetObjectGroupId(g2s1.handle, id2);
3712 iso->SetObjectGroupId(g2s2.handle, id2);
3713 iso->SetReferenceFromGroup(id2, g2c1.handle);
mstarzinger@chromium.org69008382013-10-18 10:34:25 +00003714 }
3715
3716 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
3717
3718 // All objects should be gone. 5 global handles in total.
3719 CHECK_EQ(5, counter.NumberOfWeakCalls());
3720
3721 // And now make children weak again and collect them.
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003722 g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback);
3723 g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback);
mstarzinger@chromium.org69008382013-10-18 10:34:25 +00003724
3725 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
3726 CHECK_EQ(7, counter.NumberOfWeakCalls());
3727}
3728
3729
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003730THREADED_TEST(ApiObjectGroupsCycle) {
3731 LocalContext env;
3732 v8::Isolate* iso = env->GetIsolate();
3733 HandleScope scope(iso);
3734
3735 WeakCallCounter counter(1234);
3736
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003737 WeakCallCounterAndPersistent<Value> g1s1(&counter);
3738 WeakCallCounterAndPersistent<Value> g1s2(&counter);
3739 WeakCallCounterAndPersistent<Value> g2s1(&counter);
3740 WeakCallCounterAndPersistent<Value> g2s2(&counter);
3741 WeakCallCounterAndPersistent<Value> g3s1(&counter);
3742 WeakCallCounterAndPersistent<Value> g3s2(&counter);
3743 WeakCallCounterAndPersistent<Value> g4s1(&counter);
3744 WeakCallCounterAndPersistent<Value> g4s2(&counter);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003745
3746 {
3747 HandleScope scope(iso);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003748 g1s1.handle.Reset(iso, Object::New(iso));
3749 g1s2.handle.Reset(iso, Object::New(iso));
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003750 g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback);
3751 g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback);
3752 CHECK(g1s1.handle.IsWeak());
3753 CHECK(g1s2.handle.IsWeak());
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003754
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003755 g2s1.handle.Reset(iso, Object::New(iso));
3756 g2s2.handle.Reset(iso, Object::New(iso));
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003757 g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback);
3758 g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback);
3759 CHECK(g2s1.handle.IsWeak());
3760 CHECK(g2s2.handle.IsWeak());
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003761
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003762 g3s1.handle.Reset(iso, Object::New(iso));
3763 g3s2.handle.Reset(iso, Object::New(iso));
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003764 g3s1.handle.SetWeak(&g3s1, &WeakPointerCallback);
3765 g3s2.handle.SetWeak(&g3s2, &WeakPointerCallback);
3766 CHECK(g3s1.handle.IsWeak());
3767 CHECK(g3s2.handle.IsWeak());
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003768
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003769 g4s1.handle.Reset(iso, Object::New(iso));
3770 g4s2.handle.Reset(iso, Object::New(iso));
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003771 g4s1.handle.SetWeak(&g4s1, &WeakPointerCallback);
3772 g4s2.handle.SetWeak(&g4s2, &WeakPointerCallback);
3773 CHECK(g4s1.handle.IsWeak());
3774 CHECK(g4s2.handle.IsWeak());
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003775 }
3776
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003777 WeakCallCounterAndPersistent<Value> root(&counter);
3778 root.handle.Reset(iso, g1s1.handle); // make a root.
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003779
3780 // Connect groups. We're building the following cycle:
3781 // G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other
3782 // groups.
3783 {
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003784 UniqueId id1 = MakeUniqueId(g1s1.handle);
3785 UniqueId id2 = MakeUniqueId(g2s1.handle);
3786 UniqueId id3 = MakeUniqueId(g3s1.handle);
3787 UniqueId id4 = MakeUniqueId(g4s1.handle);
3788 iso->SetObjectGroupId(g1s1.handle, id1);
3789 iso->SetObjectGroupId(g1s2.handle, id1);
3790 iso->SetReferenceFromGroup(id1, g2s1.handle);
3791 iso->SetObjectGroupId(g2s1.handle, id2);
3792 iso->SetObjectGroupId(g2s2.handle, id2);
3793 iso->SetReferenceFromGroup(id2, g3s1.handle);
3794 iso->SetObjectGroupId(g3s1.handle, id3);
3795 iso->SetObjectGroupId(g3s2.handle, id3);
3796 iso->SetReferenceFromGroup(id3, g4s1.handle);
3797 iso->SetObjectGroupId(g4s1.handle, id4);
3798 iso->SetObjectGroupId(g4s2.handle, id4);
3799 iso->SetReferenceFromGroup(id4, g1s1.handle);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003800 }
3801 // Do a single full GC
3802 v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>(
3803 iso)->heap();
3804 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
3805
3806 // All object should be alive.
3807 CHECK_EQ(0, counter.NumberOfWeakCalls());
3808
3809 // Weaken the root.
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003810 root.handle.SetWeak(&root, &WeakPointerCallback);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003811
3812 // Groups are deleted, rebuild groups.
3813 {
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003814 UniqueId id1 = MakeUniqueId(g1s1.handle);
3815 UniqueId id2 = MakeUniqueId(g2s1.handle);
3816 UniqueId id3 = MakeUniqueId(g3s1.handle);
3817 UniqueId id4 = MakeUniqueId(g4s1.handle);
3818 iso->SetObjectGroupId(g1s1.handle, id1);
3819 iso->SetObjectGroupId(g1s2.handle, id1);
3820 iso->SetReferenceFromGroup(id1, g2s1.handle);
3821 iso->SetObjectGroupId(g2s1.handle, id2);
3822 iso->SetObjectGroupId(g2s2.handle, id2);
3823 iso->SetReferenceFromGroup(id2, g3s1.handle);
3824 iso->SetObjectGroupId(g3s1.handle, id3);
3825 iso->SetObjectGroupId(g3s2.handle, id3);
3826 iso->SetReferenceFromGroup(id3, g4s1.handle);
3827 iso->SetObjectGroupId(g4s1.handle, id4);
3828 iso->SetObjectGroupId(g4s2.handle, id4);
3829 iso->SetReferenceFromGroup(id4, g1s1.handle);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003830 }
3831
3832 heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
3833
3834 // All objects should be gone. 9 global handles in total.
3835 CHECK_EQ(9, counter.NumberOfWeakCalls());
3836}
3837
3838
mvstanton@chromium.orge4ac3ef2012-11-12 14:53:34 +00003839// TODO(mstarzinger): This should be a THREADED_TEST but causes failures
3840// on the buildbots, so was made non-threaded for the time being.
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003841TEST(ApiObjectGroupsCycleForScavenger) {
3842 i::FLAG_stress_compaction = false;
3843 i::FLAG_gc_global = false;
3844 LocalContext env;
3845 v8::Isolate* iso = env->GetIsolate();
3846 HandleScope scope(iso);
3847
3848 WeakCallCounter counter(1234);
3849
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003850 WeakCallCounterAndPersistent<Value> g1s1(&counter);
3851 WeakCallCounterAndPersistent<Value> g1s2(&counter);
3852 WeakCallCounterAndPersistent<Value> g2s1(&counter);
3853 WeakCallCounterAndPersistent<Value> g2s2(&counter);
3854 WeakCallCounterAndPersistent<Value> g3s1(&counter);
3855 WeakCallCounterAndPersistent<Value> g3s2(&counter);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003856
3857 {
3858 HandleScope scope(iso);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003859 g1s1.handle.Reset(iso, Object::New(iso));
3860 g1s2.handle.Reset(iso, Object::New(iso));
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003861 g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback);
3862 g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003863
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003864 g2s1.handle.Reset(iso, Object::New(iso));
3865 g2s2.handle.Reset(iso, Object::New(iso));
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003866 g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback);
3867 g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003868
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003869 g3s1.handle.Reset(iso, Object::New(iso));
3870 g3s2.handle.Reset(iso, Object::New(iso));
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003871 g3s1.handle.SetWeak(&g3s1, &WeakPointerCallback);
3872 g3s2.handle.SetWeak(&g3s2, &WeakPointerCallback);
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003873 }
3874
3875 // Make a root.
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003876 WeakCallCounterAndPersistent<Value> root(&counter);
3877 root.handle.Reset(iso, g1s1.handle);
3878 root.handle.MarkPartiallyDependent();
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003879
3880 // Connect groups. We're building the following cycle:
3881 // G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other
3882 // groups.
3883 {
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003884 HandleScope handle_scope(iso);
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003885 g1s1.handle.MarkPartiallyDependent();
3886 g1s2.handle.MarkPartiallyDependent();
3887 g2s1.handle.MarkPartiallyDependent();
3888 g2s2.handle.MarkPartiallyDependent();
3889 g3s1.handle.MarkPartiallyDependent();
3890 g3s2.handle.MarkPartiallyDependent();
3891 iso->SetObjectGroupId(g1s1.handle, UniqueId(1));
3892 iso->SetObjectGroupId(g1s2.handle, UniqueId(1));
3893 Local<Object>::New(iso, g1s1.handle.As<Object>())->Set(
3894 v8_str("x"), Local<Value>::New(iso, g2s1.handle));
3895 iso->SetObjectGroupId(g2s1.handle, UniqueId(2));
3896 iso->SetObjectGroupId(g2s2.handle, UniqueId(2));
3897 Local<Object>::New(iso, g2s1.handle.As<Object>())->Set(
3898 v8_str("x"), Local<Value>::New(iso, g3s1.handle));
3899 iso->SetObjectGroupId(g3s1.handle, UniqueId(3));
3900 iso->SetObjectGroupId(g3s2.handle, UniqueId(3));
3901 Local<Object>::New(iso, g3s1.handle.As<Object>())->Set(
3902 v8_str("x"), Local<Value>::New(iso, g1s1.handle));
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003903 }
3904
3905 v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>(
3906 iso)->heap();
3907 heap->CollectGarbage(i::NEW_SPACE);
3908
3909 // All objects should be alive.
3910 CHECK_EQ(0, counter.NumberOfWeakCalls());
3911
3912 // Weaken the root.
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003913 root.handle.SetWeak(&root, &WeakPointerCallback);
3914 root.handle.MarkPartiallyDependent();
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003915
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003916 // Groups are deleted, rebuild groups.
3917 {
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00003918 HandleScope handle_scope(iso);
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00003919 g1s1.handle.MarkPartiallyDependent();
3920 g1s2.handle.MarkPartiallyDependent();
3921 g2s1.handle.MarkPartiallyDependent();
3922 g2s2.handle.MarkPartiallyDependent();
3923 g3s1.handle.MarkPartiallyDependent();
3924 g3s2.handle.MarkPartiallyDependent();
3925 iso->SetObjectGroupId(g1s1.handle, UniqueId(1));
3926 iso->SetObjectGroupId(g1s2.handle, UniqueId(1));
3927 Local<Object>::New(iso, g1s1.handle.As<Object>())->Set(
3928 v8_str("x"), Local<Value>::New(iso, g2s1.handle));
3929 iso->SetObjectGroupId(g2s1.handle, UniqueId(2));
3930 iso->SetObjectGroupId(g2s2.handle, UniqueId(2));
3931 Local<Object>::New(iso, g2s1.handle.As<Object>())->Set(
3932 v8_str("x"), Local<Value>::New(iso, g3s1.handle));
3933 iso->SetObjectGroupId(g3s1.handle, UniqueId(3));
3934 iso->SetObjectGroupId(g3s2.handle, UniqueId(3));
3935 Local<Object>::New(iso, g3s1.handle.As<Object>())->Set(
3936 v8_str("x"), Local<Value>::New(iso, g1s1.handle));
danno@chromium.orgca29dd82013-04-26 11:59:48 +00003937 }
3938
3939 heap->CollectGarbage(i::NEW_SPACE);
3940
3941 // All objects should be gone. 7 global handles in total.
3942 CHECK_EQ(7, counter.NumberOfWeakCalls());
3943}
3944
3945
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003946THREADED_TEST(ScriptException) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003947 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003948 v8::HandleScope scope(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003949 Local<Script> script = Script::Compile(v8_str("throw 'panama!';"));
3950 v8::TryCatch try_catch;
3951 Local<Value> result = script->Run();
3952 CHECK(result.IsEmpty());
3953 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00003954 String::Utf8Value exception_value(try_catch.Exception());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003955 CHECK_EQ(*exception_value, "panama!");
3956}
3957
3958
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00003959TEST(TryCatchCustomException) {
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00003960 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00003961 v8::HandleScope scope(env->GetIsolate());
yangguo@chromium.orgeeb44b62012-11-13 13:56:09 +00003962 v8::TryCatch try_catch;
3963 CompileRun("function CustomError() { this.a = 'b'; }"
3964 "(function f() { throw new CustomError(); })();");
3965 CHECK(try_catch.HasCaught());
3966 CHECK(try_catch.Exception()->ToObject()->
3967 Get(v8_str("a"))->Equals(v8_str("b")));
3968}
3969
3970
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003971bool message_received;
3972
3973
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00003974static void check_message_0(v8::Handle<v8::Message> message,
3975 v8::Handle<Value> data) {
hpayer@chromium.org8432c912013-02-28 15:55:26 +00003976 CHECK_EQ(5.76, data->NumberValue());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00003977 CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
ager@chromium.org65dad4b2009-04-23 08:48:43 +00003978 CHECK_EQ(7.56, message->GetScriptData()->NumberValue());
danno@chromium.orgd3c42102013-08-01 16:58:23 +00003979 CHECK(!message->IsSharedCrossOrigin());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003980 message_received = true;
3981}
3982
3983
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00003984THREADED_TEST(MessageHandler0) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003985 message_received = false;
machenbach@chromium.org528ce022013-09-23 14:09:36 +00003986 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003987 CHECK(!message_received);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003988 LocalContext context;
ulan@chromium.org0f13e742014-01-03 15:51:11 +00003989 v8::V8::AddMessageListener(check_message_0, v8_num(5.76));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003990 v8::ScriptOrigin origin =
3991 v8::ScriptOrigin(v8_str("6.75"));
ager@chromium.org65dad4b2009-04-23 08:48:43 +00003992 v8::Handle<v8::Script> script = Script::Compile(v8_str("throw 'error'"),
3993 &origin);
3994 script->SetData(v8_str("7.56"));
3995 script->Run();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00003996 CHECK(message_received);
3997 // clear out the message listener
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00003998 v8::V8::RemoveMessageListeners(check_message_0);
3999}
4000
4001
4002static void check_message_1(v8::Handle<v8::Message> message,
4003 v8::Handle<Value> data) {
4004 CHECK(data->IsNumber());
4005 CHECK_EQ(1337, data->Int32Value());
danno@chromium.orgd3c42102013-08-01 16:58:23 +00004006 CHECK(!message->IsSharedCrossOrigin());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00004007 message_received = true;
4008}
4009
4010
4011TEST(MessageHandler1) {
4012 message_received = false;
machenbach@chromium.org528ce022013-09-23 14:09:36 +00004013 v8::HandleScope scope(CcTest::isolate());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00004014 CHECK(!message_received);
4015 v8::V8::AddMessageListener(check_message_1);
4016 LocalContext context;
4017 CompileRun("throw 1337;");
4018 CHECK(message_received);
4019 // clear out the message listener
4020 v8::V8::RemoveMessageListeners(check_message_1);
4021}
4022
4023
4024static void check_message_2(v8::Handle<v8::Message> message,
4025 v8::Handle<Value> data) {
4026 LocalContext context;
4027 CHECK(data->IsObject());
4028 v8::Local<v8::Value> hidden_property =
4029 v8::Object::Cast(*data)->GetHiddenValue(v8_str("hidden key"));
4030 CHECK(v8_str("hidden value")->Equals(hidden_property));
danno@chromium.orgd3c42102013-08-01 16:58:23 +00004031 CHECK(!message->IsSharedCrossOrigin());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00004032 message_received = true;
4033}
4034
4035
4036TEST(MessageHandler2) {
4037 message_received = false;
machenbach@chromium.org528ce022013-09-23 14:09:36 +00004038 v8::HandleScope scope(CcTest::isolate());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00004039 CHECK(!message_received);
4040 v8::V8::AddMessageListener(check_message_2);
4041 LocalContext context;
4042 v8::Local<v8::Value> error = v8::Exception::Error(v8_str("custom error"));
4043 v8::Object::Cast(*error)->SetHiddenValue(v8_str("hidden key"),
4044 v8_str("hidden value"));
4045 context->Global()->Set(v8_str("error"), error);
4046 CompileRun("throw error;");
4047 CHECK(message_received);
4048 // clear out the message listener
4049 v8::V8::RemoveMessageListeners(check_message_2);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004050}
4051
4052
danno@chromium.orgd3c42102013-08-01 16:58:23 +00004053static void check_message_3(v8::Handle<v8::Message> message,
4054 v8::Handle<Value> data) {
4055 CHECK(message->IsSharedCrossOrigin());
4056 CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
4057 message_received = true;
4058}
4059
4060
4061TEST(MessageHandler3) {
4062 message_received = false;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00004063 v8::Isolate* isolate = CcTest::isolate();
4064 v8::HandleScope scope(isolate);
danno@chromium.orgd3c42102013-08-01 16:58:23 +00004065 CHECK(!message_received);
4066 v8::V8::AddMessageListener(check_message_3);
4067 LocalContext context;
4068 v8::ScriptOrigin origin =
4069 v8::ScriptOrigin(v8_str("6.75"),
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004070 v8::Integer::New(isolate, 1),
4071 v8::Integer::New(isolate, 2),
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00004072 v8::True(isolate));
danno@chromium.orgd3c42102013-08-01 16:58:23 +00004073 v8::Handle<v8::Script> script = Script::Compile(v8_str("throw 'error'"),
4074 &origin);
4075 script->Run();
4076 CHECK(message_received);
4077 // clear out the message listener
4078 v8::V8::RemoveMessageListeners(check_message_3);
4079}
4080
4081
4082static void check_message_4(v8::Handle<v8::Message> message,
4083 v8::Handle<Value> data) {
4084 CHECK(!message->IsSharedCrossOrigin());
4085 CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
4086 message_received = true;
4087}
4088
4089
4090TEST(MessageHandler4) {
4091 message_received = false;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00004092 v8::Isolate* isolate = CcTest::isolate();
4093 v8::HandleScope scope(isolate);
danno@chromium.orgd3c42102013-08-01 16:58:23 +00004094 CHECK(!message_received);
4095 v8::V8::AddMessageListener(check_message_4);
4096 LocalContext context;
4097 v8::ScriptOrigin origin =
4098 v8::ScriptOrigin(v8_str("6.75"),
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004099 v8::Integer::New(isolate, 1),
4100 v8::Integer::New(isolate, 2),
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00004101 v8::False(isolate));
danno@chromium.orgd3c42102013-08-01 16:58:23 +00004102 v8::Handle<v8::Script> script = Script::Compile(v8_str("throw 'error'"),
4103 &origin);
4104 script->Run();
4105 CHECK(message_received);
4106 // clear out the message listener
4107 v8::V8::RemoveMessageListeners(check_message_4);
4108}
4109
4110
4111static void check_message_5a(v8::Handle<v8::Message> message,
4112 v8::Handle<Value> data) {
4113 CHECK(message->IsSharedCrossOrigin());
4114 CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
4115 message_received = true;
4116}
4117
4118
4119static void check_message_5b(v8::Handle<v8::Message> message,
4120 v8::Handle<Value> data) {
4121 CHECK(!message->IsSharedCrossOrigin());
4122 CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
4123 message_received = true;
4124}
4125
4126
4127TEST(MessageHandler5) {
4128 message_received = false;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00004129 v8::Isolate* isolate = CcTest::isolate();
4130 v8::HandleScope scope(isolate);
danno@chromium.orgd3c42102013-08-01 16:58:23 +00004131 CHECK(!message_received);
4132 v8::V8::AddMessageListener(check_message_5a);
4133 LocalContext context;
4134 v8::ScriptOrigin origin =
4135 v8::ScriptOrigin(v8_str("6.75"),
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004136 v8::Integer::New(isolate, 1),
4137 v8::Integer::New(isolate, 2),
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00004138 v8::True(isolate));
danno@chromium.orgd3c42102013-08-01 16:58:23 +00004139 v8::Handle<v8::Script> script = Script::Compile(v8_str("throw 'error'"),
4140 &origin);
4141 script->Run();
4142 CHECK(message_received);
4143 // clear out the message listener
4144 v8::V8::RemoveMessageListeners(check_message_5a);
4145
4146 message_received = false;
4147 v8::V8::AddMessageListener(check_message_5b);
4148 origin =
4149 v8::ScriptOrigin(v8_str("6.75"),
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004150 v8::Integer::New(isolate, 1),
4151 v8::Integer::New(isolate, 2),
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00004152 v8::False(isolate));
danno@chromium.orgd3c42102013-08-01 16:58:23 +00004153 script = Script::Compile(v8_str("throw 'error'"),
4154 &origin);
4155 script->Run();
4156 CHECK(message_received);
4157 // clear out the message listener
4158 v8::V8::RemoveMessageListeners(check_message_5b);
4159}
4160
4161
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004162THREADED_TEST(GetSetProperty) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004163 LocalContext context;
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004164 v8::Isolate* isolate = context->GetIsolate();
4165 v8::HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004166 context->Global()->Set(v8_str("foo"), v8_num(14));
4167 context->Global()->Set(v8_str("12"), v8_num(92));
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004168 context->Global()->Set(v8::Integer::New(isolate, 16), v8_num(32));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004169 context->Global()->Set(v8_num(13), v8_num(56));
4170 Local<Value> foo = Script::Compile(v8_str("this.foo"))->Run();
4171 CHECK_EQ(14, foo->Int32Value());
4172 Local<Value> twelve = Script::Compile(v8_str("this[12]"))->Run();
4173 CHECK_EQ(92, twelve->Int32Value());
4174 Local<Value> sixteen = Script::Compile(v8_str("this[16]"))->Run();
4175 CHECK_EQ(32, sixteen->Int32Value());
4176 Local<Value> thirteen = Script::Compile(v8_str("this[13]"))->Run();
4177 CHECK_EQ(56, thirteen->Int32Value());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004178 CHECK_EQ(92,
4179 context->Global()->Get(v8::Integer::New(isolate, 12))->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004180 CHECK_EQ(92, context->Global()->Get(v8_str("12"))->Int32Value());
4181 CHECK_EQ(92, context->Global()->Get(v8_num(12))->Int32Value());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004182 CHECK_EQ(32,
4183 context->Global()->Get(v8::Integer::New(isolate, 16))->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004184 CHECK_EQ(32, context->Global()->Get(v8_str("16"))->Int32Value());
4185 CHECK_EQ(32, context->Global()->Get(v8_num(16))->Int32Value());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004186 CHECK_EQ(56,
4187 context->Global()->Get(v8::Integer::New(isolate, 13))->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004188 CHECK_EQ(56, context->Global()->Get(v8_str("13"))->Int32Value());
4189 CHECK_EQ(56, context->Global()->Get(v8_num(13))->Int32Value());
4190}
4191
4192
4193THREADED_TEST(PropertyAttributes) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004194 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004195 v8::HandleScope scope(context->GetIsolate());
rossberg@chromium.org717967f2011-07-20 13:44:42 +00004196 // none
4197 Local<String> prop = v8_str("none");
4198 context->Global()->Set(prop, v8_num(7));
4199 CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(prop));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004200 // read-only
rossberg@chromium.org717967f2011-07-20 13:44:42 +00004201 prop = v8_str("read_only");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004202 context->Global()->Set(prop, v8_num(7), v8::ReadOnly);
4203 CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
rossberg@chromium.org717967f2011-07-20 13:44:42 +00004204 CHECK_EQ(v8::ReadOnly, context->Global()->GetPropertyAttributes(prop));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004205 Script::Compile(v8_str("read_only = 9"))->Run();
4206 CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
4207 context->Global()->Set(prop, v8_num(10));
4208 CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
4209 // dont-delete
4210 prop = v8_str("dont_delete");
4211 context->Global()->Set(prop, v8_num(13), v8::DontDelete);
4212 CHECK_EQ(13, context->Global()->Get(prop)->Int32Value());
4213 Script::Compile(v8_str("delete dont_delete"))->Run();
4214 CHECK_EQ(13, context->Global()->Get(prop)->Int32Value());
rossberg@chromium.org717967f2011-07-20 13:44:42 +00004215 CHECK_EQ(v8::DontDelete, context->Global()->GetPropertyAttributes(prop));
4216 // dont-enum
4217 prop = v8_str("dont_enum");
4218 context->Global()->Set(prop, v8_num(28), v8::DontEnum);
4219 CHECK_EQ(v8::DontEnum, context->Global()->GetPropertyAttributes(prop));
4220 // absent
4221 prop = v8_str("absent");
4222 CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(prop));
4223 Local<Value> fake_prop = v8_num(1);
4224 CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(fake_prop));
4225 // exception
4226 TryCatch try_catch;
4227 Local<Value> exception =
4228 CompileRun("({ toString: function() { throw 'exception';} })");
4229 CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(exception));
4230 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00004231 String::Utf8Value exception_value(try_catch.Exception());
rossberg@chromium.org717967f2011-07-20 13:44:42 +00004232 CHECK_EQ("exception", *exception_value);
4233 try_catch.Reset();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004234}
4235
4236
4237THREADED_TEST(Array) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004238 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004239 v8::HandleScope scope(context->GetIsolate());
machenbach@chromium.org9f18d912013-11-28 13:42:41 +00004240 Local<v8::Array> array = v8::Array::New(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004241 CHECK_EQ(0, array->Length());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004242 CHECK(array->Get(0)->IsUndefined());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004243 CHECK(!array->Has(0));
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004244 CHECK(array->Get(100)->IsUndefined());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004245 CHECK(!array->Has(100));
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004246 array->Set(2, v8_num(7));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004247 CHECK_EQ(3, array->Length());
4248 CHECK(!array->Has(0));
4249 CHECK(!array->Has(1));
4250 CHECK(array->Has(2));
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004251 CHECK_EQ(7, array->Get(2)->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004252 Local<Value> obj = Script::Compile(v8_str("[1, 2, 3]"))->Run();
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004253 Local<v8::Array> arr = obj.As<v8::Array>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004254 CHECK_EQ(3, arr->Length());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004255 CHECK_EQ(1, arr->Get(0)->Int32Value());
4256 CHECK_EQ(2, arr->Get(1)->Int32Value());
4257 CHECK_EQ(3, arr->Get(2)->Int32Value());
machenbach@chromium.org9f18d912013-11-28 13:42:41 +00004258 array = v8::Array::New(context->GetIsolate(), 27);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00004259 CHECK_EQ(27, array->Length());
machenbach@chromium.org9f18d912013-11-28 13:42:41 +00004260 array = v8::Array::New(context->GetIsolate(), -27);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00004261 CHECK_EQ(0, array->Length());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004262}
4263
4264
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00004265void HandleF(const v8::FunctionCallbackInfo<v8::Value>& args) {
machenbach@chromium.orgafbdadc2013-12-09 16:12:18 +00004266 v8::EscapableHandleScope scope(args.GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004267 ApiTestFuzzer::Fuzz();
machenbach@chromium.org9f18d912013-11-28 13:42:41 +00004268 Local<v8::Array> result = v8::Array::New(args.GetIsolate(), args.Length());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004269 for (int i = 0; i < args.Length(); i++)
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004270 result->Set(i, args[i]);
machenbach@chromium.orgafbdadc2013-12-09 16:12:18 +00004271 args.GetReturnValue().Set(scope.Escape(result));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004272}
4273
4274
4275THREADED_TEST(Vector) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00004276 v8::Isolate* isolate = CcTest::isolate();
4277 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004278 Local<ObjectTemplate> global = ObjectTemplate::New(isolate);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00004279 global->Set(v8_str("f"), v8::FunctionTemplate::New(isolate, HandleF));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004280 LocalContext context(0, global);
4281
4282 const char* fun = "f()";
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004283 Local<v8::Array> a0 = CompileRun(fun).As<v8::Array>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004284 CHECK_EQ(0, a0->Length());
4285
4286 const char* fun2 = "f(11)";
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004287 Local<v8::Array> a1 = CompileRun(fun2).As<v8::Array>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004288 CHECK_EQ(1, a1->Length());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004289 CHECK_EQ(11, a1->Get(0)->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004290
4291 const char* fun3 = "f(12, 13)";
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004292 Local<v8::Array> a2 = CompileRun(fun3).As<v8::Array>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004293 CHECK_EQ(2, a2->Length());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004294 CHECK_EQ(12, a2->Get(0)->Int32Value());
4295 CHECK_EQ(13, a2->Get(1)->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004296
4297 const char* fun4 = "f(14, 15, 16)";
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004298 Local<v8::Array> a3 = CompileRun(fun4).As<v8::Array>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004299 CHECK_EQ(3, a3->Length());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004300 CHECK_EQ(14, a3->Get(0)->Int32Value());
4301 CHECK_EQ(15, a3->Get(1)->Int32Value());
4302 CHECK_EQ(16, a3->Get(2)->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004303
4304 const char* fun5 = "f(17, 18, 19, 20)";
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004305 Local<v8::Array> a4 = CompileRun(fun5).As<v8::Array>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004306 CHECK_EQ(4, a4->Length());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004307 CHECK_EQ(17, a4->Get(0)->Int32Value());
4308 CHECK_EQ(18, a4->Get(1)->Int32Value());
4309 CHECK_EQ(19, a4->Get(2)->Int32Value());
4310 CHECK_EQ(20, a4->Get(3)->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004311}
4312
4313
4314THREADED_TEST(FunctionCall) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004315 LocalContext context;
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +00004316 v8::Isolate* isolate = context->GetIsolate();
4317 v8::HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004318 CompileRun(
4319 "function Foo() {"
4320 " var result = [];"
4321 " for (var i = 0; i < arguments.length; i++) {"
4322 " result.push(arguments[i]);"
4323 " }"
4324 " return result;"
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +00004325 "}"
4326 "function ReturnThisSloppy() {"
4327 " return this;"
4328 "}"
4329 "function ReturnThisStrict() {"
4330 " 'use strict';"
4331 " return this;"
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004332 "}");
4333 Local<Function> Foo =
4334 Local<Function>::Cast(context->Global()->Get(v8_str("Foo")));
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +00004335 Local<Function> ReturnThisSloppy =
4336 Local<Function>::Cast(context->Global()->Get(v8_str("ReturnThisSloppy")));
4337 Local<Function> ReturnThisStrict =
4338 Local<Function>::Cast(context->Global()->Get(v8_str("ReturnThisStrict")));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004339
4340 v8::Handle<Value>* args0 = NULL;
4341 Local<v8::Array> a0 = Local<v8::Array>::Cast(Foo->Call(Foo, 0, args0));
4342 CHECK_EQ(0, a0->Length());
4343
4344 v8::Handle<Value> args1[] = { v8_num(1.1) };
4345 Local<v8::Array> a1 = Local<v8::Array>::Cast(Foo->Call(Foo, 1, args1));
4346 CHECK_EQ(1, a1->Length());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004347 CHECK_EQ(1.1, a1->Get(v8::Integer::New(isolate, 0))->NumberValue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004348
4349 v8::Handle<Value> args2[] = { v8_num(2.2),
4350 v8_num(3.3) };
4351 Local<v8::Array> a2 = Local<v8::Array>::Cast(Foo->Call(Foo, 2, args2));
4352 CHECK_EQ(2, a2->Length());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004353 CHECK_EQ(2.2, a2->Get(v8::Integer::New(isolate, 0))->NumberValue());
4354 CHECK_EQ(3.3, a2->Get(v8::Integer::New(isolate, 1))->NumberValue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004355
4356 v8::Handle<Value> args3[] = { v8_num(4.4),
4357 v8_num(5.5),
4358 v8_num(6.6) };
4359 Local<v8::Array> a3 = Local<v8::Array>::Cast(Foo->Call(Foo, 3, args3));
4360 CHECK_EQ(3, a3->Length());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004361 CHECK_EQ(4.4, a3->Get(v8::Integer::New(isolate, 0))->NumberValue());
4362 CHECK_EQ(5.5, a3->Get(v8::Integer::New(isolate, 1))->NumberValue());
4363 CHECK_EQ(6.6, a3->Get(v8::Integer::New(isolate, 2))->NumberValue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004364
4365 v8::Handle<Value> args4[] = { v8_num(7.7),
4366 v8_num(8.8),
4367 v8_num(9.9),
4368 v8_num(10.11) };
4369 Local<v8::Array> a4 = Local<v8::Array>::Cast(Foo->Call(Foo, 4, args4));
4370 CHECK_EQ(4, a4->Length());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004371 CHECK_EQ(7.7, a4->Get(v8::Integer::New(isolate, 0))->NumberValue());
4372 CHECK_EQ(8.8, a4->Get(v8::Integer::New(isolate, 1))->NumberValue());
4373 CHECK_EQ(9.9, a4->Get(v8::Integer::New(isolate, 2))->NumberValue());
4374 CHECK_EQ(10.11, a4->Get(v8::Integer::New(isolate, 3))->NumberValue());
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +00004375
4376 Local<v8::Value> r1 = ReturnThisSloppy->Call(v8::Undefined(isolate), 0, NULL);
4377 CHECK(r1->StrictEquals(context->Global()));
4378 Local<v8::Value> r2 = ReturnThisSloppy->Call(v8::Null(isolate), 0, NULL);
4379 CHECK(r2->StrictEquals(context->Global()));
4380 Local<v8::Value> r3 = ReturnThisSloppy->Call(v8_num(42), 0, NULL);
4381 CHECK(r3->IsNumberObject());
4382 CHECK_EQ(42.0, r3.As<v8::NumberObject>()->ValueOf());
4383 Local<v8::Value> r4 = ReturnThisSloppy->Call(v8_str("hello"), 0, NULL);
4384 CHECK(r4->IsStringObject());
4385 CHECK(r4.As<v8::StringObject>()->ValueOf()->StrictEquals(v8_str("hello")));
4386 Local<v8::Value> r5 = ReturnThisSloppy->Call(v8::True(isolate), 0, NULL);
4387 CHECK(r5->IsBooleanObject());
4388 CHECK(r5.As<v8::BooleanObject>()->ValueOf());
4389
4390 Local<v8::Value> r6 = ReturnThisStrict->Call(v8::Undefined(isolate), 0, NULL);
4391 CHECK(r6->IsUndefined());
4392 Local<v8::Value> r7 = ReturnThisStrict->Call(v8::Null(isolate), 0, NULL);
4393 CHECK(r7->IsNull());
4394 Local<v8::Value> r8 = ReturnThisStrict->Call(v8_num(42), 0, NULL);
4395 CHECK(r8->StrictEquals(v8_num(42)));
4396 Local<v8::Value> r9 = ReturnThisStrict->Call(v8_str("hello"), 0, NULL);
4397 CHECK(r9->StrictEquals(v8_str("hello")));
4398 Local<v8::Value> r10 = ReturnThisStrict->Call(v8::True(isolate), 0, NULL);
4399 CHECK(r10->StrictEquals(v8::True(isolate)));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004400}
4401
4402
4403static const char* js_code_causing_out_of_memory =
4404 "var a = new Array(); while(true) a.push(a);";
4405
4406
4407// These tests run for a long time and prevent us from running tests
4408// that come after them so they cannot run in parallel.
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00004409TEST(OutOfMemory) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004410 // It's not possible to read a snapshot into a heap with different dimensions.
lrn@chromium.org32d961d2010-06-30 09:09:34 +00004411 if (i::Snapshot::IsEnabled()) return;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004412 // Set heap limits.
4413 static const int K = 1024;
4414 v8::ResourceConstraints constraints;
4415 constraints.set_max_young_space_size(256 * K);
machenbach@chromium.orgc1789ee2013-07-05 07:09:57 +00004416 constraints.set_max_old_space_size(5 * K * K);
machenbach@chromium.org7ff76072013-11-21 09:47:43 +00004417 v8::SetResourceConstraints(CcTest::isolate(), &constraints);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004418
4419 // Execute a script that causes out of memory.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004420 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004421 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004422 v8::V8::IgnoreOutOfMemoryException();
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00004423 Local<Script> script = Script::Compile(String::NewFromUtf8(
4424 context->GetIsolate(), js_code_causing_out_of_memory));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004425 Local<Value> result = script->Run();
4426
4427 // Check for out of memory state.
4428 CHECK(result.IsEmpty());
4429 CHECK(context->HasOutOfMemoryException());
4430}
4431
4432
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00004433void ProvokeOutOfMemory(const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004434 ApiTestFuzzer::Fuzz();
4435
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004436 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004437 v8::HandleScope scope(context->GetIsolate());
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00004438 Local<Script> script = Script::Compile(String::NewFromUtf8(
4439 context->GetIsolate(), js_code_causing_out_of_memory));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004440 Local<Value> result = script->Run();
4441
4442 // Check for out of memory state.
4443 CHECK(result.IsEmpty());
4444 CHECK(context->HasOutOfMemoryException());
4445
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00004446 args.GetReturnValue().Set(result);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004447}
4448
4449
kasperl@chromium.orgb9123622008-09-17 14:05:56 +00004450TEST(OutOfMemoryNested) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004451 // It's not possible to read a snapshot into a heap with different dimensions.
lrn@chromium.org32d961d2010-06-30 09:09:34 +00004452 if (i::Snapshot::IsEnabled()) return;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004453 // Set heap limits.
4454 static const int K = 1024;
4455 v8::ResourceConstraints constraints;
4456 constraints.set_max_young_space_size(256 * K);
machenbach@chromium.orgc1789ee2013-07-05 07:09:57 +00004457 constraints.set_max_old_space_size(5 * K * K);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004458 v8::Isolate* isolate = CcTest::isolate();
4459 v8::SetResourceConstraints(isolate, &constraints);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004460
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004461 v8::HandleScope scope(isolate);
4462 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004463 templ->Set(v8_str("ProvokeOutOfMemory"),
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004464 v8::FunctionTemplate::New(isolate, ProvokeOutOfMemory));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004465 LocalContext context(0, templ);
4466 v8::V8::IgnoreOutOfMemoryException();
4467 Local<Value> result = CompileRun(
4468 "var thrown = false;"
4469 "try {"
4470 " ProvokeOutOfMemory();"
4471 "} catch (e) {"
4472 " thrown = true;"
4473 "}");
4474 // Check for out of memory state.
4475 CHECK(result.IsEmpty());
4476 CHECK(context->HasOutOfMemoryException());
4477}
4478
4479
yangguo@chromium.org49546742013-12-23 16:17:49 +00004480void OOMCallback(const char* location, const char* message) {
4481 exit(0);
4482}
4483
4484
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004485TEST(HugeConsStringOutOfMemory) {
4486 // It's not possible to read a snapshot into a heap with different dimensions.
lrn@chromium.org32d961d2010-06-30 09:09:34 +00004487 if (i::Snapshot::IsEnabled()) return;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004488 // Set heap limits.
4489 static const int K = 1024;
4490 v8::ResourceConstraints constraints;
4491 constraints.set_max_young_space_size(256 * K);
machenbach@chromium.orgc1789ee2013-07-05 07:09:57 +00004492 constraints.set_max_old_space_size(4 * K * K);
machenbach@chromium.org7ff76072013-11-21 09:47:43 +00004493 v8::SetResourceConstraints(CcTest::isolate(), &constraints);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004494
4495 // Execute a script that causes out of memory.
yangguo@chromium.org49546742013-12-23 16:17:49 +00004496 v8::V8::SetFatalErrorHandler(OOMCallback);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004497
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00004498 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004499 v8::HandleScope scope(context->GetIsolate());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00004500
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004501 // Build huge string. This should fail with out of memory exception.
yangguo@chromium.org49546742013-12-23 16:17:49 +00004502 CompileRun(
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004503 "var str = Array.prototype.join.call({length: 513}, \"A\").toUpperCase();"
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00004504 "for (var i = 0; i < 22; i++) { str = str + str; }");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004505
yangguo@chromium.org49546742013-12-23 16:17:49 +00004506 CHECK(false); // Should not return.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004507}
4508
4509
4510THREADED_TEST(ConstructCall) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004511 LocalContext context;
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004512 v8::Isolate* isolate = context->GetIsolate();
4513 v8::HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004514 CompileRun(
4515 "function Foo() {"
4516 " var result = [];"
4517 " for (var i = 0; i < arguments.length; i++) {"
4518 " result.push(arguments[i]);"
4519 " }"
4520 " return result;"
4521 "}");
4522 Local<Function> Foo =
4523 Local<Function>::Cast(context->Global()->Get(v8_str("Foo")));
4524
4525 v8::Handle<Value>* args0 = NULL;
4526 Local<v8::Array> a0 = Local<v8::Array>::Cast(Foo->NewInstance(0, args0));
4527 CHECK_EQ(0, a0->Length());
4528
4529 v8::Handle<Value> args1[] = { v8_num(1.1) };
4530 Local<v8::Array> a1 = Local<v8::Array>::Cast(Foo->NewInstance(1, args1));
4531 CHECK_EQ(1, a1->Length());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004532 CHECK_EQ(1.1, a1->Get(v8::Integer::New(isolate, 0))->NumberValue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004533
4534 v8::Handle<Value> args2[] = { v8_num(2.2),
4535 v8_num(3.3) };
4536 Local<v8::Array> a2 = Local<v8::Array>::Cast(Foo->NewInstance(2, args2));
4537 CHECK_EQ(2, a2->Length());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004538 CHECK_EQ(2.2, a2->Get(v8::Integer::New(isolate, 0))->NumberValue());
4539 CHECK_EQ(3.3, a2->Get(v8::Integer::New(isolate, 1))->NumberValue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004540
4541 v8::Handle<Value> args3[] = { v8_num(4.4),
4542 v8_num(5.5),
4543 v8_num(6.6) };
4544 Local<v8::Array> a3 = Local<v8::Array>::Cast(Foo->NewInstance(3, args3));
4545 CHECK_EQ(3, a3->Length());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004546 CHECK_EQ(4.4, a3->Get(v8::Integer::New(isolate, 0))->NumberValue());
4547 CHECK_EQ(5.5, a3->Get(v8::Integer::New(isolate, 1))->NumberValue());
4548 CHECK_EQ(6.6, a3->Get(v8::Integer::New(isolate, 2))->NumberValue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004549
4550 v8::Handle<Value> args4[] = { v8_num(7.7),
4551 v8_num(8.8),
4552 v8_num(9.9),
4553 v8_num(10.11) };
4554 Local<v8::Array> a4 = Local<v8::Array>::Cast(Foo->NewInstance(4, args4));
4555 CHECK_EQ(4, a4->Length());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00004556 CHECK_EQ(7.7, a4->Get(v8::Integer::New(isolate, 0))->NumberValue());
4557 CHECK_EQ(8.8, a4->Get(v8::Integer::New(isolate, 1))->NumberValue());
4558 CHECK_EQ(9.9, a4->Get(v8::Integer::New(isolate, 2))->NumberValue());
4559 CHECK_EQ(10.11, a4->Get(v8::Integer::New(isolate, 3))->NumberValue());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004560}
4561
4562
4563static void CheckUncle(v8::TryCatch* try_catch) {
4564 CHECK(try_catch->HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00004565 String::Utf8Value str_value(try_catch->Exception());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004566 CHECK_EQ(*str_value, "uncle?");
4567 try_catch->Reset();
4568}
4569
4570
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004571THREADED_TEST(ConversionNumber) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004572 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004573 v8::HandleScope scope(env->GetIsolate());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004574 // Very large number.
4575 CompileRun("var obj = Math.pow(2,32) * 1237;");
4576 Local<Value> obj = env->Global()->Get(v8_str("obj"));
4577 CHECK_EQ(5312874545152.0, obj->ToNumber()->Value());
4578 CHECK_EQ(0, obj->ToInt32()->Value());
4579 CHECK(0u == obj->ToUint32()->Value()); // NOLINT - no CHECK_EQ for unsigned.
4580 // Large number.
4581 CompileRun("var obj = -1234567890123;");
4582 obj = env->Global()->Get(v8_str("obj"));
4583 CHECK_EQ(-1234567890123.0, obj->ToNumber()->Value());
4584 CHECK_EQ(-1912276171, obj->ToInt32()->Value());
4585 CHECK(2382691125u == obj->ToUint32()->Value()); // NOLINT
4586 // Small positive integer.
4587 CompileRun("var obj = 42;");
4588 obj = env->Global()->Get(v8_str("obj"));
4589 CHECK_EQ(42.0, obj->ToNumber()->Value());
4590 CHECK_EQ(42, obj->ToInt32()->Value());
4591 CHECK(42u == obj->ToUint32()->Value()); // NOLINT
4592 // Negative integer.
4593 CompileRun("var obj = -37;");
4594 obj = env->Global()->Get(v8_str("obj"));
4595 CHECK_EQ(-37.0, obj->ToNumber()->Value());
4596 CHECK_EQ(-37, obj->ToInt32()->Value());
4597 CHECK(4294967259u == obj->ToUint32()->Value()); // NOLINT
4598 // Positive non-int32 integer.
4599 CompileRun("var obj = 0x81234567;");
4600 obj = env->Global()->Get(v8_str("obj"));
4601 CHECK_EQ(2166572391.0, obj->ToNumber()->Value());
4602 CHECK_EQ(-2128394905, obj->ToInt32()->Value());
4603 CHECK(2166572391u == obj->ToUint32()->Value()); // NOLINT
4604 // Fraction.
4605 CompileRun("var obj = 42.3;");
4606 obj = env->Global()->Get(v8_str("obj"));
4607 CHECK_EQ(42.3, obj->ToNumber()->Value());
4608 CHECK_EQ(42, obj->ToInt32()->Value());
4609 CHECK(42u == obj->ToUint32()->Value()); // NOLINT
4610 // Large negative fraction.
4611 CompileRun("var obj = -5726623061.75;");
4612 obj = env->Global()->Get(v8_str("obj"));
4613 CHECK_EQ(-5726623061.75, obj->ToNumber()->Value());
4614 CHECK_EQ(-1431655765, obj->ToInt32()->Value());
4615 CHECK(2863311531u == obj->ToUint32()->Value()); // NOLINT
4616}
4617
4618
4619THREADED_TEST(isNumberType) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004620 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004621 v8::HandleScope scope(env->GetIsolate());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004622 // Very large number.
4623 CompileRun("var obj = Math.pow(2,32) * 1237;");
4624 Local<Value> obj = env->Global()->Get(v8_str("obj"));
4625 CHECK(!obj->IsInt32());
4626 CHECK(!obj->IsUint32());
4627 // Large negative number.
4628 CompileRun("var obj = -1234567890123;");
4629 obj = env->Global()->Get(v8_str("obj"));
4630 CHECK(!obj->IsInt32());
4631 CHECK(!obj->IsUint32());
4632 // Small positive integer.
4633 CompileRun("var obj = 42;");
4634 obj = env->Global()->Get(v8_str("obj"));
4635 CHECK(obj->IsInt32());
4636 CHECK(obj->IsUint32());
4637 // Negative integer.
4638 CompileRun("var obj = -37;");
4639 obj = env->Global()->Get(v8_str("obj"));
4640 CHECK(obj->IsInt32());
4641 CHECK(!obj->IsUint32());
4642 // Positive non-int32 integer.
4643 CompileRun("var obj = 0x81234567;");
4644 obj = env->Global()->Get(v8_str("obj"));
4645 CHECK(!obj->IsInt32());
4646 CHECK(obj->IsUint32());
4647 // Fraction.
4648 CompileRun("var obj = 42.3;");
4649 obj = env->Global()->Get(v8_str("obj"));
4650 CHECK(!obj->IsInt32());
4651 CHECK(!obj->IsUint32());
4652 // Large negative fraction.
4653 CompileRun("var obj = -5726623061.75;");
4654 obj = env->Global()->Get(v8_str("obj"));
4655 CHECK(!obj->IsInt32());
4656 CHECK(!obj->IsUint32());
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00004657 // Positive zero
4658 CompileRun("var obj = 0.0;");
4659 obj = env->Global()->Get(v8_str("obj"));
4660 CHECK(obj->IsInt32());
4661 CHECK(obj->IsUint32());
4662 // Positive zero
4663 CompileRun("var obj = -0.0;");
4664 obj = env->Global()->Get(v8_str("obj"));
4665 CHECK(!obj->IsInt32());
4666 CHECK(!obj->IsUint32());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00004667}
4668
4669
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004670THREADED_TEST(ConversionException) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004671 LocalContext env;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00004672 v8::Isolate* isolate = env->GetIsolate();
4673 v8::HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004674 CompileRun(
4675 "function TestClass() { };"
4676 "TestClass.prototype.toString = function () { throw 'uncle?'; };"
4677 "var obj = new TestClass();");
4678 Local<Value> obj = env->Global()->Get(v8_str("obj"));
4679
4680 v8::TryCatch try_catch;
4681
4682 Local<Value> to_string_result = obj->ToString();
4683 CHECK(to_string_result.IsEmpty());
4684 CheckUncle(&try_catch);
4685
4686 Local<Value> to_number_result = obj->ToNumber();
4687 CHECK(to_number_result.IsEmpty());
4688 CheckUncle(&try_catch);
4689
4690 Local<Value> to_integer_result = obj->ToInteger();
4691 CHECK(to_integer_result.IsEmpty());
4692 CheckUncle(&try_catch);
4693
4694 Local<Value> to_uint32_result = obj->ToUint32();
4695 CHECK(to_uint32_result.IsEmpty());
4696 CheckUncle(&try_catch);
4697
4698 Local<Value> to_int32_result = obj->ToInt32();
4699 CHECK(to_int32_result.IsEmpty());
4700 CheckUncle(&try_catch);
4701
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00004702 Local<Value> to_object_result = v8::Undefined(isolate)->ToObject();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004703 CHECK(to_object_result.IsEmpty());
4704 CHECK(try_catch.HasCaught());
4705 try_catch.Reset();
4706
4707 int32_t int32_value = obj->Int32Value();
4708 CHECK_EQ(0, int32_value);
4709 CheckUncle(&try_catch);
4710
4711 uint32_t uint32_value = obj->Uint32Value();
4712 CHECK_EQ(0, uint32_value);
4713 CheckUncle(&try_catch);
4714
4715 double number_value = obj->NumberValue();
ulan@chromium.org77ca49a2013-04-22 09:43:56 +00004716 CHECK_NE(0, std::isnan(number_value));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004717 CheckUncle(&try_catch);
4718
4719 int64_t integer_value = obj->IntegerValue();
4720 CHECK_EQ(0.0, static_cast<double>(integer_value));
4721 CheckUncle(&try_catch);
4722}
4723
4724
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00004725void ThrowFromC(const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004726 ApiTestFuzzer::Fuzz();
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00004727 args.GetIsolate()->ThrowException(v8_str("konto"));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004728}
4729
4730
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00004731void CCatcher(const v8::FunctionCallbackInfo<v8::Value>& args) {
4732 if (args.Length() < 1) {
4733 args.GetReturnValue().Set(false);
4734 return;
4735 }
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004736 v8::HandleScope scope(args.GetIsolate());
ager@chromium.org8bb60582008-12-11 12:02:20 +00004737 v8::TryCatch try_catch;
ager@chromium.org71daaf62009-04-01 07:22:49 +00004738 Local<Value> result = v8::Script::Compile(args[0]->ToString())->Run();
4739 CHECK(!try_catch.HasCaught() || result.IsEmpty());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00004740 args.GetReturnValue().Set(try_catch.HasCaught());
ager@chromium.org8bb60582008-12-11 12:02:20 +00004741}
4742
4743
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004744THREADED_TEST(APICatch) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004745 v8::Isolate* isolate = CcTest::isolate();
4746 v8::HandleScope scope(isolate);
4747 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004748 templ->Set(v8_str("ThrowFromC"),
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004749 v8::FunctionTemplate::New(isolate, ThrowFromC));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004750 LocalContext context(0, templ);
4751 CompileRun(
4752 "var thrown = false;"
4753 "try {"
4754 " ThrowFromC();"
4755 "} catch (e) {"
4756 " thrown = true;"
4757 "}");
4758 Local<Value> thrown = context->Global()->Get(v8_str("thrown"));
4759 CHECK(thrown->BooleanValue());
4760}
4761
4762
ager@chromium.org8bb60582008-12-11 12:02:20 +00004763THREADED_TEST(APIThrowTryCatch) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004764 v8::Isolate* isolate = CcTest::isolate();
4765 v8::HandleScope scope(isolate);
4766 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org8bb60582008-12-11 12:02:20 +00004767 templ->Set(v8_str("ThrowFromC"),
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004768 v8::FunctionTemplate::New(isolate, ThrowFromC));
ager@chromium.org8bb60582008-12-11 12:02:20 +00004769 LocalContext context(0, templ);
4770 v8::TryCatch try_catch;
4771 CompileRun("ThrowFromC();");
4772 CHECK(try_catch.HasCaught());
4773}
4774
4775
4776// Test that a try-finally block doesn't shadow a try-catch block
4777// when setting up an external handler.
ager@chromium.org71daaf62009-04-01 07:22:49 +00004778//
4779// BUG(271): Some of the exception propagation does not work on the
4780// ARM simulator because the simulator separates the C++ stack and the
4781// JS stack. This test therefore fails on the simulator. The test is
4782// not threaded to allow the threading tests to run on the simulator.
4783TEST(TryCatchInTryFinally) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004784 v8::Isolate* isolate = CcTest::isolate();
4785 v8::HandleScope scope(isolate);
4786 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org8bb60582008-12-11 12:02:20 +00004787 templ->Set(v8_str("CCatcher"),
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004788 v8::FunctionTemplate::New(isolate, CCatcher));
ager@chromium.org8bb60582008-12-11 12:02:20 +00004789 LocalContext context(0, templ);
4790 Local<Value> result = CompileRun("try {"
4791 " try {"
4792 " CCatcher('throw 7;');"
4793 " } finally {"
4794 " }"
4795 "} catch (e) {"
4796 "}");
4797 CHECK(result->IsTrue());
4798}
4799
4800
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00004801static void check_reference_error_message(
4802 v8::Handle<v8::Message> message,
4803 v8::Handle<v8::Value> data) {
4804 const char* reference_error = "Uncaught ReferenceError: asdf is not defined";
4805 CHECK(message->Get()->Equals(v8_str(reference_error)));
4806}
4807
4808
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00004809static void Fail(const v8::FunctionCallbackInfo<v8::Value>& args) {
kmillikin@chromium.org31b12772011-02-02 16:08:26 +00004810 ApiTestFuzzer::Fuzz();
4811 CHECK(false);
kmillikin@chromium.org31b12772011-02-02 16:08:26 +00004812}
4813
4814
4815// Test that overwritten methods are not invoked on uncaught exception
4816// formatting. However, they are invoked when performing normal error
4817// string conversions.
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00004818TEST(APIThrowMessageOverwrittenToString) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00004819 v8::Isolate* isolate = CcTest::isolate();
4820 v8::HandleScope scope(isolate);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00004821 v8::V8::AddMessageListener(check_reference_error_message);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004822 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00004823 templ->Set(v8_str("fail"), v8::FunctionTemplate::New(isolate, Fail));
kmillikin@chromium.org31b12772011-02-02 16:08:26 +00004824 LocalContext context(NULL, templ);
4825 CompileRun("asdf;");
4826 CompileRun("var limit = {};"
4827 "limit.valueOf = fail;"
4828 "Error.stackTraceLimit = limit;");
4829 CompileRun("asdf");
4830 CompileRun("Array.prototype.pop = fail;");
4831 CompileRun("Object.prototype.hasOwnProperty = fail;");
4832 CompileRun("Object.prototype.toString = function f() { return 'Yikes'; }");
whesse@chromium.org7a392b32011-01-31 11:30:36 +00004833 CompileRun("Number.prototype.toString = function f() { return 'Yikes'; }");
4834 CompileRun("String.prototype.toString = function f() { return 'Yikes'; }");
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00004835 CompileRun("ReferenceError.prototype.toString ="
4836 " function() { return 'Whoops' }");
4837 CompileRun("asdf;");
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00004838 CompileRun("ReferenceError.prototype.constructor.name = void 0;");
4839 CompileRun("asdf;");
4840 CompileRun("ReferenceError.prototype.constructor = void 0;");
4841 CompileRun("asdf;");
ager@chromium.org0ee099b2011-01-25 14:06:47 +00004842 CompileRun("ReferenceError.prototype.__proto__ = new Object();");
4843 CompileRun("asdf;");
4844 CompileRun("ReferenceError.prototype = new Object();");
4845 CompileRun("asdf;");
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00004846 v8::Handle<Value> string = CompileRun("try { asdf; } catch(e) { e + ''; }");
4847 CHECK(string->Equals(v8_str("Whoops")));
ager@chromium.org378b34e2011-01-28 08:04:38 +00004848 CompileRun("ReferenceError.prototype.constructor = new Object();"
4849 "ReferenceError.prototype.constructor.name = 1;"
4850 "Number.prototype.toString = function() { return 'Whoops'; };"
4851 "ReferenceError.prototype.toString = Object.prototype.toString;");
4852 CompileRun("asdf;");
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00004853 v8::V8::RemoveMessageListeners(check_reference_error_message);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +00004854}
4855
4856
danno@chromium.org59400602013-08-13 17:09:37 +00004857static void check_custom_error_tostring(
yangguo@chromium.org304cc332012-07-24 07:59:48 +00004858 v8::Handle<v8::Message> message,
4859 v8::Handle<v8::Value> data) {
4860 const char* uncaught_error = "Uncaught MyError toString";
4861 CHECK(message->Get()->Equals(v8_str(uncaught_error)));
4862}
4863
4864
4865TEST(CustomErrorToString) {
yangguo@chromium.org304cc332012-07-24 07:59:48 +00004866 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004867 v8::HandleScope scope(context->GetIsolate());
danno@chromium.org59400602013-08-13 17:09:37 +00004868 v8::V8::AddMessageListener(check_custom_error_tostring);
yangguo@chromium.org304cc332012-07-24 07:59:48 +00004869 CompileRun(
4870 "function MyError(name, message) { "
4871 " this.name = name; "
4872 " this.message = message; "
4873 "} "
4874 "MyError.prototype = Object.create(Error.prototype); "
4875 "MyError.prototype.toString = function() { "
4876 " return 'MyError toString'; "
4877 "}; "
4878 "throw new MyError('my name', 'my message'); ");
danno@chromium.org59400602013-08-13 17:09:37 +00004879 v8::V8::RemoveMessageListeners(check_custom_error_tostring);
4880}
4881
4882
4883static void check_custom_error_message(
4884 v8::Handle<v8::Message> message,
4885 v8::Handle<v8::Value> data) {
4886 const char* uncaught_error = "Uncaught MyError: my message";
4887 printf("%s\n", *v8::String::Utf8Value(message->Get()));
4888 CHECK(message->Get()->Equals(v8_str(uncaught_error)));
4889}
4890
4891
4892TEST(CustomErrorMessage) {
4893 LocalContext context;
4894 v8::HandleScope scope(context->GetIsolate());
4895 v8::V8::AddMessageListener(check_custom_error_message);
4896
4897 // Handlebars.
4898 CompileRun(
4899 "function MyError(msg) { "
4900 " this.name = 'MyError'; "
4901 " this.message = msg; "
4902 "} "
4903 "MyError.prototype = new Error(); "
4904 "throw new MyError('my message'); ");
4905
4906 // Closure.
4907 CompileRun(
4908 "function MyError(msg) { "
4909 " this.name = 'MyError'; "
4910 " this.message = msg; "
4911 "} "
4912 "inherits = function(childCtor, parentCtor) { "
4913 " function tempCtor() {}; "
4914 " tempCtor.prototype = parentCtor.prototype; "
4915 " childCtor.superClass_ = parentCtor.prototype; "
4916 " childCtor.prototype = new tempCtor(); "
4917 " childCtor.prototype.constructor = childCtor; "
4918 "}; "
4919 "inherits(MyError, Error); "
4920 "throw new MyError('my message'); ");
4921
4922 // Object.create.
4923 CompileRun(
4924 "function MyError(msg) { "
4925 " this.name = 'MyError'; "
4926 " this.message = msg; "
4927 "} "
4928 "MyError.prototype = Object.create(Error.prototype); "
4929 "throw new MyError('my message'); ");
4930
yangguo@chromium.org304cc332012-07-24 07:59:48 +00004931 v8::V8::RemoveMessageListeners(check_custom_error_message);
4932}
4933
4934
ager@chromium.org8bb60582008-12-11 12:02:20 +00004935static void receive_message(v8::Handle<v8::Message> message,
4936 v8::Handle<v8::Value> data) {
ager@chromium.org71daaf62009-04-01 07:22:49 +00004937 message->Get();
ager@chromium.org8bb60582008-12-11 12:02:20 +00004938 message_received = true;
4939}
4940
4941
4942TEST(APIThrowMessage) {
4943 message_received = false;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004944 v8::Isolate* isolate = CcTest::isolate();
4945 v8::HandleScope scope(isolate);
ager@chromium.org8bb60582008-12-11 12:02:20 +00004946 v8::V8::AddMessageListener(receive_message);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004947 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org8bb60582008-12-11 12:02:20 +00004948 templ->Set(v8_str("ThrowFromC"),
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004949 v8::FunctionTemplate::New(isolate, ThrowFromC));
ager@chromium.org8bb60582008-12-11 12:02:20 +00004950 LocalContext context(0, templ);
4951 CompileRun("ThrowFromC();");
4952 CHECK(message_received);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00004953 v8::V8::RemoveMessageListeners(receive_message);
ager@chromium.org8bb60582008-12-11 12:02:20 +00004954}
4955
4956
4957TEST(APIThrowMessageAndVerboseTryCatch) {
4958 message_received = false;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004959 v8::Isolate* isolate = CcTest::isolate();
4960 v8::HandleScope scope(isolate);
ager@chromium.org8bb60582008-12-11 12:02:20 +00004961 v8::V8::AddMessageListener(receive_message);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004962 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org8bb60582008-12-11 12:02:20 +00004963 templ->Set(v8_str("ThrowFromC"),
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004964 v8::FunctionTemplate::New(isolate, ThrowFromC));
ager@chromium.org8bb60582008-12-11 12:02:20 +00004965 LocalContext context(0, templ);
4966 v8::TryCatch try_catch;
4967 try_catch.SetVerbose(true);
ager@chromium.org71daaf62009-04-01 07:22:49 +00004968 Local<Value> result = CompileRun("ThrowFromC();");
ager@chromium.org8bb60582008-12-11 12:02:20 +00004969 CHECK(try_catch.HasCaught());
ager@chromium.org71daaf62009-04-01 07:22:49 +00004970 CHECK(result.IsEmpty());
ager@chromium.org8bb60582008-12-11 12:02:20 +00004971 CHECK(message_received);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00004972 v8::V8::RemoveMessageListeners(receive_message);
ager@chromium.org8bb60582008-12-11 12:02:20 +00004973}
4974
4975
karlklose@chromium.org44bc7082011-04-11 12:33:05 +00004976TEST(APIStackOverflowAndVerboseTryCatch) {
4977 message_received = false;
karlklose@chromium.org44bc7082011-04-11 12:33:05 +00004978 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00004979 v8::HandleScope scope(context->GetIsolate());
4980 v8::V8::AddMessageListener(receive_message);
karlklose@chromium.org44bc7082011-04-11 12:33:05 +00004981 v8::TryCatch try_catch;
4982 try_catch.SetVerbose(true);
4983 Local<Value> result = CompileRun("function foo() { foo(); } foo();");
4984 CHECK(try_catch.HasCaught());
4985 CHECK(result.IsEmpty());
4986 CHECK(message_received);
4987 v8::V8::RemoveMessageListeners(receive_message);
4988}
4989
4990
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004991THREADED_TEST(ExternalScriptException) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004992 v8::Isolate* isolate = CcTest::isolate();
4993 v8::HandleScope scope(isolate);
4994 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004995 templ->Set(v8_str("ThrowFromC"),
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00004996 v8::FunctionTemplate::New(isolate, ThrowFromC));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004997 LocalContext context(0, templ);
4998
4999 v8::TryCatch try_catch;
5000 Local<Script> script
5001 = Script::Compile(v8_str("ThrowFromC(); throw 'panama';"));
5002 Local<Value> result = script->Run();
5003 CHECK(result.IsEmpty());
5004 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00005005 String::Utf8Value exception_value(try_catch.Exception());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005006 CHECK_EQ("konto", *exception_value);
5007}
5008
5009
5010
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005011void CThrowCountDown(const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005012 ApiTestFuzzer::Fuzz();
5013 CHECK_EQ(4, args.Length());
5014 int count = args[0]->Int32Value();
5015 int cInterval = args[2]->Int32Value();
5016 if (count == 0) {
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00005017 args.GetIsolate()->ThrowException(v8_str("FromC"));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005018 return;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005019 } else {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00005020 Local<v8::Object> global =
5021 args.GetIsolate()->GetCurrentContext()->Global();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005022 Local<Value> fun = global->Get(v8_str("JSThrowCountDown"));
5023 v8::Handle<Value> argv[] = { v8_num(count - 1),
5024 args[1],
5025 args[2],
5026 args[3] };
5027 if (count % cInterval == 0) {
5028 v8::TryCatch try_catch;
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00005029 Local<Value> result = fun.As<Function>()->Call(global, 4, argv);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005030 int expected = args[3]->Int32Value();
5031 if (try_catch.HasCaught()) {
5032 CHECK_EQ(expected, count);
ager@chromium.org71daaf62009-04-01 07:22:49 +00005033 CHECK(result.IsEmpty());
machenbach@chromium.org528ce022013-09-23 14:09:36 +00005034 CHECK(!CcTest::i_isolate()->has_scheduled_exception());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005035 } else {
5036 CHECK_NE(expected, count);
5037 }
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005038 args.GetReturnValue().Set(result);
5039 return;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005040 } else {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005041 args.GetReturnValue().Set(fun.As<Function>()->Call(global, 4, argv));
5042 return;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005043 }
5044 }
5045}
5046
5047
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005048void JSCheck(const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005049 ApiTestFuzzer::Fuzz();
5050 CHECK_EQ(3, args.Length());
5051 bool equality = args[0]->BooleanValue();
5052 int count = args[1]->Int32Value();
5053 int expected = args[2]->Int32Value();
5054 if (equality) {
5055 CHECK_EQ(count, expected);
5056 } else {
5057 CHECK_NE(count, expected);
5058 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005059}
5060
5061
ager@chromium.org8bb60582008-12-11 12:02:20 +00005062THREADED_TEST(EvalInTryFinally) {
ager@chromium.org8bb60582008-12-11 12:02:20 +00005063 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005064 v8::HandleScope scope(context->GetIsolate());
ager@chromium.org8bb60582008-12-11 12:02:20 +00005065 v8::TryCatch try_catch;
5066 CompileRun("(function() {"
5067 " try {"
5068 " eval('asldkf (*&^&*^');"
5069 " } finally {"
5070 " return;"
5071 " }"
5072 "})()");
5073 CHECK(!try_catch.HasCaught());
5074}
5075
5076
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005077// This test works by making a stack of alternating JavaScript and C
5078// activations. These activations set up exception handlers with regular
5079// intervals, one interval for C activations and another for JavaScript
5080// activations. When enough activations have been created an exception is
5081// thrown and we check that the right activation catches the exception and that
5082// no other activations do. The right activation is always the topmost one with
5083// a handler, regardless of whether it is in JavaScript or C.
5084//
5085// The notation used to describe a test case looks like this:
5086//
5087// *JS[4] *C[3] @JS[2] C[1] JS[0]
5088//
5089// Each entry is an activation, either JS or C. The index is the count at that
5090// level. Stars identify activations with exception handlers, the @ identifies
5091// the exception handler that should catch the exception.
ager@chromium.org71daaf62009-04-01 07:22:49 +00005092//
5093// BUG(271): Some of the exception propagation does not work on the
5094// ARM simulator because the simulator separates the C++ stack and the
5095// JS stack. This test therefore fails on the simulator. The test is
5096// not threaded to allow the threading tests to run on the simulator.
5097TEST(ExceptionOrder) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00005098 v8::Isolate* isolate = CcTest::isolate();
5099 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005100 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00005101 templ->Set(v8_str("check"), v8::FunctionTemplate::New(isolate, JSCheck));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005102 templ->Set(v8_str("CThrowCountDown"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00005103 v8::FunctionTemplate::New(isolate, CThrowCountDown));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005104 LocalContext context(0, templ);
5105 CompileRun(
5106 "function JSThrowCountDown(count, jsInterval, cInterval, expected) {"
5107 " if (count == 0) throw 'FromJS';"
5108 " if (count % jsInterval == 0) {"
5109 " try {"
5110 " var value = CThrowCountDown(count - 1,"
5111 " jsInterval,"
5112 " cInterval,"
5113 " expected);"
5114 " check(false, count, expected);"
5115 " return value;"
5116 " } catch (e) {"
5117 " check(true, count, expected);"
5118 " }"
5119 " } else {"
5120 " return CThrowCountDown(count - 1, jsInterval, cInterval, expected);"
5121 " }"
5122 "}");
5123 Local<Function> fun =
5124 Local<Function>::Cast(context->Global()->Get(v8_str("JSThrowCountDown")));
5125
5126 const int argc = 4;
5127 // count jsInterval cInterval expected
5128
5129 // *JS[4] *C[3] @JS[2] C[1] JS[0]
5130 v8::Handle<Value> a0[argc] = { v8_num(4), v8_num(2), v8_num(3), v8_num(2) };
5131 fun->Call(fun, argc, a0);
5132
5133 // JS[5] *C[4] JS[3] @C[2] JS[1] C[0]
5134 v8::Handle<Value> a1[argc] = { v8_num(5), v8_num(6), v8_num(1), v8_num(2) };
5135 fun->Call(fun, argc, a1);
5136
5137 // JS[6] @C[5] JS[4] C[3] JS[2] C[1] JS[0]
5138 v8::Handle<Value> a2[argc] = { v8_num(6), v8_num(7), v8_num(5), v8_num(5) };
5139 fun->Call(fun, argc, a2);
5140
5141 // @JS[6] C[5] JS[4] C[3] JS[2] C[1] JS[0]
5142 v8::Handle<Value> a3[argc] = { v8_num(6), v8_num(6), v8_num(7), v8_num(6) };
5143 fun->Call(fun, argc, a3);
5144
5145 // JS[6] *C[5] @JS[4] C[3] JS[2] C[1] JS[0]
5146 v8::Handle<Value> a4[argc] = { v8_num(6), v8_num(4), v8_num(5), v8_num(4) };
5147 fun->Call(fun, argc, a4);
5148
5149 // JS[6] C[5] *JS[4] @C[3] JS[2] C[1] JS[0]
5150 v8::Handle<Value> a5[argc] = { v8_num(6), v8_num(4), v8_num(3), v8_num(3) };
5151 fun->Call(fun, argc, a5);
5152}
5153
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00005154
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005155void ThrowValue(const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005156 ApiTestFuzzer::Fuzz();
5157 CHECK_EQ(1, args.Length());
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00005158 args.GetIsolate()->ThrowException(args[0]);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005159}
5160
5161
5162THREADED_TEST(ThrowValues) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00005163 v8::Isolate* isolate = CcTest::isolate();
5164 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005165 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00005166 templ->Set(v8_str("Throw"), v8::FunctionTemplate::New(isolate, ThrowValue));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005167 LocalContext context(0, templ);
5168 v8::Handle<v8::Array> result = v8::Handle<v8::Array>::Cast(CompileRun(
5169 "function Run(obj) {"
5170 " try {"
5171 " Throw(obj);"
5172 " } catch (e) {"
5173 " return e;"
5174 " }"
5175 " return 'no exception';"
5176 "}"
5177 "[Run('str'), Run(1), Run(0), Run(null), Run(void 0)];"));
5178 CHECK_EQ(5, result->Length());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00005179 CHECK(result->Get(v8::Integer::New(isolate, 0))->IsString());
5180 CHECK(result->Get(v8::Integer::New(isolate, 1))->IsNumber());
5181 CHECK_EQ(1, result->Get(v8::Integer::New(isolate, 1))->Int32Value());
5182 CHECK(result->Get(v8::Integer::New(isolate, 2))->IsNumber());
5183 CHECK_EQ(0, result->Get(v8::Integer::New(isolate, 2))->Int32Value());
5184 CHECK(result->Get(v8::Integer::New(isolate, 3))->IsNull());
5185 CHECK(result->Get(v8::Integer::New(isolate, 4))->IsUndefined());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005186}
5187
5188
5189THREADED_TEST(CatchZero) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005190 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005191 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005192 v8::TryCatch try_catch;
5193 CHECK(!try_catch.HasCaught());
5194 Script::Compile(v8_str("throw 10"))->Run();
5195 CHECK(try_catch.HasCaught());
5196 CHECK_EQ(10, try_catch.Exception()->Int32Value());
5197 try_catch.Reset();
5198 CHECK(!try_catch.HasCaught());
5199 Script::Compile(v8_str("throw 0"))->Run();
5200 CHECK(try_catch.HasCaught());
5201 CHECK_EQ(0, try_catch.Exception()->Int32Value());
5202}
5203
5204
5205THREADED_TEST(CatchExceptionFromWith) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005206 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005207 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005208 v8::TryCatch try_catch;
5209 CHECK(!try_catch.HasCaught());
5210 Script::Compile(v8_str("var o = {}; with (o) { throw 42; }"))->Run();
5211 CHECK(try_catch.HasCaught());
5212}
5213
5214
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00005215THREADED_TEST(TryCatchAndFinallyHidingException) {
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00005216 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005217 v8::HandleScope scope(context->GetIsolate());
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00005218 v8::TryCatch try_catch;
5219 CHECK(!try_catch.HasCaught());
5220 CompileRun("function f(k) { try { this[k]; } finally { return 0; } };");
5221 CompileRun("f({toString: function() { throw 42; }});");
5222 CHECK(!try_catch.HasCaught());
5223}
5224
5225
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005226void WithTryCatch(const v8::FunctionCallbackInfo<v8::Value>& args) {
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00005227 v8::TryCatch try_catch;
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00005228}
5229
5230
5231THREADED_TEST(TryCatchAndFinally) {
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00005232 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00005233 v8::Isolate* isolate = context->GetIsolate();
5234 v8::HandleScope scope(isolate);
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00005235 context->Global()->Set(
5236 v8_str("native_with_try_catch"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00005237 v8::FunctionTemplate::New(isolate, WithTryCatch)->GetFunction());
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +00005238 v8::TryCatch try_catch;
5239 CHECK(!try_catch.HasCaught());
5240 CompileRun(
5241 "try {\n"
5242 " throw new Error('a');\n"
5243 "} finally {\n"
5244 " native_with_try_catch();\n"
5245 "}\n");
5246 CHECK(try_catch.HasCaught());
5247}
5248
5249
mmassi@chromium.org49a44672012-12-04 13:52:03 +00005250static void TryCatchNestedHelper(int depth) {
5251 if (depth > 0) {
5252 v8::TryCatch try_catch;
5253 try_catch.SetVerbose(true);
5254 TryCatchNestedHelper(depth - 1);
5255 CHECK(try_catch.HasCaught());
5256 try_catch.ReThrow();
5257 } else {
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00005258 CcTest::isolate()->ThrowException(v8_str("back"));
mmassi@chromium.org49a44672012-12-04 13:52:03 +00005259 }
5260}
5261
5262
5263TEST(TryCatchNested) {
5264 v8::V8::Initialize();
mmassi@chromium.org49a44672012-12-04 13:52:03 +00005265 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005266 v8::HandleScope scope(context->GetIsolate());
mmassi@chromium.org49a44672012-12-04 13:52:03 +00005267 v8::TryCatch try_catch;
5268 TryCatchNestedHelper(5);
5269 CHECK(try_catch.HasCaught());
5270 CHECK_EQ(0, strcmp(*v8::String::Utf8Value(try_catch.Exception()), "back"));
5271}
5272
5273
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +00005274void TryCatchMixedNestingCheck(v8::TryCatch* try_catch) {
5275 CHECK(try_catch->HasCaught());
5276 Handle<Message> message = try_catch->Message();
5277 Handle<Value> resource = message->GetScriptResourceName();
5278 CHECK_EQ(0, strcmp(*v8::String::Utf8Value(resource), "inner"));
5279 CHECK_EQ(0, strcmp(*v8::String::Utf8Value(message->Get()),
5280 "Uncaught Error: a"));
5281 CHECK_EQ(1, message->GetLineNumber());
5282 CHECK_EQ(6, message->GetStartColumn());
5283}
5284
5285
5286void TryCatchMixedNestingHelper(
5287 const v8::FunctionCallbackInfo<v8::Value>& args) {
5288 ApiTestFuzzer::Fuzz();
5289 v8::TryCatch try_catch;
5290 CompileRunWithOrigin("throw new Error('a');\n", "inner", 0, 0);
5291 CHECK(try_catch.HasCaught());
5292 TryCatchMixedNestingCheck(&try_catch);
5293 try_catch.ReThrow();
5294}
5295
5296
5297// This test ensures that an outer TryCatch in the following situation:
5298// C++/TryCatch -> JS -> C++/TryCatch -> JS w/ SyntaxError
5299// does not clobber the Message object generated for the inner TryCatch.
5300// This exercises the ability of TryCatch.ReThrow() to restore the
5301// inner pending Message before throwing the exception again.
5302TEST(TryCatchMixedNesting) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00005303 v8::Isolate* isolate = CcTest::isolate();
5304 v8::HandleScope scope(isolate);
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +00005305 v8::V8::Initialize();
5306 v8::TryCatch try_catch;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005307 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +00005308 templ->Set(v8_str("TryCatchMixedNestingHelper"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00005309 v8::FunctionTemplate::New(isolate, TryCatchMixedNestingHelper));
jkummerow@chromium.org93a47f42013-07-02 14:43:41 +00005310 LocalContext context(0, templ);
5311 CompileRunWithOrigin("TryCatchMixedNestingHelper();\n", "outer", 1, 1);
5312 TryCatchMixedNestingCheck(&try_catch);
5313}
5314
5315
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005316THREADED_TEST(Equality) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005317 LocalContext context;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00005318 v8::Isolate* isolate = context->GetIsolate();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005319 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005320 // Check that equality works at all before relying on CHECK_EQ
5321 CHECK(v8_str("a")->Equals(v8_str("a")));
5322 CHECK(!v8_str("a")->Equals(v8_str("b")));
5323
5324 CHECK_EQ(v8_str("a"), v8_str("a"));
5325 CHECK_NE(v8_str("a"), v8_str("b"));
5326 CHECK_EQ(v8_num(1), v8_num(1));
5327 CHECK_EQ(v8_num(1.00), v8_num(1));
5328 CHECK_NE(v8_num(1), v8_num(2));
5329
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +00005330 // Assume String is not internalized.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005331 CHECK(v8_str("a")->StrictEquals(v8_str("a")));
5332 CHECK(!v8_str("a")->StrictEquals(v8_str("b")));
5333 CHECK(!v8_str("5")->StrictEquals(v8_num(5)));
5334 CHECK(v8_num(1)->StrictEquals(v8_num(1)));
5335 CHECK(!v8_num(1)->StrictEquals(v8_num(2)));
machenbach@chromium.org3d079fe2013-09-25 08:19:55 +00005336 CHECK(v8_num(0.0)->StrictEquals(v8_num(-0.0)));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005337 Local<Value> not_a_number = v8_num(i::OS::nan_value());
5338 CHECK(!not_a_number->StrictEquals(not_a_number));
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00005339 CHECK(v8::False(isolate)->StrictEquals(v8::False(isolate)));
5340 CHECK(!v8::False(isolate)->StrictEquals(v8::Undefined(isolate)));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005341
ulan@chromium.org0f13e742014-01-03 15:51:11 +00005342 v8::Handle<v8::Object> obj = v8::Object::New(isolate);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00005343 v8::Persistent<v8::Object> alias(isolate, obj);
rossberg@chromium.org79e79022013-06-03 15:43:46 +00005344 CHECK(v8::Local<v8::Object>::New(isolate, alias)->StrictEquals(obj));
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00005345 alias.Reset();
machenbach@chromium.org3d079fe2013-09-25 08:19:55 +00005346
5347 CHECK(v8_str("a")->SameValue(v8_str("a")));
5348 CHECK(!v8_str("a")->SameValue(v8_str("b")));
5349 CHECK(!v8_str("5")->SameValue(v8_num(5)));
5350 CHECK(v8_num(1)->SameValue(v8_num(1)));
5351 CHECK(!v8_num(1)->SameValue(v8_num(2)));
5352 CHECK(!v8_num(0.0)->SameValue(v8_num(-0.0)));
5353 CHECK(not_a_number->SameValue(not_a_number));
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00005354 CHECK(v8::False(isolate)->SameValue(v8::False(isolate)));
5355 CHECK(!v8::False(isolate)->SameValue(v8::Undefined(isolate)));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005356}
5357
5358
5359THREADED_TEST(MultiRun) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005360 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005361 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005362 Local<Script> script = Script::Compile(v8_str("x"));
5363 for (int i = 0; i < 10; i++)
5364 script->Run();
5365}
5366
5367
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005368static void GetXValue(Local<String> name,
5369 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005370 ApiTestFuzzer::Fuzz();
5371 CHECK_EQ(info.Data(), v8_str("donut"));
5372 CHECK_EQ(name, v8_str("x"));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005373 info.GetReturnValue().Set(name);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005374}
5375
5376
5377THREADED_TEST(SimplePropertyRead) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005378 LocalContext context;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005379 v8::Isolate* isolate = context->GetIsolate();
5380 v8::HandleScope scope(isolate);
5381 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005382 templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005383 context->Global()->Set(v8_str("obj"), templ->NewInstance());
5384 Local<Script> script = Script::Compile(v8_str("obj.x"));
5385 for (int i = 0; i < 10; i++) {
5386 Local<Value> result = script->Run();
5387 CHECK_EQ(result, v8_str("x"));
5388 }
5389}
5390
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00005391
ager@chromium.org5c838252010-02-19 08:53:10 +00005392THREADED_TEST(DefinePropertyOnAPIAccessor) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00005393 LocalContext context;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005394 v8::Isolate* isolate = context->GetIsolate();
5395 v8::HandleScope scope(isolate);
5396 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +00005397 templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
ager@chromium.org5c838252010-02-19 08:53:10 +00005398 context->Global()->Set(v8_str("obj"), templ->NewInstance());
5399
5400 // Uses getOwnPropertyDescriptor to check the configurable status
5401 Local<Script> script_desc
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00005402 = Script::Compile(v8_str("var prop = Object.getOwnPropertyDescriptor( "
ager@chromium.org5c838252010-02-19 08:53:10 +00005403 "obj, 'x');"
5404 "prop.configurable;"));
5405 Local<Value> result = script_desc->Run();
5406 CHECK_EQ(result->BooleanValue(), true);
5407
5408 // Redefine get - but still configurable
5409 Local<Script> script_define
5410 = Script::Compile(v8_str("var desc = { get: function(){return 42; },"
5411 " configurable: true };"
5412 "Object.defineProperty(obj, 'x', desc);"
5413 "obj.x"));
5414 result = script_define->Run();
5415 CHECK_EQ(result, v8_num(42));
5416
5417 // Check that the accessor is still configurable
5418 result = script_desc->Run();
5419 CHECK_EQ(result->BooleanValue(), true);
5420
5421 // Redefine to a non-configurable
5422 script_define
5423 = Script::Compile(v8_str("var desc = { get: function(){return 43; },"
5424 " configurable: false };"
5425 "Object.defineProperty(obj, 'x', desc);"
5426 "obj.x"));
5427 result = script_define->Run();
5428 CHECK_EQ(result, v8_num(43));
5429 result = script_desc->Run();
5430 CHECK_EQ(result->BooleanValue(), false);
5431
5432 // Make sure that it is not possible to redefine again
5433 v8::TryCatch try_catch;
5434 result = script_define->Run();
5435 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00005436 String::Utf8Value exception_value(try_catch.Exception());
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00005437 CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x");
ager@chromium.org5c838252010-02-19 08:53:10 +00005438}
5439
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00005440
ager@chromium.org5c838252010-02-19 08:53:10 +00005441THREADED_TEST(DefinePropertyOnDefineGetterSetter) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005442 v8::Isolate* isolate = CcTest::isolate();
5443 v8::HandleScope scope(isolate);
5444 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +00005445 templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
5446 LocalContext context;
5447 context->Global()->Set(v8_str("obj"), templ->NewInstance());
5448
5449 Local<Script> script_desc = Script::Compile(v8_str("var prop ="
5450 "Object.getOwnPropertyDescriptor( "
5451 "obj, 'x');"
5452 "prop.configurable;"));
5453 Local<Value> result = script_desc->Run();
5454 CHECK_EQ(result->BooleanValue(), true);
5455
5456 Local<Script> script_define =
5457 Script::Compile(v8_str("var desc = {get: function(){return 42; },"
5458 " configurable: true };"
5459 "Object.defineProperty(obj, 'x', desc);"
5460 "obj.x"));
5461 result = script_define->Run();
5462 CHECK_EQ(result, v8_num(42));
5463
5464
5465 result = script_desc->Run();
5466 CHECK_EQ(result->BooleanValue(), true);
5467
5468
5469 script_define =
5470 Script::Compile(v8_str("var desc = {get: function(){return 43; },"
5471 " configurable: false };"
5472 "Object.defineProperty(obj, 'x', desc);"
5473 "obj.x"));
5474 result = script_define->Run();
5475 CHECK_EQ(result, v8_num(43));
5476 result = script_desc->Run();
5477
5478 CHECK_EQ(result->BooleanValue(), false);
5479
5480 v8::TryCatch try_catch;
5481 result = script_define->Run();
5482 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00005483 String::Utf8Value exception_value(try_catch.Exception());
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00005484 CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x");
ager@chromium.org5c838252010-02-19 08:53:10 +00005485}
5486
5487
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00005488static v8::Handle<v8::Object> GetGlobalProperty(LocalContext* context,
5489 char const* name) {
5490 return v8::Handle<v8::Object>::Cast((*context)->Global()->Get(v8_str(name)));
5491}
ager@chromium.org5c838252010-02-19 08:53:10 +00005492
5493
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00005494THREADED_TEST(DefineAPIAccessorOnObject) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005495 v8::Isolate* isolate = CcTest::isolate();
5496 v8::HandleScope scope(isolate);
5497 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00005498 LocalContext context;
5499
5500 context->Global()->Set(v8_str("obj1"), templ->NewInstance());
5501 CompileRun("var obj2 = {};");
5502
5503 CHECK(CompileRun("obj1.x")->IsUndefined());
5504 CHECK(CompileRun("obj2.x")->IsUndefined());
5505
5506 CHECK(GetGlobalProperty(&context, "obj1")->
5507 SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5508
5509 ExpectString("obj1.x", "x");
5510 CHECK(CompileRun("obj2.x")->IsUndefined());
5511
5512 CHECK(GetGlobalProperty(&context, "obj2")->
5513 SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5514
5515 ExpectString("obj1.x", "x");
5516 ExpectString("obj2.x", "x");
5517
5518 ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
5519 ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
5520
5521 CompileRun("Object.defineProperty(obj1, 'x',"
5522 "{ get: function() { return 'y'; }, configurable: true })");
5523
5524 ExpectString("obj1.x", "y");
5525 ExpectString("obj2.x", "x");
5526
5527 CompileRun("Object.defineProperty(obj2, 'x',"
5528 "{ get: function() { return 'y'; }, configurable: true })");
5529
5530 ExpectString("obj1.x", "y");
5531 ExpectString("obj2.x", "y");
5532
5533 ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
5534 ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
5535
5536 CHECK(GetGlobalProperty(&context, "obj1")->
5537 SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5538 CHECK(GetGlobalProperty(&context, "obj2")->
5539 SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5540
5541 ExpectString("obj1.x", "x");
5542 ExpectString("obj2.x", "x");
5543
5544 ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
5545 ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
5546
5547 // Define getters/setters, but now make them not configurable.
5548 CompileRun("Object.defineProperty(obj1, 'x',"
5549 "{ get: function() { return 'z'; }, configurable: false })");
5550 CompileRun("Object.defineProperty(obj2, 'x',"
5551 "{ get: function() { return 'z'; }, configurable: false })");
5552
5553 ExpectTrue("!Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
5554 ExpectTrue("!Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
5555
5556 ExpectString("obj1.x", "z");
5557 ExpectString("obj2.x", "z");
5558
5559 CHECK(!GetGlobalProperty(&context, "obj1")->
5560 SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5561 CHECK(!GetGlobalProperty(&context, "obj2")->
5562 SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5563
5564 ExpectString("obj1.x", "z");
5565 ExpectString("obj2.x", "z");
5566}
5567
5568
5569THREADED_TEST(DontDeleteAPIAccessorsCannotBeOverriden) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005570 v8::Isolate* isolate = CcTest::isolate();
5571 v8::HandleScope scope(isolate);
5572 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00005573 LocalContext context;
5574
5575 context->Global()->Set(v8_str("obj1"), templ->NewInstance());
5576 CompileRun("var obj2 = {};");
5577
5578 CHECK(GetGlobalProperty(&context, "obj1")->SetAccessor(
5579 v8_str("x"),
5580 GetXValue, NULL,
5581 v8_str("donut"), v8::DEFAULT, v8::DontDelete));
5582 CHECK(GetGlobalProperty(&context, "obj2")->SetAccessor(
5583 v8_str("x"),
5584 GetXValue, NULL,
5585 v8_str("donut"), v8::DEFAULT, v8::DontDelete));
5586
5587 ExpectString("obj1.x", "x");
5588 ExpectString("obj2.x", "x");
5589
5590 ExpectTrue("!Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
5591 ExpectTrue("!Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
5592
5593 CHECK(!GetGlobalProperty(&context, "obj1")->
5594 SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5595 CHECK(!GetGlobalProperty(&context, "obj2")->
5596 SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5597
5598 {
5599 v8::TryCatch try_catch;
5600 CompileRun("Object.defineProperty(obj1, 'x',"
5601 "{get: function() { return 'func'; }})");
5602 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00005603 String::Utf8Value exception_value(try_catch.Exception());
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00005604 CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x");
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00005605 }
5606 {
5607 v8::TryCatch try_catch;
5608 CompileRun("Object.defineProperty(obj2, 'x',"
5609 "{get: function() { return 'func'; }})");
5610 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00005611 String::Utf8Value exception_value(try_catch.Exception());
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +00005612 CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x");
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00005613 }
5614}
5615
5616
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005617static void Get239Value(Local<String> name,
5618 const v8::PropertyCallbackInfo<v8::Value>& info) {
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00005619 ApiTestFuzzer::Fuzz();
5620 CHECK_EQ(info.Data(), v8_str("donut"));
5621 CHECK_EQ(name, v8_str("239"));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005622 info.GetReturnValue().Set(name);
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00005623}
5624
5625
5626THREADED_TEST(ElementAPIAccessor) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005627 v8::Isolate* isolate = CcTest::isolate();
5628 v8::HandleScope scope(isolate);
5629 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00005630 LocalContext context;
5631
5632 context->Global()->Set(v8_str("obj1"), templ->NewInstance());
5633 CompileRun("var obj2 = {};");
5634
5635 CHECK(GetGlobalProperty(&context, "obj1")->SetAccessor(
5636 v8_str("239"),
5637 Get239Value, NULL,
5638 v8_str("donut")));
5639 CHECK(GetGlobalProperty(&context, "obj2")->SetAccessor(
5640 v8_str("239"),
5641 Get239Value, NULL,
5642 v8_str("donut")));
5643
5644 ExpectString("obj1[239]", "239");
5645 ExpectString("obj2[239]", "239");
5646 ExpectString("obj1['239']", "239");
5647 ExpectString("obj2['239']", "239");
5648}
5649
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005650
5651v8::Persistent<Value> xValue;
5652
5653
5654static void SetXValue(Local<String> name,
5655 Local<Value> value,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005656 const v8::PropertyCallbackInfo<void>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005657 CHECK_EQ(value, v8_num(4));
5658 CHECK_EQ(info.Data(), v8_str("donut"));
5659 CHECK_EQ(name, v8_str("x"));
5660 CHECK(xValue.IsEmpty());
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00005661 xValue.Reset(info.GetIsolate(), value);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005662}
5663
5664
5665THREADED_TEST(SimplePropertyWrite) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005666 v8::Isolate* isolate = CcTest::isolate();
5667 v8::HandleScope scope(isolate);
5668 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005669 templ->SetAccessor(v8_str("x"), GetXValue, SetXValue, v8_str("donut"));
5670 LocalContext context;
5671 context->Global()->Set(v8_str("obj"), templ->NewInstance());
5672 Local<Script> script = Script::Compile(v8_str("obj.x = 4"));
5673 for (int i = 0; i < 10; i++) {
5674 CHECK(xValue.IsEmpty());
5675 script->Run();
machenbach@chromium.org528ce022013-09-23 14:09:36 +00005676 CHECK_EQ(v8_num(4), Local<Value>::New(CcTest::isolate(), xValue));
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00005677 xValue.Reset();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005678 }
5679}
5680
5681
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00005682THREADED_TEST(SetterOnly) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005683 v8::Isolate* isolate = CcTest::isolate();
5684 v8::HandleScope scope(isolate);
5685 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00005686 templ->SetAccessor(v8_str("x"), NULL, SetXValue, v8_str("donut"));
5687 LocalContext context;
5688 context->Global()->Set(v8_str("obj"), templ->NewInstance());
5689 Local<Script> script = Script::Compile(v8_str("obj.x = 4; obj.x"));
5690 for (int i = 0; i < 10; i++) {
5691 CHECK(xValue.IsEmpty());
5692 script->Run();
machenbach@chromium.org528ce022013-09-23 14:09:36 +00005693 CHECK_EQ(v8_num(4), Local<Value>::New(CcTest::isolate(), xValue));
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00005694 xValue.Reset();
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00005695 }
5696}
5697
5698
5699THREADED_TEST(NoAccessors) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005700 v8::Isolate* isolate = CcTest::isolate();
5701 v8::HandleScope scope(isolate);
5702 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00005703 templ->SetAccessor(v8_str("x"),
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005704 static_cast<v8::AccessorGetterCallback>(NULL),
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00005705 NULL,
5706 v8_str("donut"));
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00005707 LocalContext context;
5708 context->Global()->Set(v8_str("obj"), templ->NewInstance());
5709 Local<Script> script = Script::Compile(v8_str("obj.x = 4; obj.x"));
5710 for (int i = 0; i < 10; i++) {
5711 script->Run();
5712 }
5713}
5714
5715
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005716static void XPropertyGetter(Local<String> property,
5717 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005718 ApiTestFuzzer::Fuzz();
5719 CHECK(info.Data()->IsUndefined());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005720 info.GetReturnValue().Set(property);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005721}
5722
5723
ager@chromium.orgeadaf222009-06-16 09:43:10 +00005724THREADED_TEST(NamedInterceptorPropertyRead) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005725 v8::Isolate* isolate = CcTest::isolate();
5726 v8::HandleScope scope(isolate);
5727 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00005728 templ->SetNamedPropertyHandler(XPropertyGetter);
5729 LocalContext context;
5730 context->Global()->Set(v8_str("obj"), templ->NewInstance());
5731 Local<Script> script = Script::Compile(v8_str("obj.x"));
5732 for (int i = 0; i < 10; i++) {
5733 Local<Value> result = script->Run();
5734 CHECK_EQ(result, v8_str("x"));
5735 }
5736}
5737
ager@chromium.orgeadaf222009-06-16 09:43:10 +00005738
ager@chromium.orgb26c50a2010-03-26 09:27:16 +00005739THREADED_TEST(NamedInterceptorDictionaryIC) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005740 v8::Isolate* isolate = CcTest::isolate();
5741 v8::HandleScope scope(isolate);
5742 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.orgb26c50a2010-03-26 09:27:16 +00005743 templ->SetNamedPropertyHandler(XPropertyGetter);
5744 LocalContext context;
5745 // Create an object with a named interceptor.
5746 context->Global()->Set(v8_str("interceptor_obj"), templ->NewInstance());
5747 Local<Script> script = Script::Compile(v8_str("interceptor_obj.x"));
5748 for (int i = 0; i < 10; i++) {
5749 Local<Value> result = script->Run();
5750 CHECK_EQ(result, v8_str("x"));
5751 }
5752 // Create a slow case object and a function accessing a property in
5753 // that slow case object (with dictionary probing in generated
5754 // code). Then force object with a named interceptor into slow-case,
5755 // pass it to the function, and check that the interceptor is called
5756 // instead of accessing the local property.
5757 Local<Value> result =
5758 CompileRun("function get_x(o) { return o.x; };"
5759 "var obj = { x : 42, y : 0 };"
5760 "delete obj.y;"
5761 "for (var i = 0; i < 10; i++) get_x(obj);"
5762 "interceptor_obj.x = 42;"
5763 "interceptor_obj.y = 10;"
5764 "delete interceptor_obj.y;"
5765 "get_x(interceptor_obj)");
5766 CHECK_EQ(result, v8_str("x"));
5767}
5768
5769
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00005770THREADED_TEST(NamedInterceptorDictionaryICMultipleContext) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00005771 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00005772 v8::HandleScope scope(isolate);
5773 v8::Local<Context> context1 = Context::New(isolate);
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00005774
5775 context1->Enter();
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005776 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00005777 templ->SetNamedPropertyHandler(XPropertyGetter);
5778 // Create an object with a named interceptor.
5779 v8::Local<v8::Object> object = templ->NewInstance();
5780 context1->Global()->Set(v8_str("interceptor_obj"), object);
5781
5782 // Force the object into the slow case.
5783 CompileRun("interceptor_obj.y = 0;"
5784 "delete interceptor_obj.y;");
5785 context1->Exit();
5786
5787 {
5788 // Introduce the object into a different context.
5789 // Repeat named loads to exercise ICs.
5790 LocalContext context2;
5791 context2->Global()->Set(v8_str("interceptor_obj"), object);
5792 Local<Value> result =
5793 CompileRun("function get_x(o) { return o.x; }"
5794 "interceptor_obj.x = 42;"
5795 "for (var i=0; i != 10; i++) {"
5796 " get_x(interceptor_obj);"
5797 "}"
5798 "get_x(interceptor_obj)");
5799 // Check that the interceptor was actually invoked.
5800 CHECK_EQ(result, v8_str("x"));
5801 }
5802
5803 // Return to the original context and force some object to the slow case
5804 // to cause the NormalizedMapCache to verify.
5805 context1->Enter();
5806 CompileRun("var obj = { x : 0 }; delete obj.x;");
5807 context1->Exit();
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00005808}
5809
5810
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005811static void SetXOnPrototypeGetter(
5812 Local<String> property,
5813 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.org5c838252010-02-19 08:53:10 +00005814 // Set x on the prototype object and do not handle the get request.
5815 v8::Handle<v8::Value> proto = info.Holder()->GetPrototype();
ulan@chromium.org0f13e742014-01-03 15:51:11 +00005816 proto.As<v8::Object>()->Set(v8_str("x"),
5817 v8::Integer::New(info.GetIsolate(), 23));
ager@chromium.org5c838252010-02-19 08:53:10 +00005818}
5819
5820
5821// This is a regression test for http://crbug.com/20104. Map
5822// transitions should not interfere with post interceptor lookup.
5823THREADED_TEST(NamedInterceptorMapTransitionRead) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00005824 v8::Isolate* isolate = CcTest::isolate();
5825 v8::HandleScope scope(isolate);
5826 Local<v8::FunctionTemplate> function_template =
5827 v8::FunctionTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +00005828 Local<v8::ObjectTemplate> instance_template
5829 = function_template->InstanceTemplate();
5830 instance_template->SetNamedPropertyHandler(SetXOnPrototypeGetter);
5831 LocalContext context;
5832 context->Global()->Set(v8_str("F"), function_template->GetFunction());
5833 // Create an instance of F and introduce a map transition for x.
5834 CompileRun("var o = new F(); o.x = 23;");
5835 // Create an instance of F and invoke the getter. The result should be 23.
5836 Local<Value> result = CompileRun("o = new F(); o.x");
5837 CHECK_EQ(result->Int32Value(), 23);
5838}
5839
5840
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005841static void IndexedPropertyGetter(
5842 uint32_t index,
5843 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.orgeadaf222009-06-16 09:43:10 +00005844 ApiTestFuzzer::Fuzz();
5845 if (index == 37) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005846 info.GetReturnValue().Set(v8_num(625));
ager@chromium.orgeadaf222009-06-16 09:43:10 +00005847 }
ager@chromium.orgeadaf222009-06-16 09:43:10 +00005848}
5849
5850
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005851static void IndexedPropertySetter(
5852 uint32_t index,
5853 Local<Value> value,
5854 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.orgeadaf222009-06-16 09:43:10 +00005855 ApiTestFuzzer::Fuzz();
5856 if (index == 39) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005857 info.GetReturnValue().Set(value);
ager@chromium.orgeadaf222009-06-16 09:43:10 +00005858 }
ager@chromium.orgeadaf222009-06-16 09:43:10 +00005859}
5860
5861
5862THREADED_TEST(IndexedInterceptorWithIndexedAccessor) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005863 v8::Isolate* isolate = CcTest::isolate();
5864 v8::HandleScope scope(isolate);
5865 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.orgeadaf222009-06-16 09:43:10 +00005866 templ->SetIndexedPropertyHandler(IndexedPropertyGetter,
5867 IndexedPropertySetter);
5868 LocalContext context;
5869 context->Global()->Set(v8_str("obj"), templ->NewInstance());
5870 Local<Script> getter_script = Script::Compile(v8_str(
5871 "obj.__defineGetter__(\"3\", function(){return 5;});obj[3];"));
5872 Local<Script> setter_script = Script::Compile(v8_str(
5873 "obj.__defineSetter__(\"17\", function(val){this.foo = val;});"
5874 "obj[17] = 23;"
5875 "obj.foo;"));
5876 Local<Script> interceptor_setter_script = Script::Compile(v8_str(
5877 "obj.__defineSetter__(\"39\", function(val){this.foo = \"hit\";});"
5878 "obj[39] = 47;"
5879 "obj.foo;")); // This setter should not run, due to the interceptor.
5880 Local<Script> interceptor_getter_script = Script::Compile(v8_str(
5881 "obj[37];"));
5882 Local<Value> result = getter_script->Run();
5883 CHECK_EQ(v8_num(5), result);
5884 result = setter_script->Run();
5885 CHECK_EQ(v8_num(23), result);
5886 result = interceptor_setter_script->Run();
5887 CHECK_EQ(v8_num(23), result);
5888 result = interceptor_getter_script->Run();
5889 CHECK_EQ(v8_num(625), result);
5890}
5891
5892
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005893static void UnboxedDoubleIndexedPropertyGetter(
ricow@chromium.org9fa09672011-07-25 11:05:35 +00005894 uint32_t index,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005895 const v8::PropertyCallbackInfo<v8::Value>& info) {
ricow@chromium.org9fa09672011-07-25 11:05:35 +00005896 ApiTestFuzzer::Fuzz();
5897 if (index < 25) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005898 info.GetReturnValue().Set(v8_num(index));
ricow@chromium.org9fa09672011-07-25 11:05:35 +00005899 }
ricow@chromium.org9fa09672011-07-25 11:05:35 +00005900}
5901
5902
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005903static void UnboxedDoubleIndexedPropertySetter(
ricow@chromium.org9fa09672011-07-25 11:05:35 +00005904 uint32_t index,
5905 Local<Value> value,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005906 const v8::PropertyCallbackInfo<v8::Value>& info) {
ricow@chromium.org9fa09672011-07-25 11:05:35 +00005907 ApiTestFuzzer::Fuzz();
5908 if (index < 25) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005909 info.GetReturnValue().Set(v8_num(index));
ricow@chromium.org9fa09672011-07-25 11:05:35 +00005910 }
ricow@chromium.org9fa09672011-07-25 11:05:35 +00005911}
5912
5913
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005914void UnboxedDoubleIndexedPropertyEnumerator(
5915 const v8::PropertyCallbackInfo<v8::Array>& info) {
ricow@chromium.org9fa09672011-07-25 11:05:35 +00005916 // Force the list of returned keys to be stored in a FastDoubleArray.
5917 Local<Script> indexed_property_names_script = Script::Compile(v8_str(
5918 "keys = new Array(); keys[125000] = 1;"
5919 "for(i = 0; i < 80000; i++) { keys[i] = i; };"
5920 "keys.length = 25; keys;"));
5921 Local<Value> result = indexed_property_names_script->Run();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005922 info.GetReturnValue().Set(Local<v8::Array>::Cast(result));
ricow@chromium.org9fa09672011-07-25 11:05:35 +00005923}
5924
5925
5926// Make sure that the the interceptor code in the runtime properly handles
5927// merging property name lists for double-array-backed arrays.
5928THREADED_TEST(IndexedInterceptorUnboxedDoubleWithIndexedAccessor) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005929 v8::Isolate* isolate = CcTest::isolate();
5930 v8::HandleScope scope(isolate);
5931 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ricow@chromium.org9fa09672011-07-25 11:05:35 +00005932 templ->SetIndexedPropertyHandler(UnboxedDoubleIndexedPropertyGetter,
5933 UnboxedDoubleIndexedPropertySetter,
5934 0,
5935 0,
5936 UnboxedDoubleIndexedPropertyEnumerator);
5937 LocalContext context;
5938 context->Global()->Set(v8_str("obj"), templ->NewInstance());
5939 // When obj is created, force it to be Stored in a FastDoubleArray.
5940 Local<Script> create_unboxed_double_script = Script::Compile(v8_str(
5941 "obj[125000] = 1; for(i = 0; i < 80000; i+=2) { obj[i] = i; } "
5942 "key_count = 0; "
5943 "for (x in obj) {key_count++;};"
5944 "obj;"));
5945 Local<Value> result = create_unboxed_double_script->Run();
5946 CHECK(result->ToObject()->HasRealIndexedProperty(2000));
5947 Local<Script> key_count_check = Script::Compile(v8_str(
5948 "key_count;"));
5949 result = key_count_check->Run();
5950 CHECK_EQ(v8_num(40013), result);
5951}
5952
5953
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005954void NonStrictArgsIndexedPropertyEnumerator(
5955 const v8::PropertyCallbackInfo<v8::Array>& info) {
rossberg@chromium.org28a37082011-08-22 11:03:23 +00005956 // Force the list of returned keys to be stored in a Arguments object.
5957 Local<Script> indexed_property_names_script = Script::Compile(v8_str(
5958 "function f(w,x) {"
5959 " return arguments;"
5960 "}"
5961 "keys = f(0, 1, 2, 3);"
5962 "keys;"));
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00005963 Local<Object> result =
5964 Local<Object>::Cast(indexed_property_names_script->Run());
5965 // Have to populate the handle manually, as it's not Cast-able.
5966 i::Handle<i::JSObject> o =
5967 v8::Utils::OpenHandle<Object, i::JSObject>(result);
5968 i::Handle<i::JSArray> array(reinterpret_cast<i::JSArray*>(*o));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005969 info.GetReturnValue().Set(v8::Utils::ToLocal(array));
rossberg@chromium.org28a37082011-08-22 11:03:23 +00005970}
5971
5972
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005973static void NonStrictIndexedPropertyGetter(
rossberg@chromium.org28a37082011-08-22 11:03:23 +00005974 uint32_t index,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005975 const v8::PropertyCallbackInfo<v8::Value>& info) {
rossberg@chromium.org28a37082011-08-22 11:03:23 +00005976 ApiTestFuzzer::Fuzz();
5977 if (index < 4) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00005978 info.GetReturnValue().Set(v8_num(index));
rossberg@chromium.org28a37082011-08-22 11:03:23 +00005979 }
rossberg@chromium.org28a37082011-08-22 11:03:23 +00005980}
5981
5982
5983// Make sure that the the interceptor code in the runtime properly handles
5984// merging property name lists for non-string arguments arrays.
5985THREADED_TEST(IndexedInterceptorNonStrictArgsWithIndexedAccessor) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00005986 v8::Isolate* isolate = CcTest::isolate();
5987 v8::HandleScope scope(isolate);
5988 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
rossberg@chromium.org28a37082011-08-22 11:03:23 +00005989 templ->SetIndexedPropertyHandler(NonStrictIndexedPropertyGetter,
5990 0,
5991 0,
5992 0,
5993 NonStrictArgsIndexedPropertyEnumerator);
5994 LocalContext context;
5995 context->Global()->Set(v8_str("obj"), templ->NewInstance());
5996 Local<Script> create_args_script =
5997 Script::Compile(v8_str(
5998 "var key_count = 0;"
5999 "for (x in obj) {key_count++;} key_count;"));
6000 Local<Value> result = create_args_script->Run();
6001 CHECK_EQ(v8_num(4), result);
6002}
6003
6004
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00006005static void IdentityIndexedPropertyGetter(
kasperl@chromium.orgeac059f2010-01-25 11:02:06 +00006006 uint32_t index,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00006007 const v8::PropertyCallbackInfo<v8::Value>& info) {
6008 info.GetReturnValue().Set(index);
kasperl@chromium.orgeac059f2010-01-25 11:02:06 +00006009}
6010
6011
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00006012THREADED_TEST(IndexedInterceptorWithGetOwnPropertyDescriptor) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00006013 v8::Isolate* isolate = CcTest::isolate();
6014 v8::HandleScope scope(isolate);
6015 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +00006016 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
6017
6018 LocalContext context;
6019 context->Global()->Set(v8_str("obj"), templ->NewInstance());
6020
6021 // Check fast object case.
6022 const char* fast_case_code =
6023 "Object.getOwnPropertyDescriptor(obj, 0).value.toString()";
6024 ExpectString(fast_case_code, "0");
6025
6026 // Check slow case.
6027 const char* slow_case_code =
6028 "obj.x = 1; delete obj.x;"
6029 "Object.getOwnPropertyDescriptor(obj, 1).value.toString()";
6030 ExpectString(slow_case_code, "1");
6031}
6032
6033
kasperl@chromium.orgeac059f2010-01-25 11:02:06 +00006034THREADED_TEST(IndexedInterceptorWithNoSetter) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00006035 v8::Isolate* isolate = CcTest::isolate();
6036 v8::HandleScope scope(isolate);
6037 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
kasperl@chromium.orgeac059f2010-01-25 11:02:06 +00006038 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
6039
6040 LocalContext context;
6041 context->Global()->Set(v8_str("obj"), templ->NewInstance());
6042
6043 const char* code =
6044 "try {"
6045 " obj[0] = 239;"
6046 " for (var i = 0; i < 100; i++) {"
6047 " var v = obj[0];"
6048 " if (v != 0) throw 'Wrong value ' + v + ' at iteration ' + i;"
6049 " }"
6050 " 'PASSED'"
6051 "} catch(e) {"
6052 " e"
6053 "}";
6054 ExpectString(code, "PASSED");
6055}
6056
6057
ager@chromium.org5c838252010-02-19 08:53:10 +00006058THREADED_TEST(IndexedInterceptorWithAccessorCheck) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00006059 v8::Isolate* isolate = CcTest::isolate();
6060 v8::HandleScope scope(isolate);
6061 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +00006062 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
6063
6064 LocalContext context;
6065 Local<v8::Object> obj = templ->NewInstance();
6066 obj->TurnOnAccessCheck();
6067 context->Global()->Set(v8_str("obj"), obj);
6068
6069 const char* code =
6070 "try {"
6071 " for (var i = 0; i < 100; i++) {"
6072 " var v = obj[0];"
6073 " if (v != undefined) throw 'Wrong value ' + v + ' at iteration ' + i;"
6074 " }"
6075 " 'PASSED'"
6076 "} catch(e) {"
6077 " e"
6078 "}";
6079 ExpectString(code, "PASSED");
6080}
6081
6082
6083THREADED_TEST(IndexedInterceptorWithAccessorCheckSwitchedOn) {
6084 i::FLAG_allow_natives_syntax = true;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00006085 v8::Isolate* isolate = CcTest::isolate();
6086 v8::HandleScope scope(isolate);
6087 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +00006088 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
6089
6090 LocalContext context;
6091 Local<v8::Object> obj = templ->NewInstance();
6092 context->Global()->Set(v8_str("obj"), obj);
6093
6094 const char* code =
6095 "try {"
6096 " for (var i = 0; i < 100; i++) {"
6097 " var expected = i;"
6098 " if (i == 5) {"
6099 " %EnableAccessChecks(obj);"
6100 " expected = undefined;"
6101 " }"
6102 " var v = obj[i];"
6103 " if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
6104 " if (i == 5) %DisableAccessChecks(obj);"
6105 " }"
6106 " 'PASSED'"
6107 "} catch(e) {"
6108 " e"
6109 "}";
6110 ExpectString(code, "PASSED");
6111}
6112
6113
6114THREADED_TEST(IndexedInterceptorWithDifferentIndices) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00006115 v8::Isolate* isolate = CcTest::isolate();
6116 v8::HandleScope scope(isolate);
6117 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +00006118 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
6119
6120 LocalContext context;
6121 Local<v8::Object> obj = templ->NewInstance();
6122 context->Global()->Set(v8_str("obj"), obj);
6123
6124 const char* code =
6125 "try {"
6126 " for (var i = 0; i < 100; i++) {"
6127 " var v = obj[i];"
6128 " if (v != i) throw 'Wrong value ' + v + ' at iteration ' + i;"
6129 " }"
6130 " 'PASSED'"
6131 "} catch(e) {"
6132 " e"
6133 "}";
6134 ExpectString(code, "PASSED");
6135}
6136
6137
kmillikin@chromium.orgf05f2912010-09-30 10:07:24 +00006138THREADED_TEST(IndexedInterceptorWithNegativeIndices) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00006139 v8::Isolate* isolate = CcTest::isolate();
6140 v8::HandleScope scope(isolate);
6141 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
kmillikin@chromium.orgf05f2912010-09-30 10:07:24 +00006142 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
6143
6144 LocalContext context;
6145 Local<v8::Object> obj = templ->NewInstance();
6146 context->Global()->Set(v8_str("obj"), obj);
6147
6148 const char* code =
6149 "try {"
6150 " for (var i = 0; i < 100; i++) {"
6151 " var expected = i;"
6152 " var key = i;"
6153 " if (i == 25) {"
6154 " key = -1;"
6155 " expected = undefined;"
6156 " }"
6157 " if (i == 50) {"
6158 " /* probe minimal Smi number on 32-bit platforms */"
6159 " key = -(1 << 30);"
6160 " expected = undefined;"
6161 " }"
6162 " if (i == 75) {"
6163 " /* probe minimal Smi number on 64-bit platforms */"
6164 " key = 1 << 31;"
6165 " expected = undefined;"
6166 " }"
6167 " var v = obj[key];"
6168 " if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
6169 " }"
6170 " 'PASSED'"
6171 "} catch(e) {"
6172 " e"
6173 "}";
6174 ExpectString(code, "PASSED");
6175}
6176
6177
ager@chromium.org5c838252010-02-19 08:53:10 +00006178THREADED_TEST(IndexedInterceptorWithNotSmiLookup) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00006179 v8::Isolate* isolate = CcTest::isolate();
6180 v8::HandleScope scope(isolate);
6181 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +00006182 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
6183
6184 LocalContext context;
6185 Local<v8::Object> obj = templ->NewInstance();
6186 context->Global()->Set(v8_str("obj"), obj);
6187
6188 const char* code =
6189 "try {"
6190 " for (var i = 0; i < 100; i++) {"
6191 " var expected = i;"
kmillikin@chromium.orgf05f2912010-09-30 10:07:24 +00006192 " var key = i;"
ager@chromium.org5c838252010-02-19 08:53:10 +00006193 " if (i == 50) {"
kmillikin@chromium.orgf05f2912010-09-30 10:07:24 +00006194 " key = 'foobar';"
ager@chromium.org5c838252010-02-19 08:53:10 +00006195 " expected = undefined;"
6196 " }"
kmillikin@chromium.orgf05f2912010-09-30 10:07:24 +00006197 " var v = obj[key];"
ager@chromium.org5c838252010-02-19 08:53:10 +00006198 " if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
6199 " }"
6200 " 'PASSED'"
6201 "} catch(e) {"
6202 " e"
6203 "}";
6204 ExpectString(code, "PASSED");
6205}
6206
6207
6208THREADED_TEST(IndexedInterceptorGoingMegamorphic) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00006209 v8::Isolate* isolate = CcTest::isolate();
6210 v8::HandleScope scope(isolate);
6211 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +00006212 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
6213
6214 LocalContext context;
6215 Local<v8::Object> obj = templ->NewInstance();
6216 context->Global()->Set(v8_str("obj"), obj);
6217
6218 const char* code =
6219 "var original = obj;"
6220 "try {"
6221 " for (var i = 0; i < 100; i++) {"
6222 " var expected = i;"
6223 " if (i == 50) {"
6224 " obj = {50: 'foobar'};"
6225 " expected = 'foobar';"
6226 " }"
6227 " var v = obj[i];"
6228 " if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
6229 " if (i == 50) obj = original;"
6230 " }"
6231 " 'PASSED'"
6232 "} catch(e) {"
6233 " e"
6234 "}";
6235 ExpectString(code, "PASSED");
6236}
6237
6238
6239THREADED_TEST(IndexedInterceptorReceiverTurningSmi) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00006240 v8::Isolate* isolate = CcTest::isolate();
6241 v8::HandleScope scope(isolate);
6242 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +00006243 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
6244
6245 LocalContext context;
6246 Local<v8::Object> obj = templ->NewInstance();
6247 context->Global()->Set(v8_str("obj"), obj);
6248
6249 const char* code =
6250 "var original = obj;"
6251 "try {"
6252 " for (var i = 0; i < 100; i++) {"
6253 " var expected = i;"
6254 " if (i == 5) {"
6255 " obj = 239;"
6256 " expected = undefined;"
6257 " }"
6258 " var v = obj[i];"
6259 " if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
6260 " if (i == 5) obj = original;"
6261 " }"
6262 " 'PASSED'"
6263 "} catch(e) {"
6264 " e"
6265 "}";
6266 ExpectString(code, "PASSED");
6267}
6268
6269
6270THREADED_TEST(IndexedInterceptorOnProto) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00006271 v8::Isolate* isolate = CcTest::isolate();
6272 v8::HandleScope scope(isolate);
6273 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +00006274 templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
6275
6276 LocalContext context;
6277 Local<v8::Object> obj = templ->NewInstance();
6278 context->Global()->Set(v8_str("obj"), obj);
6279
6280 const char* code =
6281 "var o = {__proto__: obj};"
6282 "try {"
6283 " for (var i = 0; i < 100; i++) {"
6284 " var v = o[i];"
6285 " if (v != i) throw 'Wrong value ' + v + ' at iteration ' + i;"
6286 " }"
6287 " 'PASSED'"
6288 "} catch(e) {"
6289 " e"
6290 "}";
6291 ExpectString(code, "PASSED");
6292}
6293
6294
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006295THREADED_TEST(MultiContexts) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00006296 v8::Isolate* isolate = CcTest::isolate();
6297 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00006298 v8::Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00006299 templ->Set(v8_str("dummy"), v8::FunctionTemplate::New(isolate,
6300 DummyCallHandler));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006301
6302 Local<String> password = v8_str("Password");
6303
6304 // Create an environment
6305 LocalContext context0(0, templ);
6306 context0->SetSecurityToken(password);
6307 v8::Handle<v8::Object> global0 = context0->Global();
6308 global0->Set(v8_str("custom"), v8_num(1234));
6309 CHECK_EQ(1234, global0->Get(v8_str("custom"))->Int32Value());
6310
6311 // Create an independent environment
6312 LocalContext context1(0, templ);
6313 context1->SetSecurityToken(password);
6314 v8::Handle<v8::Object> global1 = context1->Global();
6315 global1->Set(v8_str("custom"), v8_num(1234));
6316 CHECK_NE(global0, global1);
6317 CHECK_EQ(1234, global0->Get(v8_str("custom"))->Int32Value());
6318 CHECK_EQ(1234, global1->Get(v8_str("custom"))->Int32Value());
6319
6320 // Now create a new context with the old global
6321 LocalContext context2(0, templ, global1);
6322 context2->SetSecurityToken(password);
6323 v8::Handle<v8::Object> global2 = context2->Global();
6324 CHECK_EQ(global1, global2);
6325 CHECK_EQ(0, global1->Get(v8_str("custom"))->Int32Value());
6326 CHECK_EQ(0, global2->Get(v8_str("custom"))->Int32Value());
6327}
6328
6329
6330THREADED_TEST(FunctionPrototypeAcrossContexts) {
6331 // Make sure that functions created by cloning boilerplates cannot
6332 // communicate through their __proto__ field.
6333
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006334 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006335
6336 LocalContext env0;
6337 v8::Handle<v8::Object> global0 =
6338 env0->Global();
6339 v8::Handle<v8::Object> object0 =
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00006340 global0->Get(v8_str("Object")).As<v8::Object>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006341 v8::Handle<v8::Object> tostring0 =
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00006342 object0->Get(v8_str("toString")).As<v8::Object>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006343 v8::Handle<v8::Object> proto0 =
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00006344 tostring0->Get(v8_str("__proto__")).As<v8::Object>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006345 proto0->Set(v8_str("custom"), v8_num(1234));
6346
6347 LocalContext env1;
6348 v8::Handle<v8::Object> global1 =
6349 env1->Global();
6350 v8::Handle<v8::Object> object1 =
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00006351 global1->Get(v8_str("Object")).As<v8::Object>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006352 v8::Handle<v8::Object> tostring1 =
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00006353 object1->Get(v8_str("toString")).As<v8::Object>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006354 v8::Handle<v8::Object> proto1 =
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00006355 tostring1->Get(v8_str("__proto__")).As<v8::Object>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006356 CHECK(!proto1->Has(v8_str("custom")));
6357}
6358
6359
6360THREADED_TEST(Regress892105) {
6361 // Make sure that object and array literals created by cloning
6362 // boilerplates cannot communicate through their __proto__
6363 // field. This is rather difficult to check, but we try to add stuff
6364 // to Object.prototype and Array.prototype and create a new
6365 // environment. This should succeed.
6366
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006367 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006368
6369 Local<String> source = v8_str("Object.prototype.obj = 1234;"
6370 "Array.prototype.arr = 4567;"
6371 "8901");
6372
6373 LocalContext env0;
6374 Local<Script> script0 = Script::Compile(source);
6375 CHECK_EQ(8901.0, script0->Run()->NumberValue());
6376
6377 LocalContext env1;
6378 Local<Script> script1 = Script::Compile(source);
6379 CHECK_EQ(8901.0, script1->Run()->NumberValue());
6380}
6381
6382
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006383THREADED_TEST(UndetectableObject) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006384 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00006385 v8::HandleScope scope(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006386
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00006387 Local<v8::FunctionTemplate> desc =
6388 v8::FunctionTemplate::New(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006389 desc->InstanceTemplate()->MarkAsUndetectable(); // undetectable
6390
6391 Local<v8::Object> obj = desc->GetFunction()->NewInstance();
6392 env->Global()->Set(v8_str("undetectable"), obj);
6393
6394 ExpectString("undetectable.toString()", "[object Object]");
6395 ExpectString("typeof undetectable", "undefined");
6396 ExpectString("typeof(undetectable)", "undefined");
6397 ExpectBoolean("typeof undetectable == 'undefined'", true);
6398 ExpectBoolean("typeof undetectable == 'object'", false);
6399 ExpectBoolean("if (undetectable) { true; } else { false; }", false);
6400 ExpectBoolean("!undetectable", true);
6401
6402 ExpectObject("true&&undetectable", obj);
6403 ExpectBoolean("false&&undetectable", false);
6404 ExpectBoolean("true||undetectable", true);
6405 ExpectObject("false||undetectable", obj);
6406
6407 ExpectObject("undetectable&&true", obj);
6408 ExpectObject("undetectable&&false", obj);
6409 ExpectBoolean("undetectable||true", true);
6410 ExpectBoolean("undetectable||false", false);
6411
6412 ExpectBoolean("undetectable==null", true);
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00006413 ExpectBoolean("null==undetectable", true);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006414 ExpectBoolean("undetectable==undefined", true);
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00006415 ExpectBoolean("undefined==undetectable", true);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006416 ExpectBoolean("undetectable==undetectable", true);
6417
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00006418
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006419 ExpectBoolean("undetectable===null", false);
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00006420 ExpectBoolean("null===undetectable", false);
6421 ExpectBoolean("undetectable===undefined", false);
6422 ExpectBoolean("undefined===undetectable", false);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006423 ExpectBoolean("undetectable===undetectable", true);
6424}
6425
6426
ager@chromium.org04921a82011-06-27 13:21:41 +00006427THREADED_TEST(VoidLiteral) {
ager@chromium.org04921a82011-06-27 13:21:41 +00006428 LocalContext env;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00006429 v8::Isolate* isolate = env->GetIsolate();
6430 v8::HandleScope scope(isolate);
ager@chromium.org04921a82011-06-27 13:21:41 +00006431
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00006432 Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
ager@chromium.org04921a82011-06-27 13:21:41 +00006433 desc->InstanceTemplate()->MarkAsUndetectable(); // undetectable
6434
6435 Local<v8::Object> obj = desc->GetFunction()->NewInstance();
6436 env->Global()->Set(v8_str("undetectable"), obj);
6437
6438 ExpectBoolean("undefined == void 0", true);
6439 ExpectBoolean("undetectable == void 0", true);
6440 ExpectBoolean("null == void 0", true);
6441 ExpectBoolean("undefined === void 0", true);
6442 ExpectBoolean("undetectable === void 0", false);
6443 ExpectBoolean("null === void 0", false);
6444
6445 ExpectBoolean("void 0 == undefined", true);
6446 ExpectBoolean("void 0 == undetectable", true);
6447 ExpectBoolean("void 0 == null", true);
6448 ExpectBoolean("void 0 === undefined", true);
6449 ExpectBoolean("void 0 === undetectable", false);
6450 ExpectBoolean("void 0 === null", false);
6451
6452 ExpectString("(function() {"
6453 " try {"
6454 " return x === void 0;"
6455 " } catch(e) {"
6456 " return e.toString();"
6457 " }"
6458 "})()",
6459 "ReferenceError: x is not defined");
6460 ExpectString("(function() {"
6461 " try {"
6462 " return void 0 === x;"
6463 " } catch(e) {"
6464 " return e.toString();"
6465 " }"
6466 "})()",
6467 "ReferenceError: x is not defined");
6468}
6469
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00006470
6471THREADED_TEST(ExtensibleOnUndetectable) {
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00006472 LocalContext env;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00006473 v8::Isolate* isolate = env->GetIsolate();
6474 v8::HandleScope scope(isolate);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00006475
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00006476 Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00006477 desc->InstanceTemplate()->MarkAsUndetectable(); // undetectable
6478
6479 Local<v8::Object> obj = desc->GetFunction()->NewInstance();
6480 env->Global()->Set(v8_str("undetectable"), obj);
6481
6482 Local<String> source = v8_str("undetectable.x = 42;"
6483 "undetectable.x");
6484
6485 Local<Script> script = Script::Compile(source);
6486
ulan@chromium.org0f13e742014-01-03 15:51:11 +00006487 CHECK_EQ(v8::Integer::New(isolate, 42), script->Run());
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00006488
6489 ExpectBoolean("Object.isExtensible(undetectable)", true);
6490
6491 source = v8_str("Object.preventExtensions(undetectable);");
6492 script = Script::Compile(source);
6493 script->Run();
6494 ExpectBoolean("Object.isExtensible(undetectable)", false);
6495
6496 source = v8_str("undetectable.y = 2000;");
6497 script = Script::Compile(source);
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00006498 script->Run();
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00006499 ExpectBoolean("undetectable.y == undefined", true);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00006500}
6501
6502
6503
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006504THREADED_TEST(UndetectableString) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006505 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00006506 v8::HandleScope scope(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006507
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00006508 Local<String> obj = String::NewFromUtf8(env->GetIsolate(), "foo",
6509 String::kUndetectableString);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006510 env->Global()->Set(v8_str("undetectable"), obj);
6511
6512 ExpectString("undetectable", "foo");
6513 ExpectString("typeof undetectable", "undefined");
6514 ExpectString("typeof(undetectable)", "undefined");
6515 ExpectBoolean("typeof undetectable == 'undefined'", true);
6516 ExpectBoolean("typeof undetectable == 'string'", false);
6517 ExpectBoolean("if (undetectable) { true; } else { false; }", false);
6518 ExpectBoolean("!undetectable", true);
6519
6520 ExpectObject("true&&undetectable", obj);
6521 ExpectBoolean("false&&undetectable", false);
6522 ExpectBoolean("true||undetectable", true);
6523 ExpectObject("false||undetectable", obj);
6524
6525 ExpectObject("undetectable&&true", obj);
6526 ExpectObject("undetectable&&false", obj);
6527 ExpectBoolean("undetectable||true", true);
6528 ExpectBoolean("undetectable||false", false);
6529
6530 ExpectBoolean("undetectable==null", true);
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00006531 ExpectBoolean("null==undetectable", true);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006532 ExpectBoolean("undetectable==undefined", true);
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00006533 ExpectBoolean("undefined==undetectable", true);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006534 ExpectBoolean("undetectable==undetectable", true);
6535
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00006536
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006537 ExpectBoolean("undetectable===null", false);
kasperl@chromium.org8ccb0be2009-04-07 07:21:39 +00006538 ExpectBoolean("null===undetectable", false);
6539 ExpectBoolean("undetectable===undefined", false);
6540 ExpectBoolean("undefined===undetectable", false);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006541 ExpectBoolean("undetectable===undetectable", true);
6542}
6543
6544
vegorov@chromium.org7304bca2011-05-16 12:14:13 +00006545TEST(UndetectableOptimized) {
6546 i::FLAG_allow_natives_syntax = true;
vegorov@chromium.org7304bca2011-05-16 12:14:13 +00006547 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00006548 v8::HandleScope scope(env->GetIsolate());
vegorov@chromium.org7304bca2011-05-16 12:14:13 +00006549
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00006550 Local<String> obj = String::NewFromUtf8(env->GetIsolate(), "foo",
6551 String::kUndetectableString);
vegorov@chromium.org7304bca2011-05-16 12:14:13 +00006552 env->Global()->Set(v8_str("undetectable"), obj);
6553 env->Global()->Set(v8_str("detectable"), v8_str("bar"));
6554
6555 ExpectString(
6556 "function testBranch() {"
6557 " if (!%_IsUndetectableObject(undetectable)) throw 1;"
6558 " if (%_IsUndetectableObject(detectable)) throw 2;"
6559 "}\n"
6560 "function testBool() {"
6561 " var b1 = !%_IsUndetectableObject(undetectable);"
6562 " var b2 = %_IsUndetectableObject(detectable);"
6563 " if (b1) throw 3;"
6564 " if (b2) throw 4;"
6565 " return b1 == b2;"
6566 "}\n"
6567 "%OptimizeFunctionOnNextCall(testBranch);"
6568 "%OptimizeFunctionOnNextCall(testBool);"
6569 "for (var i = 0; i < 10; i++) {"
6570 " testBranch();"
6571 " testBool();"
6572 "}\n"
6573 "\"PASS\"",
6574 "PASS");
6575}
6576
6577
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006578template <typename T> static void USE(T) { }
6579
6580
machenbach@chromium.orgafbdadc2013-12-09 16:12:18 +00006581// The point of this test is type checking. We run it only so compilers
6582// don't complain about an unused function.
6583TEST(PersistentHandles) {
6584 LocalContext env;
6585 v8::Isolate* isolate = CcTest::isolate();
6586 v8::HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006587 Local<String> str = v8_str("foo");
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00006588 v8::Persistent<String> p_str(isolate, str);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00006589 p_str.Reset();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006590 Local<Script> scr = Script::Compile(v8_str(""));
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00006591 v8::Persistent<Script> p_scr(isolate, scr);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00006592 p_scr.Reset();
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00006593 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00006594 v8::Persistent<ObjectTemplate> p_templ(isolate, templ);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00006595 p_templ.Reset();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006596}
6597
6598
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00006599static void HandleLogDelegator(
6600 const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006601 ApiTestFuzzer::Fuzz();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006602}
6603
6604
6605THREADED_TEST(GlobalObjectTemplate) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006606 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006607 v8::HandleScope handle_scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00006608 Local<ObjectTemplate> global_template = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006609 global_template->Set(v8_str("JSNI_Log"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00006610 v8::FunctionTemplate::New(isolate, HandleLogDelegator));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006611 v8::Local<Context> context = Context::New(isolate, 0, global_template);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006612 Context::Scope context_scope(context);
6613 Script::Compile(v8_str("JSNI_Log('LOG')"))->Run();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006614}
6615
6616
6617static const char* kSimpleExtensionSource =
6618 "function Foo() {"
6619 " return 4;"
6620 "}";
6621
6622
machenbach@chromium.org09cae8d2014-01-30 01:05:27 +00006623TEST(SimpleExtensions) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006624 v8::HandleScope handle_scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006625 v8::RegisterExtension(new Extension("simpletest", kSimpleExtensionSource));
6626 const char* extension_names[] = { "simpletest" };
6627 v8::ExtensionConfiguration extensions(1, extension_names);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006628 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006629 Context::New(CcTest::isolate(), &extensions);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006630 Context::Scope lock(context);
6631 v8::Handle<Value> result = Script::Compile(v8_str("Foo()"))->Run();
ulan@chromium.org0f13e742014-01-03 15:51:11 +00006632 CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 4));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006633}
6634
6635
machenbach@chromium.org09cae8d2014-01-30 01:05:27 +00006636TEST(NullExtensions) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006637 v8::HandleScope handle_scope(CcTest::isolate());
danno@chromium.org412fa512012-09-14 13:28:26 +00006638 v8::RegisterExtension(new Extension("nulltest", NULL));
6639 const char* extension_names[] = { "nulltest" };
6640 v8::ExtensionConfiguration extensions(1, extension_names);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006641 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006642 Context::New(CcTest::isolate(), &extensions);
danno@chromium.org412fa512012-09-14 13:28:26 +00006643 Context::Scope lock(context);
6644 v8::Handle<Value> result = Script::Compile(v8_str("1+3"))->Run();
ulan@chromium.org0f13e742014-01-03 15:51:11 +00006645 CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 4));
danno@chromium.org412fa512012-09-14 13:28:26 +00006646}
6647
6648
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00006649static const char* kEmbeddedExtensionSource =
6650 "function Ret54321(){return 54321;}~~@@$"
6651 "$%% THIS IS A SERIES OF NON-NULL-TERMINATED STRINGS.";
6652static const int kEmbeddedExtensionSourceValidLen = 34;
6653
6654
machenbach@chromium.org09cae8d2014-01-30 01:05:27 +00006655TEST(ExtensionMissingSourceLength) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006656 v8::HandleScope handle_scope(CcTest::isolate());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00006657 v8::RegisterExtension(new Extension("srclentest_fail",
6658 kEmbeddedExtensionSource));
6659 const char* extension_names[] = { "srclentest_fail" };
6660 v8::ExtensionConfiguration extensions(1, extension_names);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006661 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006662 Context::New(CcTest::isolate(), &extensions);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00006663 CHECK_EQ(0, *context);
6664}
6665
6666
machenbach@chromium.org09cae8d2014-01-30 01:05:27 +00006667TEST(ExtensionWithSourceLength) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00006668 for (int source_len = kEmbeddedExtensionSourceValidLen - 1;
6669 source_len <= kEmbeddedExtensionSourceValidLen + 1; ++source_len) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006670 v8::HandleScope handle_scope(CcTest::isolate());
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00006671 i::ScopedVector<char> extension_name(32);
6672 i::OS::SNPrintF(extension_name, "ext #%d", source_len);
6673 v8::RegisterExtension(new Extension(extension_name.start(),
6674 kEmbeddedExtensionSource, 0, 0,
6675 source_len));
6676 const char* extension_names[1] = { extension_name.start() };
6677 v8::ExtensionConfiguration extensions(1, extension_names);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006678 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006679 Context::New(CcTest::isolate(), &extensions);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00006680 if (source_len == kEmbeddedExtensionSourceValidLen) {
6681 Context::Scope lock(context);
6682 v8::Handle<Value> result = Script::Compile(v8_str("Ret54321()"))->Run();
ulan@chromium.org0f13e742014-01-03 15:51:11 +00006683 CHECK_EQ(v8::Integer::New(CcTest::isolate(), 54321), result);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00006684 } else {
6685 // Anything but exactly the right length should fail to compile.
6686 CHECK_EQ(0, *context);
6687 }
6688 }
6689}
6690
6691
ager@chromium.org18ad94b2009-09-02 08:22:29 +00006692static const char* kEvalExtensionSource1 =
6693 "function UseEval1() {"
kasperl@chromium.org2d18d102009-04-15 13:27:32 +00006694 " var x = 42;"
6695 " return eval('x');"
6696 "}";
6697
6698
ager@chromium.org18ad94b2009-09-02 08:22:29 +00006699static const char* kEvalExtensionSource2 =
6700 "(function() {"
6701 " var x = 42;"
6702 " function e() {"
6703 " return eval('x');"
6704 " }"
6705 " this.UseEval2 = e;"
6706 "})()";
6707
6708
machenbach@chromium.org09cae8d2014-01-30 01:05:27 +00006709TEST(UseEvalFromExtension) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006710 v8::HandleScope handle_scope(CcTest::isolate());
ager@chromium.org18ad94b2009-09-02 08:22:29 +00006711 v8::RegisterExtension(new Extension("evaltest1", kEvalExtensionSource1));
6712 v8::RegisterExtension(new Extension("evaltest2", kEvalExtensionSource2));
6713 const char* extension_names[] = { "evaltest1", "evaltest2" };
6714 v8::ExtensionConfiguration extensions(2, extension_names);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006715 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006716 Context::New(CcTest::isolate(), &extensions);
kasperl@chromium.org2d18d102009-04-15 13:27:32 +00006717 Context::Scope lock(context);
ager@chromium.org18ad94b2009-09-02 08:22:29 +00006718 v8::Handle<Value> result = Script::Compile(v8_str("UseEval1()"))->Run();
ulan@chromium.org0f13e742014-01-03 15:51:11 +00006719 CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 42));
ager@chromium.org18ad94b2009-09-02 08:22:29 +00006720 result = Script::Compile(v8_str("UseEval2()"))->Run();
ulan@chromium.org0f13e742014-01-03 15:51:11 +00006721 CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 42));
kasperl@chromium.org2d18d102009-04-15 13:27:32 +00006722}
6723
6724
ager@chromium.org18ad94b2009-09-02 08:22:29 +00006725static const char* kWithExtensionSource1 =
6726 "function UseWith1() {"
kasperl@chromium.org2d18d102009-04-15 13:27:32 +00006727 " var x = 42;"
6728 " with({x:87}) { return x; }"
6729 "}";
6730
6731
ager@chromium.org18ad94b2009-09-02 08:22:29 +00006732
6733static const char* kWithExtensionSource2 =
6734 "(function() {"
6735 " var x = 42;"
6736 " function e() {"
6737 " with ({x:87}) { return x; }"
6738 " }"
6739 " this.UseWith2 = e;"
6740 "})()";
6741
6742
machenbach@chromium.org09cae8d2014-01-30 01:05:27 +00006743TEST(UseWithFromExtension) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006744 v8::HandleScope handle_scope(CcTest::isolate());
ager@chromium.org18ad94b2009-09-02 08:22:29 +00006745 v8::RegisterExtension(new Extension("withtest1", kWithExtensionSource1));
6746 v8::RegisterExtension(new Extension("withtest2", kWithExtensionSource2));
6747 const char* extension_names[] = { "withtest1", "withtest2" };
6748 v8::ExtensionConfiguration extensions(2, extension_names);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006749 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006750 Context::New(CcTest::isolate(), &extensions);
kasperl@chromium.org2d18d102009-04-15 13:27:32 +00006751 Context::Scope lock(context);
ager@chromium.org18ad94b2009-09-02 08:22:29 +00006752 v8::Handle<Value> result = Script::Compile(v8_str("UseWith1()"))->Run();
ulan@chromium.org0f13e742014-01-03 15:51:11 +00006753 CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 87));
ager@chromium.org18ad94b2009-09-02 08:22:29 +00006754 result = Script::Compile(v8_str("UseWith2()"))->Run();
ulan@chromium.org0f13e742014-01-03 15:51:11 +00006755 CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 87));
kasperl@chromium.org2d18d102009-04-15 13:27:32 +00006756}
6757
6758
machenbach@chromium.org09cae8d2014-01-30 01:05:27 +00006759TEST(AutoExtensions) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006760 v8::HandleScope handle_scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006761 Extension* extension = new Extension("autotest", kSimpleExtensionSource);
6762 extension->set_auto_enable(true);
6763 v8::RegisterExtension(extension);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006764 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006765 Context::New(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006766 Context::Scope lock(context);
6767 v8::Handle<Value> result = Script::Compile(v8_str("Foo()"))->Run();
ulan@chromium.org0f13e742014-01-03 15:51:11 +00006768 CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 4));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006769}
6770
6771
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00006772static const char* kSyntaxErrorInExtensionSource =
6773 "[";
6774
6775
6776// Test that a syntax error in an extension does not cause a fatal
6777// error but results in an empty context.
machenbach@chromium.org09cae8d2014-01-30 01:05:27 +00006778TEST(SyntaxErrorExtensions) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006779 v8::HandleScope handle_scope(CcTest::isolate());
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00006780 v8::RegisterExtension(new Extension("syntaxerror",
6781 kSyntaxErrorInExtensionSource));
6782 const char* extension_names[] = { "syntaxerror" };
6783 v8::ExtensionConfiguration extensions(1, extension_names);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006784 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006785 Context::New(CcTest::isolate(), &extensions);
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00006786 CHECK(context.IsEmpty());
6787}
6788
6789
6790static const char* kExceptionInExtensionSource =
6791 "throw 42";
6792
6793
6794// Test that an exception when installing an extension does not cause
6795// a fatal error but results in an empty context.
machenbach@chromium.org09cae8d2014-01-30 01:05:27 +00006796TEST(ExceptionExtensions) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006797 v8::HandleScope handle_scope(CcTest::isolate());
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00006798 v8::RegisterExtension(new Extension("exception",
6799 kExceptionInExtensionSource));
6800 const char* extension_names[] = { "exception" };
6801 v8::ExtensionConfiguration extensions(1, extension_names);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006802 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006803 Context::New(CcTest::isolate(), &extensions);
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00006804 CHECK(context.IsEmpty());
6805}
6806
6807
ager@chromium.org5b2fbee2010-09-08 06:38:15 +00006808static const char* kNativeCallInExtensionSource =
6809 "function call_runtime_last_index_of(x) {"
6810 " return %StringLastIndexOf(x, 'bob', 10);"
6811 "}";
6812
6813
6814static const char* kNativeCallTest =
6815 "call_runtime_last_index_of('bobbobboellebobboellebobbob');";
6816
6817// Test that a native runtime calls are supported in extensions.
machenbach@chromium.org09cae8d2014-01-30 01:05:27 +00006818TEST(NativeCallInExtensions) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006819 v8::HandleScope handle_scope(CcTest::isolate());
ager@chromium.org5b2fbee2010-09-08 06:38:15 +00006820 v8::RegisterExtension(new Extension("nativecall",
6821 kNativeCallInExtensionSource));
6822 const char* extension_names[] = { "nativecall" };
6823 v8::ExtensionConfiguration extensions(1, extension_names);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006824 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006825 Context::New(CcTest::isolate(), &extensions);
ager@chromium.org5b2fbee2010-09-08 06:38:15 +00006826 Context::Scope lock(context);
6827 v8::Handle<Value> result = Script::Compile(v8_str(kNativeCallTest))->Run();
ulan@chromium.org0f13e742014-01-03 15:51:11 +00006828 CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 3));
ager@chromium.org5b2fbee2010-09-08 06:38:15 +00006829}
6830
6831
whesse@chromium.org7b260152011-06-20 15:33:18 +00006832class NativeFunctionExtension : public Extension {
6833 public:
6834 NativeFunctionExtension(const char* name,
6835 const char* source,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00006836 v8::FunctionCallback fun = &Echo)
whesse@chromium.org7b260152011-06-20 15:33:18 +00006837 : Extension(name, source),
6838 function_(fun) { }
6839
machenbach@chromium.org9f18d912013-11-28 13:42:41 +00006840 virtual v8::Handle<v8::FunctionTemplate> GetNativeFunctionTemplate(
6841 v8::Isolate* isolate,
whesse@chromium.org7b260152011-06-20 15:33:18 +00006842 v8::Handle<v8::String> name) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00006843 return v8::FunctionTemplate::New(isolate, function_);
whesse@chromium.org7b260152011-06-20 15:33:18 +00006844 }
6845
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00006846 static void Echo(const v8::FunctionCallbackInfo<v8::Value>& args) {
6847 if (args.Length() >= 1) args.GetReturnValue().Set(args[0]);
whesse@chromium.org7b260152011-06-20 15:33:18 +00006848 }
6849 private:
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00006850 v8::FunctionCallback function_;
whesse@chromium.org7b260152011-06-20 15:33:18 +00006851};
6852
6853
machenbach@chromium.org09cae8d2014-01-30 01:05:27 +00006854TEST(NativeFunctionDeclaration) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006855 v8::HandleScope handle_scope(CcTest::isolate());
whesse@chromium.org7b260152011-06-20 15:33:18 +00006856 const char* name = "nativedecl";
6857 v8::RegisterExtension(new NativeFunctionExtension(name,
6858 "native function foo();"));
6859 const char* extension_names[] = { name };
6860 v8::ExtensionConfiguration extensions(1, extension_names);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006861 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006862 Context::New(CcTest::isolate(), &extensions);
whesse@chromium.org7b260152011-06-20 15:33:18 +00006863 Context::Scope lock(context);
6864 v8::Handle<Value> result = Script::Compile(v8_str("foo(42);"))->Run();
ulan@chromium.org0f13e742014-01-03 15:51:11 +00006865 CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 42));
whesse@chromium.org7b260152011-06-20 15:33:18 +00006866}
6867
6868
machenbach@chromium.org09cae8d2014-01-30 01:05:27 +00006869TEST(NativeFunctionDeclarationError) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006870 v8::HandleScope handle_scope(CcTest::isolate());
lrn@chromium.org67e236d2011-06-23 10:18:16 +00006871 const char* name = "nativedeclerr";
whesse@chromium.org7b260152011-06-20 15:33:18 +00006872 // Syntax error in extension code.
6873 v8::RegisterExtension(new NativeFunctionExtension(name,
6874 "native\nfunction foo();"));
6875 const char* extension_names[] = { name };
6876 v8::ExtensionConfiguration extensions(1, extension_names);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006877 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006878 Context::New(CcTest::isolate(), &extensions);
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00006879 CHECK(context.IsEmpty());
whesse@chromium.org7b260152011-06-20 15:33:18 +00006880}
6881
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00006882
machenbach@chromium.org09cae8d2014-01-30 01:05:27 +00006883TEST(NativeFunctionDeclarationErrorEscape) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006884 v8::HandleScope handle_scope(CcTest::isolate());
lrn@chromium.org67e236d2011-06-23 10:18:16 +00006885 const char* name = "nativedeclerresc";
whesse@chromium.org7b260152011-06-20 15:33:18 +00006886 // Syntax error in extension code - escape code in "native" means that
6887 // it's not treated as a keyword.
6888 v8::RegisterExtension(new NativeFunctionExtension(
6889 name,
6890 "nativ\\u0065 function foo();"));
6891 const char* extension_names[] = { name };
6892 v8::ExtensionConfiguration extensions(1, extension_names);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00006893 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006894 Context::New(CcTest::isolate(), &extensions);
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00006895 CHECK(context.IsEmpty());
whesse@chromium.org7b260152011-06-20 15:33:18 +00006896}
6897
6898
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006899static void CheckDependencies(const char* name, const char* expected) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006900 v8::HandleScope handle_scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006901 v8::ExtensionConfiguration config(1, &name);
6902 LocalContext context(&config);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00006903 CHECK_EQ(String::NewFromUtf8(CcTest::isolate(), expected),
6904 context->Global()->Get(v8_str("loaded")));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006905}
6906
6907
6908/*
6909 * Configuration:
6910 *
6911 * /-- B <--\
6912 * A <- -- D <-- E
6913 * \-- C <--/
6914 */
6915THREADED_TEST(ExtensionDependency) {
6916 static const char* kEDeps[] = { "D" };
6917 v8::RegisterExtension(new Extension("E", "this.loaded += 'E';", 1, kEDeps));
6918 static const char* kDDeps[] = { "B", "C" };
6919 v8::RegisterExtension(new Extension("D", "this.loaded += 'D';", 2, kDDeps));
6920 static const char* kBCDeps[] = { "A" };
6921 v8::RegisterExtension(new Extension("B", "this.loaded += 'B';", 1, kBCDeps));
6922 v8::RegisterExtension(new Extension("C", "this.loaded += 'C';", 1, kBCDeps));
6923 v8::RegisterExtension(new Extension("A", "this.loaded += 'A';"));
6924 CheckDependencies("A", "undefinedA");
6925 CheckDependencies("B", "undefinedAB");
6926 CheckDependencies("C", "undefinedAC");
6927 CheckDependencies("D", "undefinedABCD");
6928 CheckDependencies("E", "undefinedABCDE");
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006929 v8::HandleScope handle_scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006930 static const char* exts[2] = { "C", "E" };
6931 v8::ExtensionConfiguration config(2, exts);
6932 LocalContext context(&config);
6933 CHECK_EQ(v8_str("undefinedACBDE"), context->Global()->Get(v8_str("loaded")));
6934}
6935
6936
6937static const char* kExtensionTestScript =
6938 "native function A();"
6939 "native function B();"
6940 "native function C();"
6941 "function Foo(i) {"
6942 " if (i == 0) return A();"
6943 " if (i == 1) return B();"
6944 " if (i == 2) return C();"
6945 "}";
6946
6947
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00006948static void CallFun(const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006949 ApiTestFuzzer::Fuzz();
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00006950 if (args.IsConstructCall()) {
6951 args.This()->Set(v8_str("data"), args.Data());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00006952 args.GetReturnValue().SetNull();
6953 return;
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00006954 }
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00006955 args.GetReturnValue().Set(args.Data());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006956}
6957
6958
6959class FunctionExtension : public Extension {
6960 public:
6961 FunctionExtension() : Extension("functiontest", kExtensionTestScript) { }
machenbach@chromium.org9f18d912013-11-28 13:42:41 +00006962 virtual v8::Handle<v8::FunctionTemplate> GetNativeFunctionTemplate(
6963 v8::Isolate* isolate,
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006964 v8::Handle<String> name);
6965};
6966
6967
6968static int lookup_count = 0;
machenbach@chromium.org9f18d912013-11-28 13:42:41 +00006969v8::Handle<v8::FunctionTemplate> FunctionExtension::GetNativeFunctionTemplate(
6970 v8::Isolate* isolate, v8::Handle<String> name) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006971 lookup_count++;
6972 if (name->Equals(v8_str("A"))) {
ulan@chromium.org0f13e742014-01-03 15:51:11 +00006973 return v8::FunctionTemplate::New(
6974 isolate, CallFun, v8::Integer::New(isolate, 8));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006975 } else if (name->Equals(v8_str("B"))) {
ulan@chromium.org0f13e742014-01-03 15:51:11 +00006976 return v8::FunctionTemplate::New(
6977 isolate, CallFun, v8::Integer::New(isolate, 7));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006978 } else if (name->Equals(v8_str("C"))) {
ulan@chromium.org0f13e742014-01-03 15:51:11 +00006979 return v8::FunctionTemplate::New(
6980 isolate, CallFun, v8::Integer::New(isolate, 6));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006981 } else {
6982 return v8::Handle<v8::FunctionTemplate>();
6983 }
6984}
6985
6986
6987THREADED_TEST(FunctionLookup) {
6988 v8::RegisterExtension(new FunctionExtension());
machenbach@chromium.org528ce022013-09-23 14:09:36 +00006989 v8::HandleScope handle_scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00006990 static const char* exts[1] = { "functiontest" };
6991 v8::ExtensionConfiguration config(1, exts);
6992 LocalContext context(&config);
6993 CHECK_EQ(3, lookup_count);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00006994 CHECK_EQ(v8::Integer::New(CcTest::isolate(), 8),
6995 Script::Compile(v8_str("Foo(0)"))->Run());
6996 CHECK_EQ(v8::Integer::New(CcTest::isolate(), 7),
6997 Script::Compile(v8_str("Foo(1)"))->Run());
6998 CHECK_EQ(v8::Integer::New(CcTest::isolate(), 6),
6999 Script::Compile(v8_str("Foo(2)"))->Run());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007000}
7001
7002
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00007003THREADED_TEST(NativeFunctionConstructCall) {
7004 v8::RegisterExtension(new FunctionExtension());
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007005 v8::HandleScope handle_scope(CcTest::isolate());
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00007006 static const char* exts[1] = { "functiontest" };
7007 v8::ExtensionConfiguration config(1, exts);
7008 LocalContext context(&config);
7009 for (int i = 0; i < 10; i++) {
7010 // Run a few times to ensure that allocation of objects doesn't
7011 // change behavior of a constructor function.
ulan@chromium.org0f13e742014-01-03 15:51:11 +00007012 CHECK_EQ(v8::Integer::New(CcTest::isolate(), 8),
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00007013 Script::Compile(v8_str("(new A()).data"))->Run());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00007014 CHECK_EQ(v8::Integer::New(CcTest::isolate(), 7),
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00007015 Script::Compile(v8_str("(new B()).data"))->Run());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00007016 CHECK_EQ(v8::Integer::New(CcTest::isolate(), 6),
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00007017 Script::Compile(v8_str("(new C()).data"))->Run());
7018 }
7019}
7020
7021
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007022static const char* last_location;
7023static const char* last_message;
7024void StoringErrorCallback(const char* location, const char* message) {
7025 if (last_location == NULL) {
7026 last_location = location;
7027 last_message = message;
7028 }
7029}
7030
7031
7032// ErrorReporting creates a circular extensions configuration and
7033// tests that the fatal error handler gets called. This renders V8
7034// unusable and therefore this test cannot be run in parallel.
7035TEST(ErrorReporting) {
7036 v8::V8::SetFatalErrorHandler(StoringErrorCallback);
7037 static const char* aDeps[] = { "B" };
7038 v8::RegisterExtension(new Extension("A", "", 1, aDeps));
7039 static const char* bDeps[] = { "A" };
7040 v8::RegisterExtension(new Extension("B", "", 1, bDeps));
7041 last_location = NULL;
7042 v8::ExtensionConfiguration config(1, bDeps);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007043 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007044 Context::New(CcTest::isolate(), &config);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007045 CHECK(context.IsEmpty());
7046 CHECK_NE(last_location, NULL);
7047}
7048
7049
ager@chromium.org7c537e22008-10-16 08:43:32 +00007050static const char* js_code_causing_huge_string_flattening =
7051 "var str = 'X';"
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +00007052 "for (var i = 0; i < 30; i++) {"
ager@chromium.org7c537e22008-10-16 08:43:32 +00007053 " str = str + str;"
7054 "}"
7055 "str.match(/X/);";
7056
7057
ager@chromium.org7c537e22008-10-16 08:43:32 +00007058TEST(RegexpOutOfMemory) {
7059 // Execute a script that causes out of memory when flattening a string.
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007060 v8::HandleScope scope(CcTest::isolate());
ager@chromium.org7c537e22008-10-16 08:43:32 +00007061 v8::V8::SetFatalErrorHandler(OOMCallback);
7062 LocalContext context;
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00007063 Local<Script> script = Script::Compile(String::NewFromUtf8(
7064 CcTest::isolate(), js_code_causing_huge_string_flattening));
ager@chromium.org7c537e22008-10-16 08:43:32 +00007065 last_location = NULL;
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00007066 script->Run();
ager@chromium.org7c537e22008-10-16 08:43:32 +00007067
7068 CHECK(false); // Should not return.
7069}
7070
7071
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007072static void MissingScriptInfoMessageListener(v8::Handle<v8::Message> message,
7073 v8::Handle<Value> data) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00007074 CHECK(message->GetScriptResourceName()->IsUndefined());
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00007075 CHECK_EQ(v8::Undefined(CcTest::isolate()), message->GetScriptResourceName());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007076 message->GetLineNumber();
7077 message->GetSourceLine();
7078}
7079
7080
7081THREADED_TEST(ErrorWithMissingScriptInfo) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007082 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00007083 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007084 v8::V8::AddMessageListener(MissingScriptInfoMessageListener);
7085 Script::Compile(v8_str("throw Error()"))->Run();
7086 v8::V8::RemoveMessageListeners(MissingScriptInfoMessageListener);
7087}
7088
7089
7090int global_index = 0;
7091
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007092template<typename T>
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007093class Snorkel {
7094 public:
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007095 explicit Snorkel(v8::Persistent<T>* handle) : handle_(handle) {
7096 index_ = global_index++;
7097 }
7098 v8::Persistent<T>* handle_;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007099 int index_;
7100};
7101
7102class Whammy {
7103 public:
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00007104 explicit Whammy(v8::Isolate* isolate) : cursor_(0), isolate_(isolate) { }
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00007105 ~Whammy() { script_.Reset(); }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007106 v8::Handle<Script> getScript() {
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00007107 if (script_.IsEmpty()) script_.Reset(isolate_, v8_compile("({}).blammo"));
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00007108 return Local<Script>::New(isolate_, script_);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007109 }
7110
7111 public:
7112 static const int kObjectCount = 256;
7113 int cursor_;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +00007114 v8::Isolate* isolate_;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007115 v8::Persistent<v8::Object> objects_[kObjectCount];
7116 v8::Persistent<Script> script_;
7117};
7118
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007119static void HandleWeakReference(
7120 const v8::WeakCallbackData<v8::Value, Snorkel<v8::Value> >& data) {
7121 data.GetParameter()->handle_->ClearWeak();
7122 delete data.GetParameter();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007123}
7124
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007125void WhammyPropertyGetter(Local<String> name,
7126 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007127 Whammy* whammy =
7128 static_cast<Whammy*>(v8::Handle<v8::External>::Cast(info.Data())->Value());
7129
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00007130 v8::Persistent<v8::Object>& prev = whammy->objects_[whammy->cursor_];
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007131
ulan@chromium.org0f13e742014-01-03 15:51:11 +00007132 v8::Handle<v8::Object> obj = v8::Object::New(info.GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007133 if (!prev.IsEmpty()) {
rossberg@chromium.org79e79022013-06-03 15:43:46 +00007134 v8::Local<v8::Object>::New(info.GetIsolate(), prev)
7135 ->Set(v8_str("next"), obj);
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007136 prev.SetWeak<Value, Snorkel<Value> >(new Snorkel<Value>(&prev.As<Value>()),
7137 &HandleWeakReference);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007138 }
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +00007139 whammy->objects_[whammy->cursor_].Reset(info.GetIsolate(), obj);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007140 whammy->cursor_ = (whammy->cursor_ + 1) % Whammy::kObjectCount;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007141 info.GetReturnValue().Set(whammy->getScript()->Run());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007142}
7143
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00007144
machenbach@chromium.org09cae8d2014-01-30 01:05:27 +00007145TEST(WeakReference) {
machenbach@chromium.orgc8cbc432014-01-21 09:01:57 +00007146 i::FLAG_expose_gc = true;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00007147 v8::Isolate* isolate = CcTest::isolate();
7148 v8::HandleScope handle_scope(isolate);
7149 v8::Handle<v8::ObjectTemplate> templ= v8::ObjectTemplate::New(isolate);
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007150 Whammy* whammy = new Whammy(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007151 templ->SetNamedPropertyHandler(WhammyPropertyGetter,
7152 0, 0, 0, 0,
machenbach@chromium.org0cc09502013-11-13 12:20:55 +00007153 v8::External::New(CcTest::isolate(), whammy));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007154 const char* extension_list[] = { "v8/gc" };
7155 v8::ExtensionConfiguration extensions(1, extension_list);
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007156 v8::Handle<Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007157 Context::New(CcTest::isolate(), &extensions);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007158 Context::Scope context_scope(context);
7159
7160 v8::Handle<v8::Object> interceptor = templ->NewInstance();
7161 context->Global()->Set(v8_str("whammy"), interceptor);
7162 const char* code =
7163 "var last;"
7164 "for (var i = 0; i < 10000; i++) {"
7165 " var obj = whammy.length;"
7166 " if (last) last.next = obj;"
7167 " last = obj;"
7168 "}"
7169 "gc();"
7170 "4";
7171 v8::Handle<Value> result = CompileRun(code);
7172 CHECK_EQ(4.0, result->NumberValue());
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +00007173 delete whammy;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007174}
7175
7176
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007177struct FlagAndPersistent {
7178 bool flag;
7179 v8::Persistent<v8::Object> handle;
7180};
7181
7182
7183static void DisposeAndSetFlag(
7184 const v8::WeakCallbackData<v8::Object, FlagAndPersistent>& data) {
7185 data.GetParameter()->handle.Reset();
7186 data.GetParameter()->flag = true;
ager@chromium.orgc4c92722009-11-18 14:12:51 +00007187}
7188
ager@chromium.orgc4c92722009-11-18 14:12:51 +00007189
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007190THREADED_TEST(IndependentWeakHandle) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007191 v8::Isolate* iso = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007192 v8::HandleScope scope(iso);
7193 v8::Handle<Context> context = Context::New(iso);
ager@chromium.orgc4c92722009-11-18 14:12:51 +00007194 Context::Scope context_scope(context);
7195
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007196 FlagAndPersistent object_a, object_b;
ager@chromium.orgc4c92722009-11-18 14:12:51 +00007197
7198 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00007199 v8::HandleScope handle_scope(iso);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00007200 object_a.handle.Reset(iso, v8::Object::New(iso));
7201 object_b.handle.Reset(iso, v8::Object::New(iso));
ager@chromium.orgc4c92722009-11-18 14:12:51 +00007202 }
7203
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007204 object_a.flag = false;
7205 object_b.flag = false;
7206 object_a.handle.SetWeak(&object_a, &DisposeAndSetFlag);
7207 object_b.handle.SetWeak(&object_b, &DisposeAndSetFlag);
7208 CHECK(!object_b.handle.IsIndependent());
7209 object_a.handle.MarkIndependent();
7210 object_b.handle.MarkIndependent();
7211 CHECK(object_b.handle.IsIndependent());
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007212 CcTest::heap()->PerformScavenge();
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007213 CHECK(object_a.flag);
7214 CHECK(object_b.flag);
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007215}
ager@chromium.orgc4c92722009-11-18 14:12:51 +00007216
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007217
7218static void InvokeScavenge() {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007219 CcTest::heap()->PerformScavenge();
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007220}
7221
7222
7223static void InvokeMarkSweep() {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007224 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007225}
7226
7227
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007228static void ForceScavenge(
7229 const v8::WeakCallbackData<v8::Object, FlagAndPersistent>& data) {
7230 data.GetParameter()->handle.Reset();
7231 data.GetParameter()->flag = true;
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007232 InvokeScavenge();
7233}
7234
7235
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007236static void ForceMarkSweep(
7237 const v8::WeakCallbackData<v8::Object, FlagAndPersistent>& data) {
7238 data.GetParameter()->handle.Reset();
7239 data.GetParameter()->flag = true;
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007240 InvokeMarkSweep();
7241}
7242
7243
7244THREADED_TEST(GCFromWeakCallbacks) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007245 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007246 v8::HandleScope scope(isolate);
7247 v8::Handle<Context> context = Context::New(isolate);
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007248 Context::Scope context_scope(context);
7249
7250 static const int kNumberOfGCTypes = 2;
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007251 typedef v8::WeakCallbackData<v8::Object, FlagAndPersistent>::Callback
7252 Callback;
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007253 Callback gc_forcing_callback[kNumberOfGCTypes] =
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007254 {&ForceScavenge, &ForceMarkSweep};
7255
7256 typedef void (*GCInvoker)();
7257 GCInvoker invoke_gc[kNumberOfGCTypes] = {&InvokeScavenge, &InvokeMarkSweep};
7258
7259 for (int outer_gc = 0; outer_gc < kNumberOfGCTypes; outer_gc++) {
7260 for (int inner_gc = 0; inner_gc < kNumberOfGCTypes; inner_gc++) {
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007261 FlagAndPersistent object;
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007262 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00007263 v8::HandleScope handle_scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00007264 object.handle.Reset(isolate, v8::Object::New(isolate));
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007265 }
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007266 object.flag = false;
7267 object.handle.SetWeak(&object, gc_forcing_callback[inner_gc]);
7268 object.handle.MarkIndependent();
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007269 invoke_gc[outer_gc]();
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007270 CHECK(object.flag);
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007271 }
ager@chromium.orgc4c92722009-11-18 14:12:51 +00007272 }
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007273}
7274
7275
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007276static void RevivingCallback(
7277 const v8::WeakCallbackData<v8::Object, FlagAndPersistent>& data) {
7278 data.GetParameter()->handle.ClearWeak();
7279 data.GetParameter()->flag = true;
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007280}
7281
7282
7283THREADED_TEST(IndependentHandleRevival) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007284 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007285 v8::HandleScope scope(isolate);
7286 v8::Handle<Context> context = Context::New(isolate);
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007287 Context::Scope context_scope(context);
7288
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007289 FlagAndPersistent object;
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007290 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00007291 v8::HandleScope handle_scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00007292 v8::Local<v8::Object> o = v8::Object::New(isolate);
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007293 object.handle.Reset(isolate, o);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00007294 o->Set(v8_str("x"), v8::Integer::New(isolate, 1));
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007295 v8::Local<String> y_str = v8_str("y");
rossberg@chromium.org79e79022013-06-03 15:43:46 +00007296 o->Set(y_str, y_str);
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007297 }
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007298 object.flag = false;
7299 object.handle.SetWeak(&object, &RevivingCallback);
7300 object.handle.MarkIndependent();
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007301 CcTest::heap()->PerformScavenge();
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007302 CHECK(object.flag);
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007303 CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007304 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00007305 v8::HandleScope handle_scope(isolate);
machenbach@chromium.orgddf38112013-12-04 09:42:52 +00007306 v8::Local<v8::Object> o =
7307 v8::Local<v8::Object>::New(isolate, object.handle);
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007308 v8::Local<String> y_str = v8_str("y");
ulan@chromium.org0f13e742014-01-03 15:51:11 +00007309 CHECK_EQ(v8::Integer::New(isolate, 1), o->Get(v8_str("x")));
rossberg@chromium.org79e79022013-06-03 15:43:46 +00007310 CHECK(o->Get(y_str)->Equals(y_str));
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +00007311 }
ager@chromium.orgc4c92722009-11-18 14:12:51 +00007312}
7313
7314
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007315v8::Handle<Function> args_fun;
7316
7317
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007318static void ArgumentsTestCallback(
7319 const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007320 ApiTestFuzzer::Fuzz();
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00007321 v8::Isolate* isolate = args.GetIsolate();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007322 CHECK_EQ(args_fun, args.Callee());
7323 CHECK_EQ(3, args.Length());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00007324 CHECK_EQ(v8::Integer::New(isolate, 1), args[0]);
7325 CHECK_EQ(v8::Integer::New(isolate, 2), args[1]);
7326 CHECK_EQ(v8::Integer::New(isolate, 3), args[2]);
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00007327 CHECK_EQ(v8::Undefined(isolate), args[3]);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00007328 v8::HandleScope scope(args.GetIsolate());
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007329 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007330}
7331
7332
7333THREADED_TEST(Arguments) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00007334 v8::Isolate* isolate = CcTest::isolate();
7335 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00007336 v8::Handle<v8::ObjectTemplate> global = ObjectTemplate::New(isolate);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00007337 global->Set(v8_str("f"),
7338 v8::FunctionTemplate::New(isolate, ArgumentsTestCallback));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007339 LocalContext context(NULL, global);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00007340 args_fun = context->Global()->Get(v8_str("f")).As<Function>();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007341 v8_compile("f(1, 2, 3)")->Run();
7342}
7343
7344
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007345static void NoBlockGetterX(Local<String> name,
7346 const v8::PropertyCallbackInfo<v8::Value>&) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007347}
7348
7349
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007350static void NoBlockGetterI(uint32_t index,
7351 const v8::PropertyCallbackInfo<v8::Value>&) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007352}
7353
7354
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007355static void PDeleter(Local<String> name,
7356 const v8::PropertyCallbackInfo<v8::Boolean>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007357 if (!name->Equals(v8_str("foo"))) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007358 return; // not intercepted
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007359 }
7360
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007361 info.GetReturnValue().Set(false); // intercepted, don't delete the property
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007362}
7363
7364
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007365static void IDeleter(uint32_t index,
7366 const v8::PropertyCallbackInfo<v8::Boolean>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007367 if (index != 2) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007368 return; // not intercepted
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007369 }
7370
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007371 info.GetReturnValue().Set(false); // intercepted, don't delete the property
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007372}
7373
7374
7375THREADED_TEST(Deleter) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00007376 v8::Isolate* isolate = CcTest::isolate();
7377 v8::HandleScope scope(isolate);
7378 v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007379 obj->SetNamedPropertyHandler(NoBlockGetterX, NULL, NULL, PDeleter, NULL);
7380 obj->SetIndexedPropertyHandler(NoBlockGetterI, NULL, NULL, IDeleter, NULL);
7381 LocalContext context;
7382 context->Global()->Set(v8_str("k"), obj->NewInstance());
7383 CompileRun(
7384 "k.foo = 'foo';"
7385 "k.bar = 'bar';"
7386 "k[2] = 2;"
7387 "k[4] = 4;");
7388 CHECK(v8_compile("delete k.foo")->Run()->IsFalse());
7389 CHECK(v8_compile("delete k.bar")->Run()->IsTrue());
7390
7391 CHECK_EQ(v8_compile("k.foo")->Run(), v8_str("foo"));
7392 CHECK(v8_compile("k.bar")->Run()->IsUndefined());
7393
7394 CHECK(v8_compile("delete k[2]")->Run()->IsFalse());
7395 CHECK(v8_compile("delete k[4]")->Run()->IsTrue());
7396
7397 CHECK_EQ(v8_compile("k[2]")->Run(), v8_num(2));
7398 CHECK(v8_compile("k[4]")->Run()->IsUndefined());
7399}
7400
7401
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007402static void GetK(Local<String> name,
7403 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007404 ApiTestFuzzer::Fuzz();
ager@chromium.org65dad4b2009-04-23 08:48:43 +00007405 if (name->Equals(v8_str("foo")) ||
7406 name->Equals(v8_str("bar")) ||
7407 name->Equals(v8_str("baz"))) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007408 info.GetReturnValue().SetUndefined();
ager@chromium.org65dad4b2009-04-23 08:48:43 +00007409 }
ager@chromium.org65dad4b2009-04-23 08:48:43 +00007410}
7411
7412
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007413static void IndexedGetK(uint32_t index,
7414 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.org65dad4b2009-04-23 08:48:43 +00007415 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007416 if (index == 0 || index == 1) info.GetReturnValue().SetUndefined();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007417}
7418
7419
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007420static void NamedEnum(const v8::PropertyCallbackInfo<v8::Array>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007421 ApiTestFuzzer::Fuzz();
machenbach@chromium.org9f18d912013-11-28 13:42:41 +00007422 v8::Handle<v8::Array> result = v8::Array::New(info.GetIsolate(), 3);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00007423 result->Set(v8::Integer::New(info.GetIsolate(), 0), v8_str("foo"));
7424 result->Set(v8::Integer::New(info.GetIsolate(), 1), v8_str("bar"));
7425 result->Set(v8::Integer::New(info.GetIsolate(), 2), v8_str("baz"));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007426 info.GetReturnValue().Set(result);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007427}
7428
7429
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007430static void IndexedEnum(const v8::PropertyCallbackInfo<v8::Array>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007431 ApiTestFuzzer::Fuzz();
machenbach@chromium.org9f18d912013-11-28 13:42:41 +00007432 v8::Handle<v8::Array> result = v8::Array::New(info.GetIsolate(), 2);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00007433 result->Set(v8::Integer::New(info.GetIsolate(), 0), v8_str("0"));
7434 result->Set(v8::Integer::New(info.GetIsolate(), 1), v8_str("1"));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007435 info.GetReturnValue().Set(result);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007436}
7437
7438
7439THREADED_TEST(Enumerators) {
ulan@chromium.org0f13e742014-01-03 15:51:11 +00007440 v8::Isolate* isolate = CcTest::isolate();
7441 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00007442 v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007443 obj->SetNamedPropertyHandler(GetK, NULL, NULL, NULL, NamedEnum);
ager@chromium.org65dad4b2009-04-23 08:48:43 +00007444 obj->SetIndexedPropertyHandler(IndexedGetK, NULL, NULL, NULL, IndexedEnum);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007445 LocalContext context;
7446 context->Global()->Set(v8_str("k"), obj->NewInstance());
7447 v8::Handle<v8::Array> result = v8::Handle<v8::Array>::Cast(CompileRun(
ager@chromium.org65dad4b2009-04-23 08:48:43 +00007448 "k[10] = 0;"
7449 "k.a = 0;"
7450 "k[5] = 0;"
7451 "k.b = 0;"
7452 "k[4294967295] = 0;"
7453 "k.c = 0;"
7454 "k[4294967296] = 0;"
7455 "k.d = 0;"
7456 "k[140000] = 0;"
7457 "k.e = 0;"
7458 "k[30000000000] = 0;"
7459 "k.f = 0;"
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007460 "var result = [];"
7461 "for (var prop in k) {"
7462 " result.push(prop);"
7463 "}"
7464 "result"));
ager@chromium.org65dad4b2009-04-23 08:48:43 +00007465 // Check that we get all the property names returned including the
7466 // ones from the enumerators in the right order: indexed properties
7467 // in numerical order, indexed interceptor properties, named
7468 // properties in insertion order, named interceptor properties.
7469 // This order is not mandated by the spec, so this test is just
7470 // documenting our behavior.
7471 CHECK_EQ(17, result->Length());
7472 // Indexed properties in numerical order.
ulan@chromium.org0f13e742014-01-03 15:51:11 +00007473 CHECK_EQ(v8_str("5"), result->Get(v8::Integer::New(isolate, 0)));
7474 CHECK_EQ(v8_str("10"), result->Get(v8::Integer::New(isolate, 1)));
7475 CHECK_EQ(v8_str("140000"), result->Get(v8::Integer::New(isolate, 2)));
7476 CHECK_EQ(v8_str("4294967295"), result->Get(v8::Integer::New(isolate, 3)));
ager@chromium.org65dad4b2009-04-23 08:48:43 +00007477 // Indexed interceptor properties in the order they are returned
7478 // from the enumerator interceptor.
ulan@chromium.org0f13e742014-01-03 15:51:11 +00007479 CHECK_EQ(v8_str("0"), result->Get(v8::Integer::New(isolate, 4)));
7480 CHECK_EQ(v8_str("1"), result->Get(v8::Integer::New(isolate, 5)));
ager@chromium.org65dad4b2009-04-23 08:48:43 +00007481 // Named properties in insertion order.
ulan@chromium.org0f13e742014-01-03 15:51:11 +00007482 CHECK_EQ(v8_str("a"), result->Get(v8::Integer::New(isolate, 6)));
7483 CHECK_EQ(v8_str("b"), result->Get(v8::Integer::New(isolate, 7)));
7484 CHECK_EQ(v8_str("c"), result->Get(v8::Integer::New(isolate, 8)));
7485 CHECK_EQ(v8_str("4294967296"), result->Get(v8::Integer::New(isolate, 9)));
7486 CHECK_EQ(v8_str("d"), result->Get(v8::Integer::New(isolate, 10)));
7487 CHECK_EQ(v8_str("e"), result->Get(v8::Integer::New(isolate, 11)));
7488 CHECK_EQ(v8_str("30000000000"), result->Get(v8::Integer::New(isolate, 12)));
7489 CHECK_EQ(v8_str("f"), result->Get(v8::Integer::New(isolate, 13)));
ager@chromium.org65dad4b2009-04-23 08:48:43 +00007490 // Named interceptor properties.
ulan@chromium.org0f13e742014-01-03 15:51:11 +00007491 CHECK_EQ(v8_str("foo"), result->Get(v8::Integer::New(isolate, 14)));
7492 CHECK_EQ(v8_str("bar"), result->Get(v8::Integer::New(isolate, 15)));
7493 CHECK_EQ(v8_str("baz"), result->Get(v8::Integer::New(isolate, 16)));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007494}
7495
7496
7497int p_getter_count;
7498int p_getter_count2;
7499
7500
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007501static void PGetter(Local<String> name,
7502 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007503 ApiTestFuzzer::Fuzz();
7504 p_getter_count++;
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007505 v8::Handle<v8::Object> global =
7506 info.GetIsolate()->GetCurrentContext()->Global();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007507 CHECK_EQ(info.Holder(), global->Get(v8_str("o1")));
7508 if (name->Equals(v8_str("p1"))) {
7509 CHECK_EQ(info.This(), global->Get(v8_str("o1")));
7510 } else if (name->Equals(v8_str("p2"))) {
7511 CHECK_EQ(info.This(), global->Get(v8_str("o2")));
7512 } else if (name->Equals(v8_str("p3"))) {
7513 CHECK_EQ(info.This(), global->Get(v8_str("o3")));
7514 } else if (name->Equals(v8_str("p4"))) {
7515 CHECK_EQ(info.This(), global->Get(v8_str("o4")));
7516 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007517}
7518
7519
7520static void RunHolderTest(v8::Handle<v8::ObjectTemplate> obj) {
7521 ApiTestFuzzer::Fuzz();
7522 LocalContext context;
7523 context->Global()->Set(v8_str("o1"), obj->NewInstance());
7524 CompileRun(
7525 "o1.__proto__ = { };"
7526 "var o2 = { __proto__: o1 };"
7527 "var o3 = { __proto__: o2 };"
7528 "var o4 = { __proto__: o3 };"
7529 "for (var i = 0; i < 10; i++) o4.p4;"
7530 "for (var i = 0; i < 10; i++) o3.p3;"
7531 "for (var i = 0; i < 10; i++) o2.p2;"
7532 "for (var i = 0; i < 10; i++) o1.p1;");
7533}
7534
7535
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00007536static void PGetter2(Local<String> name,
7537 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007538 ApiTestFuzzer::Fuzz();
7539 p_getter_count2++;
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007540 v8::Handle<v8::Object> global =
7541 info.GetIsolate()->GetCurrentContext()->Global();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007542 CHECK_EQ(info.Holder(), global->Get(v8_str("o1")));
7543 if (name->Equals(v8_str("p1"))) {
7544 CHECK_EQ(info.This(), global->Get(v8_str("o1")));
7545 } else if (name->Equals(v8_str("p2"))) {
7546 CHECK_EQ(info.This(), global->Get(v8_str("o2")));
7547 } else if (name->Equals(v8_str("p3"))) {
7548 CHECK_EQ(info.This(), global->Get(v8_str("o3")));
7549 } else if (name->Equals(v8_str("p4"))) {
7550 CHECK_EQ(info.This(), global->Get(v8_str("o4")));
7551 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007552}
7553
7554
7555THREADED_TEST(GetterHolders) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00007556 v8::Isolate* isolate = CcTest::isolate();
7557 v8::HandleScope scope(isolate);
7558 v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007559 obj->SetAccessor(v8_str("p1"), PGetter);
7560 obj->SetAccessor(v8_str("p2"), PGetter);
7561 obj->SetAccessor(v8_str("p3"), PGetter);
7562 obj->SetAccessor(v8_str("p4"), PGetter);
7563 p_getter_count = 0;
7564 RunHolderTest(obj);
7565 CHECK_EQ(40, p_getter_count);
7566}
7567
7568
7569THREADED_TEST(PreInterceptorHolders) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00007570 v8::Isolate* isolate = CcTest::isolate();
7571 v8::HandleScope scope(isolate);
7572 v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007573 obj->SetNamedPropertyHandler(PGetter2);
7574 p_getter_count2 = 0;
7575 RunHolderTest(obj);
7576 CHECK_EQ(40, p_getter_count2);
7577}
7578
7579
7580THREADED_TEST(ObjectInstantiation) {
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00007581 v8::Isolate* isolate = CcTest::isolate();
7582 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00007583 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007584 templ->SetAccessor(v8_str("t"), PGetter2);
7585 LocalContext context;
7586 context->Global()->Set(v8_str("o"), templ->NewInstance());
7587 for (int i = 0; i < 100; i++) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007588 v8::HandleScope inner_scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007589 v8::Handle<v8::Object> obj = templ->NewInstance();
7590 CHECK_NE(obj, context->Global()->Get(v8_str("o")));
7591 context->Global()->Set(v8_str("o2"), obj);
7592 v8::Handle<Value> value =
7593 Script::Compile(v8_str("o.__proto__ === o2.__proto__"))->Run();
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +00007594 CHECK_EQ(v8::True(isolate), value);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007595 context->Global()->Set(v8_str("o"), obj);
7596 }
7597}
7598
7599
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007600static int StrCmp16(uint16_t* a, uint16_t* b) {
7601 while (true) {
7602 if (*a == 0 && *b == 0) return 0;
7603 if (*a != *b) return 0 + *a - *b;
7604 a++;
7605 b++;
7606 }
7607}
7608
7609
7610static int StrNCmp16(uint16_t* a, uint16_t* b, int n) {
7611 while (true) {
7612 if (n-- == 0) return 0;
7613 if (*a == 0 && *b == 0) return 0;
7614 if (*a != *b) return 0 + *a - *b;
7615 a++;
7616 b++;
7617 }
7618}
7619
7620
yangguo@chromium.org154ff992012-03-13 08:09:54 +00007621int GetUtf8Length(Handle<String> str) {
7622 int len = str->Utf8Length();
7623 if (len < 0) {
7624 i::Handle<i::String> istr(v8::Utils::OpenHandle(*str));
7625 i::FlattenString(istr);
7626 len = str->Utf8Length();
7627 }
7628 return len;
7629}
7630
7631
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007632THREADED_TEST(StringWrite) {
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007633 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00007634 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007635 v8::Handle<String> str = v8_str("abcde");
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007636 // abc<Icelandic eth><Unicode snowman>.
7637 v8::Handle<String> str2 = v8_str("abc\303\260\342\230\203");
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00007638 v8::Handle<String> str3 = v8::String::NewFromUtf8(
7639 context->GetIsolate(), "abc\0def", v8::String::kNormalString, 7);
machenbach@chromium.orgc8cbc432014-01-21 09:01:57 +00007640 // "ab" + lead surrogate + "cd" + trail surrogate + "ef"
7641 uint16_t orphans[8] = { 0x61, 0x62, 0xd800, 0x63, 0x64, 0xdc00, 0x65, 0x66 };
7642 v8::Handle<String> orphans_str = v8::String::NewFromTwoByte(
7643 context->GetIsolate(), orphans, v8::String::kNormalString, 8);
7644 // single lead surrogate
7645 uint16_t lead[1] = { 0xd800 };
7646 v8::Handle<String> lead_str = v8::String::NewFromTwoByte(
7647 context->GetIsolate(), lead, v8::String::kNormalString, 1);
7648 // single trail surrogate
7649 uint16_t trail[1] = { 0xdc00 };
7650 v8::Handle<String> trail_str = v8::String::NewFromTwoByte(
7651 context->GetIsolate(), trail, v8::String::kNormalString, 1);
7652 // surrogate pair
7653 uint16_t pair[2] = { 0xd800, 0xdc00 };
7654 v8::Handle<String> pair_str = v8::String::NewFromTwoByte(
7655 context->GetIsolate(), pair, v8::String::kNormalString, 2);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007656 const int kStride = 4; // Must match stride in for loops in JS below.
7657 CompileRun(
7658 "var left = '';"
7659 "for (var i = 0; i < 0xd800; i += 4) {"
7660 " left = left + String.fromCharCode(i);"
7661 "}");
7662 CompileRun(
7663 "var right = '';"
7664 "for (var i = 0; i < 0xd800; i += 4) {"
7665 " right = String.fromCharCode(i) + right;"
7666 "}");
machenbach@chromium.org528ce022013-09-23 14:09:36 +00007667 v8::Handle<v8::Object> global = context->Global();
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007668 Handle<String> left_tree = global->Get(v8_str("left")).As<String>();
7669 Handle<String> right_tree = global->Get(v8_str("right")).As<String>();
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007670
7671 CHECK_EQ(5, str2->Length());
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007672 CHECK_EQ(0xd800 / kStride, left_tree->Length());
7673 CHECK_EQ(0xd800 / kStride, right_tree->Length());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007674
7675 char buf[100];
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007676 char utf8buf[0xd800 * 3];
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007677 uint16_t wbuf[100];
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007678 int len;
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007679 int charlen;
7680
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007681 memset(utf8buf, 0x1, 1000);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007682 len = str2->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007683 CHECK_EQ(9, len);
7684 CHECK_EQ(5, charlen);
7685 CHECK_EQ(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007686
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007687 memset(utf8buf, 0x1, 1000);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007688 len = str2->WriteUtf8(utf8buf, 8, &charlen);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007689 CHECK_EQ(8, len);
7690 CHECK_EQ(5, charlen);
7691 CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\342\230\203\1", 9));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007692
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007693 memset(utf8buf, 0x1, 1000);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007694 len = str2->WriteUtf8(utf8buf, 7, &charlen);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007695 CHECK_EQ(5, len);
7696 CHECK_EQ(4, charlen);
7697 CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007698
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007699 memset(utf8buf, 0x1, 1000);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007700 len = str2->WriteUtf8(utf8buf, 6, &charlen);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007701 CHECK_EQ(5, len);
7702 CHECK_EQ(4, charlen);
7703 CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007704
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007705 memset(utf8buf, 0x1, 1000);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007706 len = str2->WriteUtf8(utf8buf, 5, &charlen);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007707 CHECK_EQ(5, len);
7708 CHECK_EQ(4, charlen);
7709 CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007710
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007711 memset(utf8buf, 0x1, 1000);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007712 len = str2->WriteUtf8(utf8buf, 4, &charlen);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007713 CHECK_EQ(3, len);
7714 CHECK_EQ(3, charlen);
7715 CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007716
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007717 memset(utf8buf, 0x1, 1000);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007718 len = str2->WriteUtf8(utf8buf, 3, &charlen);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007719 CHECK_EQ(3, len);
7720 CHECK_EQ(3, charlen);
7721 CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007722
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007723 memset(utf8buf, 0x1, 1000);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007724 len = str2->WriteUtf8(utf8buf, 2, &charlen);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007725 CHECK_EQ(2, len);
7726 CHECK_EQ(2, charlen);
7727 CHECK_EQ(0, strncmp(utf8buf, "ab\1", 3));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007728
machenbach@chromium.orgc8cbc432014-01-21 09:01:57 +00007729 // allow orphan surrogates by default
7730 memset(utf8buf, 0x1, 1000);
7731 len = orphans_str->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen);
7732 CHECK_EQ(13, len);
7733 CHECK_EQ(8, charlen);
7734 CHECK_EQ(0, strcmp(utf8buf, "ab\355\240\200cd\355\260\200ef"));
7735
7736 // replace orphan surrogates with unicode replacement character
7737 memset(utf8buf, 0x1, 1000);
7738 len = orphans_str->WriteUtf8(utf8buf,
7739 sizeof(utf8buf),
7740 &charlen,
7741 String::REPLACE_INVALID_UTF8);
7742 CHECK_EQ(13, len);
7743 CHECK_EQ(8, charlen);
7744 CHECK_EQ(0, strcmp(utf8buf, "ab\357\277\275cd\357\277\275ef"));
7745
7746 // replace single lead surrogate with unicode replacement character
7747 memset(utf8buf, 0x1, 1000);
7748 len = lead_str->WriteUtf8(utf8buf,
7749 sizeof(utf8buf),
7750 &charlen,
7751 String::REPLACE_INVALID_UTF8);
7752 CHECK_EQ(4, len);
7753 CHECK_EQ(1, charlen);
7754 CHECK_EQ(0, strcmp(utf8buf, "\357\277\275"));
7755
7756 // replace single trail surrogate with unicode replacement character
7757 memset(utf8buf, 0x1, 1000);
7758 len = trail_str->WriteUtf8(utf8buf,
7759 sizeof(utf8buf),
7760 &charlen,
7761 String::REPLACE_INVALID_UTF8);
7762 CHECK_EQ(4, len);
7763 CHECK_EQ(1, charlen);
7764 CHECK_EQ(0, strcmp(utf8buf, "\357\277\275"));
7765
7766 // do not replace / write anything if surrogate pair does not fit the buffer
7767 // space
7768 memset(utf8buf, 0x1, 1000);
7769 len = pair_str->WriteUtf8(utf8buf,
7770 3,
7771 &charlen,
7772 String::REPLACE_INVALID_UTF8);
7773 CHECK_EQ(0, len);
7774 CHECK_EQ(0, charlen);
7775
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007776 memset(utf8buf, 0x1, sizeof(utf8buf));
yangguo@chromium.org154ff992012-03-13 08:09:54 +00007777 len = GetUtf8Length(left_tree);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007778 int utf8_expected =
7779 (0x80 + (0x800 - 0x80) * 2 + (0xd800 - 0x800) * 3) / kStride;
7780 CHECK_EQ(utf8_expected, len);
7781 len = left_tree->WriteUtf8(utf8buf, utf8_expected, &charlen);
7782 CHECK_EQ(utf8_expected, len);
7783 CHECK_EQ(0xd800 / kStride, charlen);
7784 CHECK_EQ(0xed, static_cast<unsigned char>(utf8buf[utf8_expected - 3]));
7785 CHECK_EQ(0x9f, static_cast<unsigned char>(utf8buf[utf8_expected - 2]));
7786 CHECK_EQ(0xc0 - kStride,
7787 static_cast<unsigned char>(utf8buf[utf8_expected - 1]));
7788 CHECK_EQ(1, utf8buf[utf8_expected]);
7789
7790 memset(utf8buf, 0x1, sizeof(utf8buf));
yangguo@chromium.org154ff992012-03-13 08:09:54 +00007791 len = GetUtf8Length(right_tree);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +00007792 CHECK_EQ(utf8_expected, len);
7793 len = right_tree->WriteUtf8(utf8buf, utf8_expected, &charlen);
7794 CHECK_EQ(utf8_expected, len);
7795 CHECK_EQ(0xd800 / kStride, charlen);
7796 CHECK_EQ(0xed, static_cast<unsigned char>(utf8buf[0]));
7797 CHECK_EQ(0x9f, static_cast<unsigned char>(utf8buf[1]));
7798 CHECK_EQ(0xc0 - kStride, static_cast<unsigned char>(utf8buf[2]));
7799 CHECK_EQ(1, utf8buf[utf8_expected]);
7800
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007801 memset(buf, 0x1, sizeof(buf));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007802 memset(wbuf, 0x1, sizeof(wbuf));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007803 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf));
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007804 CHECK_EQ(5, len);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007805 len = str->Write(wbuf);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007806 CHECK_EQ(5, len);
7807 CHECK_EQ(0, strcmp("abcde", buf));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007808 uint16_t answer1[] = {'a', 'b', 'c', 'd', 'e', '\0'};
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007809 CHECK_EQ(0, StrCmp16(answer1, wbuf));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007810
7811 memset(buf, 0x1, sizeof(buf));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007812 memset(wbuf, 0x1, sizeof(wbuf));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007813 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 4);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007814 CHECK_EQ(4, len);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007815 len = str->Write(wbuf, 0, 4);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007816 CHECK_EQ(4, len);
7817 CHECK_EQ(0, strncmp("abcd\1", buf, 5));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007818 uint16_t answer2[] = {'a', 'b', 'c', 'd', 0x101};
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007819 CHECK_EQ(0, StrNCmp16(answer2, wbuf, 5));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007820
7821 memset(buf, 0x1, sizeof(buf));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007822 memset(wbuf, 0x1, sizeof(wbuf));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007823 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 5);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007824 CHECK_EQ(5, len);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007825 len = str->Write(wbuf, 0, 5);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007826 CHECK_EQ(5, len);
7827 CHECK_EQ(0, strncmp("abcde\1", buf, 6));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007828 uint16_t answer3[] = {'a', 'b', 'c', 'd', 'e', 0x101};
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007829 CHECK_EQ(0, StrNCmp16(answer3, wbuf, 6));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007830
7831 memset(buf, 0x1, sizeof(buf));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007832 memset(wbuf, 0x1, sizeof(wbuf));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007833 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 6);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007834 CHECK_EQ(5, len);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007835 len = str->Write(wbuf, 0, 6);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007836 CHECK_EQ(5, len);
7837 CHECK_EQ(0, strcmp("abcde", buf));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007838 uint16_t answer4[] = {'a', 'b', 'c', 'd', 'e', '\0'};
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007839 CHECK_EQ(0, StrCmp16(answer4, wbuf));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007840
7841 memset(buf, 0x1, sizeof(buf));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007842 memset(wbuf, 0x1, sizeof(wbuf));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007843 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, -1);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007844 CHECK_EQ(1, len);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007845 len = str->Write(wbuf, 4, -1);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007846 CHECK_EQ(1, len);
7847 CHECK_EQ(0, strcmp("e", buf));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007848 uint16_t answer5[] = {'e', '\0'};
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007849 CHECK_EQ(0, StrCmp16(answer5, wbuf));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007850
7851 memset(buf, 0x1, sizeof(buf));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007852 memset(wbuf, 0x1, sizeof(wbuf));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007853 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, 6);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007854 CHECK_EQ(1, len);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007855 len = str->Write(wbuf, 4, 6);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007856 CHECK_EQ(1, len);
7857 CHECK_EQ(0, strcmp("e", buf));
7858 CHECK_EQ(0, StrCmp16(answer5, wbuf));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007859
7860 memset(buf, 0x1, sizeof(buf));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007861 memset(wbuf, 0x1, sizeof(wbuf));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007862 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, 1);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007863 CHECK_EQ(1, len);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007864 len = str->Write(wbuf, 4, 1);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007865 CHECK_EQ(1, len);
7866 CHECK_EQ(0, strncmp("e\1", buf, 2));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007867 uint16_t answer6[] = {'e', 0x101};
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007868 CHECK_EQ(0, StrNCmp16(answer6, wbuf, 2));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007869
7870 memset(buf, 0x1, sizeof(buf));
7871 memset(wbuf, 0x1, sizeof(wbuf));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007872 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 3, 1);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007873 CHECK_EQ(1, len);
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007874 len = str->Write(wbuf, 3, 1);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007875 CHECK_EQ(1, len);
7876 CHECK_EQ(0, strncmp("d\1", buf, 2));
ager@chromium.org5f0c45f2010-12-17 08:51:21 +00007877 uint16_t answer7[] = {'d', 0x101};
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00007878 CHECK_EQ(0, StrNCmp16(answer7, wbuf, 2));
ricow@chromium.orgddd545c2011-08-24 12:02:41 +00007879
7880 memset(wbuf, 0x1, sizeof(wbuf));
7881 wbuf[5] = 'X';
7882 len = str->Write(wbuf, 0, 6, String::NO_NULL_TERMINATION);
7883 CHECK_EQ(5, len);
7884 CHECK_EQ('X', wbuf[5]);
7885 uint16_t answer8a[] = {'a', 'b', 'c', 'd', 'e'};
7886 uint16_t answer8b[] = {'a', 'b', 'c', 'd', 'e', '\0'};
7887 CHECK_EQ(0, StrNCmp16(answer8a, wbuf, 5));
7888 CHECK_NE(0, StrCmp16(answer8b, wbuf));
7889 wbuf[5] = '\0';
7890 CHECK_EQ(0, StrCmp16(answer8b, wbuf));
7891
7892 memset(buf, 0x1, sizeof(buf));
7893 buf[5] = 'X';
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007894 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf),
7895 0,
7896 6,
7897 String::NO_NULL_TERMINATION);
ricow@chromium.orgddd545c2011-08-24 12:02:41 +00007898 CHECK_EQ(5, len);
7899 CHECK_EQ('X', buf[5]);
7900 CHECK_EQ(0, strncmp("abcde", buf, 5));
7901 CHECK_NE(0, strcmp("abcde", buf));
7902 buf[5] = '\0';
7903 CHECK_EQ(0, strcmp("abcde", buf));
7904
7905 memset(utf8buf, 0x1, sizeof(utf8buf));
7906 utf8buf[8] = 'X';
7907 len = str2->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen,
7908 String::NO_NULL_TERMINATION);
7909 CHECK_EQ(8, len);
7910 CHECK_EQ('X', utf8buf[8]);
7911 CHECK_EQ(5, charlen);
7912 CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\342\230\203", 8));
7913 CHECK_NE(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
7914 utf8buf[8] = '\0';
7915 CHECK_EQ(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
yangguo@chromium.org304cc332012-07-24 07:59:48 +00007916
7917 memset(utf8buf, 0x1, sizeof(utf8buf));
7918 utf8buf[5] = 'X';
7919 len = str->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen,
7920 String::NO_NULL_TERMINATION);
7921 CHECK_EQ(5, len);
7922 CHECK_EQ('X', utf8buf[5]); // Test that the sixth character is untouched.
7923 CHECK_EQ(5, charlen);
7924 utf8buf[5] = '\0';
7925 CHECK_EQ(0, strcmp(utf8buf, "abcde"));
7926
7927 memset(buf, 0x1, sizeof(buf));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007928 len = str3->WriteOneByte(reinterpret_cast<uint8_t*>(buf));
yangguo@chromium.org304cc332012-07-24 07:59:48 +00007929 CHECK_EQ(7, len);
7930 CHECK_EQ(0, strcmp("abc", buf));
7931 CHECK_EQ(0, buf[3]);
7932 CHECK_EQ(0, strcmp("def", buf + 4));
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00007933
ulan@chromium.org57ff8812013-05-10 08:16:55 +00007934 CHECK_EQ(0, str->WriteOneByte(NULL, 0, 0, String::NO_NULL_TERMINATION));
yangguo@chromium.org46a2a512013-01-18 16:29:40 +00007935 CHECK_EQ(0, str->WriteUtf8(NULL, 0, 0, String::NO_NULL_TERMINATION));
7936 CHECK_EQ(0, str->Write(NULL, 0, 0, String::NO_NULL_TERMINATION));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00007937}
7938
7939
yangguo@chromium.org154ff992012-03-13 08:09:54 +00007940static void Utf16Helper(
7941 LocalContext& context,
7942 const char* name,
7943 const char* lengths_name,
7944 int len) {
7945 Local<v8::Array> a =
7946 Local<v8::Array>::Cast(context->Global()->Get(v8_str(name)));
7947 Local<v8::Array> alens =
7948 Local<v8::Array>::Cast(context->Global()->Get(v8_str(lengths_name)));
7949 for (int i = 0; i < len; i++) {
7950 Local<v8::String> string =
7951 Local<v8::String>::Cast(a->Get(i));
7952 Local<v8::Number> expected_len =
7953 Local<v8::Number>::Cast(alens->Get(i));
7954 int length = GetUtf8Length(string);
7955 CHECK_EQ(static_cast<int>(expected_len->Value()), length);
7956 }
7957}
7958
7959
7960static uint16_t StringGet(Handle<String> str, int index) {
7961 i::Handle<i::String> istring =
7962 v8::Utils::OpenHandle(String::Cast(*str));
7963 return istring->Get(index);
7964}
7965
7966
7967static void WriteUtf8Helper(
7968 LocalContext& context,
7969 const char* name,
7970 const char* lengths_name,
7971 int len) {
7972 Local<v8::Array> b =
7973 Local<v8::Array>::Cast(context->Global()->Get(v8_str(name)));
7974 Local<v8::Array> alens =
7975 Local<v8::Array>::Cast(context->Global()->Get(v8_str(lengths_name)));
7976 char buffer[1000];
7977 char buffer2[1000];
7978 for (int i = 0; i < len; i++) {
7979 Local<v8::String> string =
7980 Local<v8::String>::Cast(b->Get(i));
7981 Local<v8::Number> expected_len =
7982 Local<v8::Number>::Cast(alens->Get(i));
7983 int utf8_length = static_cast<int>(expected_len->Value());
7984 for (int j = utf8_length + 1; j >= 0; j--) {
7985 memset(reinterpret_cast<void*>(&buffer), 42, sizeof(buffer));
7986 memset(reinterpret_cast<void*>(&buffer2), 42, sizeof(buffer2));
7987 int nchars;
7988 int utf8_written =
7989 string->WriteUtf8(buffer, j, &nchars, String::NO_OPTIONS);
7990 int utf8_written2 =
7991 string->WriteUtf8(buffer2, j, &nchars, String::NO_NULL_TERMINATION);
7992 CHECK_GE(utf8_length + 1, utf8_written);
7993 CHECK_GE(utf8_length, utf8_written2);
7994 for (int k = 0; k < utf8_written2; k++) {
7995 CHECK_EQ(buffer[k], buffer2[k]);
7996 }
7997 CHECK(nchars * 3 >= utf8_written - 1);
7998 CHECK(nchars <= utf8_written);
7999 if (j == utf8_length + 1) {
8000 CHECK_EQ(utf8_written2, utf8_length);
8001 CHECK_EQ(utf8_written2 + 1, utf8_written);
8002 }
8003 CHECK_EQ(buffer[utf8_written], 42);
8004 if (j > utf8_length) {
8005 if (utf8_written != 0) CHECK_EQ(buffer[utf8_written - 1], 0);
8006 if (utf8_written > 1) CHECK_NE(buffer[utf8_written - 2], 42);
8007 Handle<String> roundtrip = v8_str(buffer);
8008 CHECK(roundtrip->Equals(string));
8009 } else {
8010 if (utf8_written != 0) CHECK_NE(buffer[utf8_written - 1], 42);
8011 }
8012 if (utf8_written2 != 0) CHECK_NE(buffer[utf8_written - 1], 42);
8013 if (nchars >= 2) {
8014 uint16_t trail = StringGet(string, nchars - 1);
8015 uint16_t lead = StringGet(string, nchars - 2);
8016 if (((lead & 0xfc00) == 0xd800) &&
8017 ((trail & 0xfc00) == 0xdc00)) {
8018 unsigned char u1 = buffer2[utf8_written2 - 4];
8019 unsigned char u2 = buffer2[utf8_written2 - 3];
8020 unsigned char u3 = buffer2[utf8_written2 - 2];
8021 unsigned char u4 = buffer2[utf8_written2 - 1];
8022 CHECK_EQ((u1 & 0xf8), 0xf0);
8023 CHECK_EQ((u2 & 0xc0), 0x80);
8024 CHECK_EQ((u3 & 0xc0), 0x80);
8025 CHECK_EQ((u4 & 0xc0), 0x80);
8026 uint32_t c = 0x10000 + ((lead & 0x3ff) << 10) + (trail & 0x3ff);
8027 CHECK_EQ((u4 & 0x3f), (c & 0x3f));
8028 CHECK_EQ((u3 & 0x3f), ((c >> 6) & 0x3f));
8029 CHECK_EQ((u2 & 0x3f), ((c >> 12) & 0x3f));
8030 CHECK_EQ((u1 & 0x3), c >> 18);
8031 }
8032 }
8033 }
8034 }
8035}
8036
8037
8038THREADED_TEST(Utf16) {
8039 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008040 v8::HandleScope scope(context->GetIsolate());
yangguo@chromium.org154ff992012-03-13 08:09:54 +00008041 CompileRun(
8042 "var pad = '01234567890123456789';"
8043 "var p = [];"
8044 "var plens = [20, 3, 3];"
8045 "p.push('01234567890123456789');"
8046 "var lead = 0xd800;"
8047 "var trail = 0xdc00;"
8048 "p.push(String.fromCharCode(0xd800));"
8049 "p.push(String.fromCharCode(0xdc00));"
8050 "var a = [];"
8051 "var b = [];"
danno@chromium.org88aa0582012-03-23 15:11:57 +00008052 "var c = [];"
yangguo@chromium.org154ff992012-03-13 08:09:54 +00008053 "var alens = [];"
8054 "for (var i = 0; i < 3; i++) {"
8055 " p[1] = String.fromCharCode(lead++);"
8056 " for (var j = 0; j < 3; j++) {"
8057 " p[2] = String.fromCharCode(trail++);"
8058 " a.push(p[i] + p[j]);"
8059 " b.push(p[i] + p[j]);"
danno@chromium.org88aa0582012-03-23 15:11:57 +00008060 " c.push(p[i] + p[j]);"
yangguo@chromium.org154ff992012-03-13 08:09:54 +00008061 " alens.push(plens[i] + plens[j]);"
8062 " }"
8063 "}"
8064 "alens[5] -= 2;" // Here the surrogate pairs match up.
8065 "var a2 = [];"
8066 "var b2 = [];"
danno@chromium.org88aa0582012-03-23 15:11:57 +00008067 "var c2 = [];"
yangguo@chromium.org154ff992012-03-13 08:09:54 +00008068 "var a2lens = [];"
8069 "for (var m = 0; m < 9; m++) {"
8070 " for (var n = 0; n < 9; n++) {"
8071 " a2.push(a[m] + a[n]);"
8072 " b2.push(b[m] + b[n]);"
danno@chromium.org88aa0582012-03-23 15:11:57 +00008073 " var newc = 'x' + c[m] + c[n] + 'y';"
8074 " c2.push(newc.substring(1, newc.length - 1));"
yangguo@chromium.org154ff992012-03-13 08:09:54 +00008075 " var utf = alens[m] + alens[n];" // And here.
8076 // The 'n's that start with 0xdc.. are 6-8
8077 // The 'm's that end with 0xd8.. are 1, 4 and 7
8078 " if ((m % 3) == 1 && n >= 6) utf -= 2;"
8079 " a2lens.push(utf);"
8080 " }"
8081 "}");
8082 Utf16Helper(context, "a", "alens", 9);
8083 Utf16Helper(context, "a2", "a2lens", 81);
8084 WriteUtf8Helper(context, "b", "alens", 9);
8085 WriteUtf8Helper(context, "b2", "a2lens", 81);
danno@chromium.org88aa0582012-03-23 15:11:57 +00008086 WriteUtf8Helper(context, "c2", "a2lens", 81);
yangguo@chromium.org154ff992012-03-13 08:09:54 +00008087}
8088
8089
8090static bool SameSymbol(Handle<String> s1, Handle<String> s2) {
8091 i::Handle<i::String> is1(v8::Utils::OpenHandle(*s1));
8092 i::Handle<i::String> is2(v8::Utils::OpenHandle(*s2));
8093 return *is1 == *is2;
8094}
8095
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00008096static void SameSymbolHelper(v8::Isolate* isolate, const char* a,
8097 const char* b) {
8098 Handle<String> symbol1 =
8099 v8::String::NewFromUtf8(isolate, a, v8::String::kInternalizedString);
8100 Handle<String> symbol2 =
8101 v8::String::NewFromUtf8(isolate, b, v8::String::kInternalizedString);
yangguo@chromium.org154ff992012-03-13 08:09:54 +00008102 CHECK(SameSymbol(symbol1, symbol2));
8103}
8104
8105
8106THREADED_TEST(Utf16Symbol) {
8107 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008108 v8::HandleScope scope(context->GetIsolate());
yangguo@chromium.org154ff992012-03-13 08:09:54 +00008109
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00008110 Handle<String> symbol1 = v8::String::NewFromUtf8(
8111 context->GetIsolate(), "abc", v8::String::kInternalizedString);
8112 Handle<String> symbol2 = v8::String::NewFromUtf8(
8113 context->GetIsolate(), "abc", v8::String::kInternalizedString);
yangguo@chromium.org154ff992012-03-13 08:09:54 +00008114 CHECK(SameSymbol(symbol1, symbol2));
8115
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00008116 SameSymbolHelper(context->GetIsolate(),
8117 "\360\220\220\205", // 4 byte encoding.
yangguo@chromium.org154ff992012-03-13 08:09:54 +00008118 "\355\240\201\355\260\205"); // 2 3-byte surrogates.
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00008119 SameSymbolHelper(context->GetIsolate(),
8120 "\355\240\201\355\260\206", // 2 3-byte surrogates.
yangguo@chromium.org154ff992012-03-13 08:09:54 +00008121 "\360\220\220\206"); // 4 byte encoding.
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00008122 SameSymbolHelper(context->GetIsolate(),
8123 "x\360\220\220\205", // 4 byte encoding.
yangguo@chromium.org154ff992012-03-13 08:09:54 +00008124 "x\355\240\201\355\260\205"); // 2 3-byte surrogates.
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00008125 SameSymbolHelper(context->GetIsolate(),
8126 "x\355\240\201\355\260\206", // 2 3-byte surrogates.
yangguo@chromium.org154ff992012-03-13 08:09:54 +00008127 "x\360\220\220\206"); // 4 byte encoding.
8128 CompileRun(
8129 "var sym0 = 'benedictus';"
8130 "var sym0b = 'S\303\270ren';"
8131 "var sym1 = '\355\240\201\355\260\207';"
8132 "var sym2 = '\360\220\220\210';"
8133 "var sym3 = 'x\355\240\201\355\260\207';"
8134 "var sym4 = 'x\360\220\220\210';"
8135 "if (sym1.length != 2) throw sym1;"
8136 "if (sym1.charCodeAt(1) != 0xdc07) throw sym1.charCodeAt(1);"
8137 "if (sym2.length != 2) throw sym2;"
8138 "if (sym2.charCodeAt(1) != 0xdc08) throw sym2.charCodeAt(2);"
8139 "if (sym3.length != 3) throw sym3;"
8140 "if (sym3.charCodeAt(2) != 0xdc07) throw sym1.charCodeAt(2);"
8141 "if (sym4.length != 3) throw sym4;"
8142 "if (sym4.charCodeAt(2) != 0xdc08) throw sym2.charCodeAt(2);");
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00008143 Handle<String> sym0 = v8::String::NewFromUtf8(
8144 context->GetIsolate(), "benedictus", v8::String::kInternalizedString);
8145 Handle<String> sym0b = v8::String::NewFromUtf8(
8146 context->GetIsolate(), "S\303\270ren", v8::String::kInternalizedString);
8147 Handle<String> sym1 =
8148 v8::String::NewFromUtf8(context->GetIsolate(), "\355\240\201\355\260\207",
8149 v8::String::kInternalizedString);
8150 Handle<String> sym2 =
8151 v8::String::NewFromUtf8(context->GetIsolate(), "\360\220\220\210",
8152 v8::String::kInternalizedString);
8153 Handle<String> sym3 = v8::String::NewFromUtf8(
8154 context->GetIsolate(), "x\355\240\201\355\260\207",
8155 v8::String::kInternalizedString);
8156 Handle<String> sym4 =
8157 v8::String::NewFromUtf8(context->GetIsolate(), "x\360\220\220\210",
8158 v8::String::kInternalizedString);
yangguo@chromium.org154ff992012-03-13 08:09:54 +00008159 v8::Local<v8::Object> global = context->Global();
8160 Local<Value> s0 = global->Get(v8_str("sym0"));
8161 Local<Value> s0b = global->Get(v8_str("sym0b"));
8162 Local<Value> s1 = global->Get(v8_str("sym1"));
8163 Local<Value> s2 = global->Get(v8_str("sym2"));
8164 Local<Value> s3 = global->Get(v8_str("sym3"));
8165 Local<Value> s4 = global->Get(v8_str("sym4"));
danno@chromium.orgf95d4b92013-06-13 14:40:17 +00008166 CHECK(SameSymbol(sym0, Handle<String>::Cast(s0)));
8167 CHECK(SameSymbol(sym0b, Handle<String>::Cast(s0b)));
8168 CHECK(SameSymbol(sym1, Handle<String>::Cast(s1)));
8169 CHECK(SameSymbol(sym2, Handle<String>::Cast(s2)));
8170 CHECK(SameSymbol(sym3, Handle<String>::Cast(s3)));
8171 CHECK(SameSymbol(sym4, Handle<String>::Cast(s4)));
yangguo@chromium.org154ff992012-03-13 08:09:54 +00008172}
8173
8174
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008175THREADED_TEST(ToArrayIndex) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008176 LocalContext context;
ulan@chromium.org0f13e742014-01-03 15:51:11 +00008177 v8::Isolate* isolate = context->GetIsolate();
8178 v8::HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008179
8180 v8::Handle<String> str = v8_str("42");
8181 v8::Handle<v8::Uint32> index = str->ToArrayIndex();
8182 CHECK(!index.IsEmpty());
8183 CHECK_EQ(42.0, index->Uint32Value());
8184 str = v8_str("42asdf");
8185 index = str->ToArrayIndex();
8186 CHECK(index.IsEmpty());
8187 str = v8_str("-42");
8188 index = str->ToArrayIndex();
8189 CHECK(index.IsEmpty());
8190 str = v8_str("4294967295");
8191 index = str->ToArrayIndex();
8192 CHECK(!index.IsEmpty());
8193 CHECK_EQ(4294967295.0, index->Uint32Value());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00008194 v8::Handle<v8::Number> num = v8::Number::New(isolate, 1);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008195 index = num->ToArrayIndex();
8196 CHECK(!index.IsEmpty());
8197 CHECK_EQ(1.0, index->Uint32Value());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00008198 num = v8::Number::New(isolate, -1);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008199 index = num->ToArrayIndex();
8200 CHECK(index.IsEmpty());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00008201 v8::Handle<v8::Object> obj = v8::Object::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008202 index = obj->ToArrayIndex();
8203 CHECK(index.IsEmpty());
8204}
8205
8206
8207THREADED_TEST(ErrorConstruction) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008208 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008209 v8::HandleScope scope(context->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008210
8211 v8::Handle<String> foo = v8_str("foo");
8212 v8::Handle<String> message = v8_str("message");
8213 v8::Handle<Value> range_error = v8::Exception::RangeError(foo);
8214 CHECK(range_error->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00008215 CHECK(range_error.As<v8::Object>()->Get(message)->Equals(foo));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008216 v8::Handle<Value> reference_error = v8::Exception::ReferenceError(foo);
8217 CHECK(reference_error->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00008218 CHECK(reference_error.As<v8::Object>()->Get(message)->Equals(foo));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008219 v8::Handle<Value> syntax_error = v8::Exception::SyntaxError(foo);
8220 CHECK(syntax_error->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00008221 CHECK(syntax_error.As<v8::Object>()->Get(message)->Equals(foo));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008222 v8::Handle<Value> type_error = v8::Exception::TypeError(foo);
8223 CHECK(type_error->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00008224 CHECK(type_error.As<v8::Object>()->Get(message)->Equals(foo));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008225 v8::Handle<Value> error = v8::Exception::Error(foo);
8226 CHECK(error->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00008227 CHECK(error.As<v8::Object>()->Get(message)->Equals(foo));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008228}
8229
8230
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00008231static void YGetter(Local<String> name,
8232 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008233 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00008234 info.GetReturnValue().Set(v8_num(10));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008235}
8236
8237
8238static void YSetter(Local<String> name,
8239 Local<Value> value,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00008240 const v8::PropertyCallbackInfo<void>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008241 if (info.This()->Has(name)) {
8242 info.This()->Delete(name);
8243 }
8244 info.This()->Set(name, value);
8245}
8246
8247
8248THREADED_TEST(DeleteAccessor) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00008249 v8::Isolate* isolate = CcTest::isolate();
8250 v8::HandleScope scope(isolate);
8251 v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008252 obj->SetAccessor(v8_str("y"), YGetter, YSetter);
8253 LocalContext context;
8254 v8::Handle<v8::Object> holder = obj->NewInstance();
8255 context->Global()->Set(v8_str("holder"), holder);
8256 v8::Handle<Value> result = CompileRun(
8257 "holder.y = 11; holder.y = 12; holder.y");
8258 CHECK_EQ(12, result->Uint32Value());
8259}
8260
8261
8262THREADED_TEST(TypeSwitch) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00008263 v8::Isolate* isolate = CcTest::isolate();
8264 v8::HandleScope scope(isolate);
8265 v8::Handle<v8::FunctionTemplate> templ1 = v8::FunctionTemplate::New(isolate);
8266 v8::Handle<v8::FunctionTemplate> templ2 = v8::FunctionTemplate::New(isolate);
8267 v8::Handle<v8::FunctionTemplate> templ3 = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008268 v8::Handle<v8::FunctionTemplate> templs[3] = { templ1, templ2, templ3 };
8269 v8::Handle<v8::TypeSwitch> type_switch = v8::TypeSwitch::New(3, templs);
8270 LocalContext context;
ulan@chromium.org0f13e742014-01-03 15:51:11 +00008271 v8::Handle<v8::Object> obj0 = v8::Object::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008272 v8::Handle<v8::Object> obj1 = templ1->GetFunction()->NewInstance();
8273 v8::Handle<v8::Object> obj2 = templ2->GetFunction()->NewInstance();
8274 v8::Handle<v8::Object> obj3 = templ3->GetFunction()->NewInstance();
8275 for (int i = 0; i < 10; i++) {
8276 CHECK_EQ(0, type_switch->match(obj0));
8277 CHECK_EQ(1, type_switch->match(obj1));
8278 CHECK_EQ(2, type_switch->match(obj2));
8279 CHECK_EQ(3, type_switch->match(obj3));
8280 CHECK_EQ(3, type_switch->match(obj3));
8281 CHECK_EQ(2, type_switch->match(obj2));
8282 CHECK_EQ(1, type_switch->match(obj1));
8283 CHECK_EQ(0, type_switch->match(obj0));
8284 }
8285}
8286
8287
8288// For use within the TestSecurityHandler() test.
8289static bool g_security_callback_result = false;
8290static bool NamedSecurityTestCallback(Local<v8::Object> global,
8291 Local<Value> name,
8292 v8::AccessType type,
8293 Local<Value> data) {
8294 // Always allow read access.
8295 if (type == v8::ACCESS_GET)
8296 return true;
8297
8298 // Sometimes allow other access.
8299 return g_security_callback_result;
8300}
8301
8302
8303static bool IndexedSecurityTestCallback(Local<v8::Object> global,
8304 uint32_t key,
8305 v8::AccessType type,
8306 Local<Value> data) {
8307 // Always allow read access.
8308 if (type == v8::ACCESS_GET)
8309 return true;
8310
8311 // Sometimes allow other access.
8312 return g_security_callback_result;
8313}
8314
8315
8316static int trouble_nesting = 0;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00008317static void TroubleCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008318 ApiTestFuzzer::Fuzz();
8319 trouble_nesting++;
8320
8321 // Call a JS function that throws an uncaught exception.
machenbach@chromium.org528ce022013-09-23 14:09:36 +00008322 Local<v8::Object> arg_this =
8323 args.GetIsolate()->GetCurrentContext()->Global();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008324 Local<Value> trouble_callee = (trouble_nesting == 3) ?
8325 arg_this->Get(v8_str("trouble_callee")) :
8326 arg_this->Get(v8_str("trouble_caller"));
8327 CHECK(trouble_callee->IsFunction());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00008328 args.GetReturnValue().Set(
8329 Function::Cast(*trouble_callee)->Call(arg_this, 0, NULL));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008330}
8331
8332
8333static int report_count = 0;
8334static void ApiUncaughtExceptionTestListener(v8::Handle<v8::Message>,
8335 v8::Handle<Value>) {
8336 report_count++;
8337}
8338
8339
8340// Counts uncaught exceptions, but other tests running in parallel
8341// also have uncaught exceptions.
8342TEST(ApiUncaughtException) {
ager@chromium.org8bb60582008-12-11 12:02:20 +00008343 report_count = 0;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008344 LocalContext env;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00008345 v8::Isolate* isolate = env->GetIsolate();
8346 v8::HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008347 v8::V8::AddMessageListener(ApiUncaughtExceptionTestListener);
8348
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00008349 Local<v8::FunctionTemplate> fun =
8350 v8::FunctionTemplate::New(isolate, TroubleCallback);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008351 v8::Local<v8::Object> global = env->Global();
8352 global->Set(v8_str("trouble"), fun->GetFunction());
8353
8354 Script::Compile(v8_str("function trouble_callee() {"
8355 " var x = null;"
8356 " return x.foo;"
8357 "};"
8358 "function trouble_caller() {"
8359 " trouble();"
8360 "};"))->Run();
8361 Local<Value> trouble = global->Get(v8_str("trouble"));
8362 CHECK(trouble->IsFunction());
8363 Local<Value> trouble_callee = global->Get(v8_str("trouble_callee"));
8364 CHECK(trouble_callee->IsFunction());
8365 Local<Value> trouble_caller = global->Get(v8_str("trouble_caller"));
8366 CHECK(trouble_caller->IsFunction());
8367 Function::Cast(*trouble_caller)->Call(global, 0, NULL);
8368 CHECK_EQ(1, report_count);
ager@chromium.org8bb60582008-12-11 12:02:20 +00008369 v8::V8::RemoveMessageListeners(ApiUncaughtExceptionTestListener);
8370}
8371
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00008372static const char* script_resource_name = "ExceptionInNativeScript.js";
8373static void ExceptionInNativeScriptTestListener(v8::Handle<v8::Message> message,
8374 v8::Handle<Value>) {
8375 v8::Handle<v8::Value> name_val = message->GetScriptResourceName();
8376 CHECK(!name_val.IsEmpty() && name_val->IsString());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00008377 v8::String::Utf8Value name(message->GetScriptResourceName());
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00008378 CHECK_EQ(script_resource_name, *name);
8379 CHECK_EQ(3, message->GetLineNumber());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +00008380 v8::String::Utf8Value source_line(message->GetSourceLine());
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00008381 CHECK_EQ(" new o.foo();", *source_line);
8382}
8383
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00008384
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00008385TEST(ExceptionInNativeScript) {
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00008386 LocalContext env;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00008387 v8::Isolate* isolate = env->GetIsolate();
8388 v8::HandleScope scope(isolate);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00008389 v8::V8::AddMessageListener(ExceptionInNativeScriptTestListener);
8390
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00008391 Local<v8::FunctionTemplate> fun =
8392 v8::FunctionTemplate::New(isolate, TroubleCallback);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00008393 v8::Local<v8::Object> global = env->Global();
8394 global->Set(v8_str("trouble"), fun->GetFunction());
8395
machenbach@chromium.orgf9841892013-11-25 12:01:13 +00008396 Script::Compile(
8397 v8_str(
8398 "function trouble() {\n"
8399 " var o = {};\n"
8400 " new o.foo();\n"
8401 "};"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00008402 v8::String::NewFromUtf8(isolate, script_resource_name))->Run();
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00008403 Local<Value> trouble = global->Get(v8_str("trouble"));
8404 CHECK(trouble->IsFunction());
8405 Function::Cast(*trouble)->Call(global, 0, NULL);
8406 v8::V8::RemoveMessageListeners(ExceptionInNativeScriptTestListener);
8407}
8408
ager@chromium.org8bb60582008-12-11 12:02:20 +00008409
8410TEST(CompilationErrorUsingTryCatchHandler) {
ager@chromium.org8bb60582008-12-11 12:02:20 +00008411 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008412 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org8bb60582008-12-11 12:02:20 +00008413 v8::TryCatch try_catch;
8414 Script::Compile(v8_str("This doesn't &*&@#$&*^ compile."));
8415 CHECK_NE(NULL, *try_catch.Exception());
8416 CHECK(try_catch.HasCaught());
8417}
8418
8419
8420TEST(TryCatchFinallyUsingTryCatchHandler) {
ager@chromium.org8bb60582008-12-11 12:02:20 +00008421 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008422 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org8bb60582008-12-11 12:02:20 +00008423 v8::TryCatch try_catch;
8424 Script::Compile(v8_str("try { throw ''; } catch (e) {}"))->Run();
8425 CHECK(!try_catch.HasCaught());
8426 Script::Compile(v8_str("try { throw ''; } finally {}"))->Run();
8427 CHECK(try_catch.HasCaught());
8428 try_catch.Reset();
8429 Script::Compile(v8_str("(function() {"
8430 "try { throw ''; } finally { return; }"
8431 "})()"))->Run();
8432 CHECK(!try_catch.HasCaught());
8433 Script::Compile(v8_str("(function()"
8434 " { try { throw ''; } finally { throw 0; }"
8435 "})()"))->Run();
8436 CHECK(try_catch.HasCaught());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008437}
8438
8439
8440// SecurityHandler can't be run twice
8441TEST(SecurityHandler) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00008442 v8::Isolate* isolate = CcTest::isolate();
8443 v8::HandleScope scope0(isolate);
8444 v8::Handle<v8::ObjectTemplate> global_template =
8445 v8::ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008446 global_template->SetAccessCheckCallbacks(NamedSecurityTestCallback,
8447 IndexedSecurityTestCallback);
8448 // Create an environment
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00008449 v8::Handle<Context> context0 = Context::New(isolate, NULL, global_template);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008450 context0->Enter();
8451
8452 v8::Handle<v8::Object> global0 = context0->Global();
8453 v8::Handle<Script> script0 = v8_compile("foo = 111");
8454 script0->Run();
8455 global0->Set(v8_str("0"), v8_num(999));
8456 v8::Handle<Value> foo0 = global0->Get(v8_str("foo"));
8457 CHECK_EQ(111, foo0->Int32Value());
8458 v8::Handle<Value> z0 = global0->Get(v8_str("0"));
8459 CHECK_EQ(999, z0->Int32Value());
8460
8461 // Create another environment, should fail security checks.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00008462 v8::HandleScope scope1(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008463
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008464 v8::Handle<Context> context1 =
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00008465 Context::New(isolate, NULL, global_template);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008466 context1->Enter();
8467
8468 v8::Handle<v8::Object> global1 = context1->Global();
8469 global1->Set(v8_str("othercontext"), global0);
8470 // This set will fail the security check.
8471 v8::Handle<Script> script1 =
8472 v8_compile("othercontext.foo = 222; othercontext[0] = 888;");
8473 script1->Run();
8474 // This read will pass the security check.
8475 v8::Handle<Value> foo1 = global0->Get(v8_str("foo"));
8476 CHECK_EQ(111, foo1->Int32Value());
8477 // This read will pass the security check.
8478 v8::Handle<Value> z1 = global0->Get(v8_str("0"));
8479 CHECK_EQ(999, z1->Int32Value());
8480
8481 // Create another environment, should pass security checks.
8482 { g_security_callback_result = true; // allow security handler to pass.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00008483 v8::HandleScope scope2(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008484 LocalContext context2;
8485 v8::Handle<v8::Object> global2 = context2->Global();
8486 global2->Set(v8_str("othercontext"), global0);
8487 v8::Handle<Script> script2 =
8488 v8_compile("othercontext.foo = 333; othercontext[0] = 888;");
8489 script2->Run();
8490 v8::Handle<Value> foo2 = global0->Get(v8_str("foo"));
8491 CHECK_EQ(333, foo2->Int32Value());
8492 v8::Handle<Value> z2 = global0->Get(v8_str("0"));
8493 CHECK_EQ(888, z2->Int32Value());
8494 }
8495
8496 context1->Exit();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008497 context0->Exit();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008498}
8499
8500
8501THREADED_TEST(SecurityChecks) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008502 LocalContext env1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008503 v8::HandleScope handle_scope(env1->GetIsolate());
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008504 v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008505
8506 Local<Value> foo = v8_str("foo");
8507 Local<Value> bar = v8_str("bar");
8508
8509 // Set to the same domain.
8510 env1->SetSecurityToken(foo);
8511
8512 // Create a function in env1.
8513 Script::Compile(v8_str("spy=function(){return spy;}"))->Run();
8514 Local<Value> spy = env1->Global()->Get(v8_str("spy"));
8515 CHECK(spy->IsFunction());
8516
8517 // Create another function accessing global objects.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00008518 Script::Compile(v8_str("spy2=function(){return new this.Array();}"))->Run();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008519 Local<Value> spy2 = env1->Global()->Get(v8_str("spy2"));
8520 CHECK(spy2->IsFunction());
8521
8522 // Switch to env2 in the same domain and invoke spy on env2.
8523 {
8524 env2->SetSecurityToken(foo);
8525 // Enter env2
8526 Context::Scope scope_env2(env2);
8527 Local<Value> result = Function::Cast(*spy)->Call(env2->Global(), 0, NULL);
8528 CHECK(result->IsFunction());
8529 }
8530
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008531 {
8532 env2->SetSecurityToken(bar);
8533 Context::Scope scope_env2(env2);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008534
8535 // Call cross_domain_call, it should throw an exception
8536 v8::TryCatch try_catch;
8537 Function::Cast(*spy2)->Call(env2->Global(), 0, NULL);
8538 CHECK(try_catch.HasCaught());
8539 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008540}
8541
8542
8543// Regression test case for issue 1183439.
8544THREADED_TEST(SecurityChecksForPrototypeChain) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008545 LocalContext current;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008546 v8::HandleScope scope(current->GetIsolate());
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008547 v8::Handle<Context> other = Context::New(current->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008548
8549 // Change context to be able to get to the Object function in the
8550 // other context without hitting the security checks.
8551 v8::Local<Value> other_object;
8552 { Context::Scope scope(other);
8553 other_object = other->Global()->Get(v8_str("Object"));
8554 other->Global()->Set(v8_num(42), v8_num(87));
8555 }
8556
8557 current->Global()->Set(v8_str("other"), other->Global());
8558 CHECK(v8_compile("other")->Run()->Equals(other->Global()));
8559
8560 // Make sure the security check fails here and we get an undefined
8561 // result instead of getting the Object function. Repeat in a loop
8562 // to make sure to exercise the IC code.
8563 v8::Local<Script> access_other0 = v8_compile("other.Object");
8564 v8::Local<Script> access_other1 = v8_compile("other[42]");
8565 for (int i = 0; i < 5; i++) {
8566 CHECK(!access_other0->Run()->Equals(other_object));
8567 CHECK(access_other0->Run()->IsUndefined());
8568 CHECK(!access_other1->Run()->Equals(v8_num(87)));
8569 CHECK(access_other1->Run()->IsUndefined());
8570 }
8571
8572 // Create an object that has 'other' in its prototype chain and make
8573 // sure we cannot access the Object function indirectly through
8574 // that. Repeat in a loop to make sure to exercise the IC code.
8575 v8_compile("function F() { };"
8576 "F.prototype = other;"
8577 "var f = new F();")->Run();
8578 v8::Local<Script> access_f0 = v8_compile("f.Object");
8579 v8::Local<Script> access_f1 = v8_compile("f[42]");
8580 for (int j = 0; j < 5; j++) {
8581 CHECK(!access_f0->Run()->Equals(other_object));
8582 CHECK(access_f0->Run()->IsUndefined());
8583 CHECK(!access_f1->Run()->Equals(v8_num(87)));
8584 CHECK(access_f1->Run()->IsUndefined());
8585 }
8586
8587 // Now it gets hairy: Set the prototype for the other global object
8588 // to be the current global object. The prototype chain for 'f' now
8589 // goes through 'other' but ends up in the current global object.
8590 { Context::Scope scope(other);
8591 other->Global()->Set(v8_str("__proto__"), current->Global());
8592 }
8593 // Set a named and an index property on the current global
8594 // object. To force the lookup to go through the other global object,
8595 // the properties must not exist in the other global object.
8596 current->Global()->Set(v8_str("foo"), v8_num(100));
8597 current->Global()->Set(v8_num(99), v8_num(101));
8598 // Try to read the properties from f and make sure that the access
8599 // gets stopped by the security checks on the other global object.
8600 Local<Script> access_f2 = v8_compile("f.foo");
8601 Local<Script> access_f3 = v8_compile("f[99]");
8602 for (int k = 0; k < 5; k++) {
8603 CHECK(!access_f2->Run()->Equals(v8_num(100)));
8604 CHECK(access_f2->Run()->IsUndefined());
8605 CHECK(!access_f3->Run()->Equals(v8_num(101)));
8606 CHECK(access_f3->Run()->IsUndefined());
8607 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008608}
8609
8610
8611THREADED_TEST(CrossDomainDelete) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008612 LocalContext env1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008613 v8::HandleScope handle_scope(env1->GetIsolate());
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008614 v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008615
8616 Local<Value> foo = v8_str("foo");
8617 Local<Value> bar = v8_str("bar");
8618
8619 // Set to the same domain.
8620 env1->SetSecurityToken(foo);
8621 env2->SetSecurityToken(foo);
8622
8623 env1->Global()->Set(v8_str("prop"), v8_num(3));
8624 env2->Global()->Set(v8_str("env1"), env1->Global());
8625
8626 // Change env2 to a different domain and delete env1.prop.
8627 env2->SetSecurityToken(bar);
8628 {
8629 Context::Scope scope_env2(env2);
8630 Local<Value> result =
8631 Script::Compile(v8_str("delete env1.prop"))->Run();
8632 CHECK(result->IsFalse());
8633 }
8634
8635 // Check that env1.prop still exists.
8636 Local<Value> v = env1->Global()->Get(v8_str("prop"));
8637 CHECK(v->IsNumber());
8638 CHECK_EQ(3, v->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008639}
8640
8641
ager@chromium.org870a0b62008-11-04 11:43:05 +00008642THREADED_TEST(CrossDomainIsPropertyEnumerable) {
ager@chromium.org870a0b62008-11-04 11:43:05 +00008643 LocalContext env1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008644 v8::HandleScope handle_scope(env1->GetIsolate());
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008645 v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
ager@chromium.org870a0b62008-11-04 11:43:05 +00008646
8647 Local<Value> foo = v8_str("foo");
8648 Local<Value> bar = v8_str("bar");
8649
8650 // Set to the same domain.
8651 env1->SetSecurityToken(foo);
8652 env2->SetSecurityToken(foo);
8653
8654 env1->Global()->Set(v8_str("prop"), v8_num(3));
8655 env2->Global()->Set(v8_str("env1"), env1->Global());
8656
8657 // env1.prop is enumerable in env2.
8658 Local<String> test = v8_str("propertyIsEnumerable.call(env1, 'prop')");
8659 {
8660 Context::Scope scope_env2(env2);
8661 Local<Value> result = Script::Compile(test)->Run();
8662 CHECK(result->IsTrue());
8663 }
8664
8665 // Change env2 to a different domain and test again.
8666 env2->SetSecurityToken(bar);
8667 {
8668 Context::Scope scope_env2(env2);
8669 Local<Value> result = Script::Compile(test)->Run();
8670 CHECK(result->IsFalse());
8671 }
ager@chromium.org870a0b62008-11-04 11:43:05 +00008672}
8673
8674
ager@chromium.org236ad962008-09-25 09:45:57 +00008675THREADED_TEST(CrossDomainForIn) {
ager@chromium.org236ad962008-09-25 09:45:57 +00008676 LocalContext env1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008677 v8::HandleScope handle_scope(env1->GetIsolate());
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008678 v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
ager@chromium.org236ad962008-09-25 09:45:57 +00008679
8680 Local<Value> foo = v8_str("foo");
8681 Local<Value> bar = v8_str("bar");
8682
8683 // Set to the same domain.
8684 env1->SetSecurityToken(foo);
8685 env2->SetSecurityToken(foo);
8686
8687 env1->Global()->Set(v8_str("prop"), v8_num(3));
8688 env2->Global()->Set(v8_str("env1"), env1->Global());
8689
8690 // Change env2 to a different domain and set env1's global object
8691 // as the __proto__ of an object in env2 and enumerate properties
8692 // in for-in. It shouldn't enumerate properties on env1's global
8693 // object.
8694 env2->SetSecurityToken(bar);
8695 {
8696 Context::Scope scope_env2(env2);
8697 Local<Value> result =
8698 CompileRun("(function(){var obj = {'__proto__':env1};"
8699 "for (var p in obj)"
8700 " if (p == 'prop') return false;"
8701 "return true;})()");
8702 CHECK(result->IsTrue());
8703 }
ager@chromium.org236ad962008-09-25 09:45:57 +00008704}
8705
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008706
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00008707TEST(ContextDetachGlobal) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00008708 LocalContext env1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008709 v8::HandleScope handle_scope(env1->GetIsolate());
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008710 v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00008711
8712 Local<v8::Object> global1 = env1->Global();
8713
8714 Local<Value> foo = v8_str("foo");
8715
8716 // Set to the same domain.
8717 env1->SetSecurityToken(foo);
8718 env2->SetSecurityToken(foo);
8719
8720 // Enter env2
8721 env2->Enter();
8722
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +00008723 // Create a function in env2 and add a reference to it in env1.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00008724 Local<v8::Object> global2 = env2->Global();
ulan@chromium.org0f13e742014-01-03 15:51:11 +00008725 global2->Set(v8_str("prop"), v8::Integer::New(env2->GetIsolate(), 1));
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00008726 CompileRun("function getProp() {return prop;}");
8727
8728 env1->Global()->Set(v8_str("getProp"),
8729 global2->Get(v8_str("getProp")));
8730
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +00008731 // Detach env2's global, and reuse the global object of env2
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00008732 env2->Exit();
8733 env2->DetachGlobal();
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00008734
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008735 v8::Handle<Context> env3 = Context::New(env1->GetIsolate(),
8736 0,
8737 v8::Handle<v8::ObjectTemplate>(),
8738 global2);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00008739 env3->SetSecurityToken(v8_str("bar"));
8740 env3->Enter();
8741
8742 Local<v8::Object> global3 = env3->Global();
8743 CHECK_EQ(global2, global3);
8744 CHECK(global3->Get(v8_str("prop"))->IsUndefined());
8745 CHECK(global3->Get(v8_str("getProp"))->IsUndefined());
ulan@chromium.org0f13e742014-01-03 15:51:11 +00008746 global3->Set(v8_str("prop"), v8::Integer::New(env3->GetIsolate(), -1));
8747 global3->Set(v8_str("prop2"), v8::Integer::New(env3->GetIsolate(), 2));
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00008748 env3->Exit();
8749
8750 // Call getProp in env1, and it should return the value 1
8751 {
8752 Local<Value> get_prop = global1->Get(v8_str("getProp"));
8753 CHECK(get_prop->IsFunction());
8754 v8::TryCatch try_catch;
8755 Local<Value> r = Function::Cast(*get_prop)->Call(global1, 0, NULL);
8756 CHECK(!try_catch.HasCaught());
8757 CHECK_EQ(1, r->Int32Value());
8758 }
8759
8760 // Check that env3 is not accessible from env1
8761 {
8762 Local<Value> r = global3->Get(v8_str("prop2"));
8763 CHECK(r->IsUndefined());
8764 }
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +00008765}
8766
8767
jkummerow@chromium.org113035e2013-12-13 15:13:40 +00008768TEST(DetachGlobal) {
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +00008769 LocalContext env1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +00008770 v8::HandleScope scope(env1->GetIsolate());
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +00008771
8772 // Create second environment.
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008773 v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +00008774
8775 Local<Value> foo = v8_str("foo");
8776
8777 // Set same security token for env1 and env2.
8778 env1->SetSecurityToken(foo);
8779 env2->SetSecurityToken(foo);
8780
8781 // Create a property on the global object in env2.
8782 {
8783 v8::Context::Scope scope(env2);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00008784 env2->Global()->Set(v8_str("p"), v8::Integer::New(env2->GetIsolate(), 42));
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +00008785 }
8786
8787 // Create a reference to env2 global from env1 global.
8788 env1->Global()->Set(v8_str("other"), env2->Global());
8789
8790 // Check that we have access to other.p in env2 from env1.
8791 Local<Value> result = CompileRun("other.p");
8792 CHECK(result->IsInt32());
8793 CHECK_EQ(42, result->Int32Value());
8794
8795 // Hold on to global from env2 and detach global from env2.
8796 Local<v8::Object> global2 = env2->Global();
8797 env2->DetachGlobal();
8798
8799 // Check that the global has been detached. No other.p property can
8800 // be found.
8801 result = CompileRun("other.p");
8802 CHECK(result->IsUndefined());
8803
8804 // Reuse global2 for env3.
ulan@chromium.org57ff8812013-05-10 08:16:55 +00008805 v8::Handle<Context> env3 = Context::New(env1->GetIsolate(),
8806 0,
8807 v8::Handle<v8::ObjectTemplate>(),
8808 global2);
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +00008809 CHECK_EQ(global2, env3->Global());
8810
8811 // Start by using the same security token for env3 as for env1 and env2.
8812 env3->SetSecurityToken(foo);
8813
8814 // Create a property on the global object in env3.
8815 {
8816 v8::Context::Scope scope(env3);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00008817 env3->Global()->Set(v8_str("p"), v8::Integer::New(env3->GetIsolate(), 24));
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +00008818 }
8819
8820 // Check that other.p is now the property in env3 and that we have access.
8821 result = CompileRun("other.p");
8822 CHECK(result->IsInt32());
8823 CHECK_EQ(24, result->Int32Value());
8824
8825 // Change security token for env3 to something different from env1 and env2.
8826 env3->SetSecurityToken(v8_str("bar"));
8827
8828 // Check that we do not have access to other.p in env1. |other| is now
8829 // the global object for env3 which has a different security token,
8830 // so access should be blocked.
8831 result = CompileRun("other.p");
8832 CHECK(result->IsUndefined());
jkummerow@chromium.org113035e2013-12-13 15:13:40 +00008833}
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +00008834
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +00008835
rossberg@chromium.org9ed27462014-01-07 14:16:41 +00008836void GetThisX(const v8::FunctionCallbackInfo<v8::Value>& info) {
8837 info.GetReturnValue().Set(
8838 info.GetIsolate()->GetCurrentContext()->Global()->Get(v8_str("x")));
8839}
8840
8841
jkummerow@chromium.org113035e2013-12-13 15:13:40 +00008842TEST(DetachedAccesses) {
8843 LocalContext env1;
8844 v8::HandleScope scope(env1->GetIsolate());
8845
8846 // Create second environment.
rossberg@chromium.org9ed27462014-01-07 14:16:41 +00008847 Local<ObjectTemplate> inner_global_template =
8848 FunctionTemplate::New(env1->GetIsolate())->InstanceTemplate();
8849 inner_global_template ->SetAccessorProperty(
8850 v8_str("this_x"), FunctionTemplate::New(env1->GetIsolate(), GetThisX));
8851 v8::Local<Context> env2 =
8852 Context::New(env1->GetIsolate(), NULL, inner_global_template);
jkummerow@chromium.org113035e2013-12-13 15:13:40 +00008853
8854 Local<Value> foo = v8_str("foo");
8855
8856 // Set same security token for env1 and env2.
8857 env1->SetSecurityToken(foo);
8858 env2->SetSecurityToken(foo);
8859
rossberg@chromium.org9ed27462014-01-07 14:16:41 +00008860 env1->Global()->Set(v8_str("x"), v8_str("env1_x"));
8861
jkummerow@chromium.org113035e2013-12-13 15:13:40 +00008862 {
8863 v8::Context::Scope scope(env2);
rossberg@chromium.org9ed27462014-01-07 14:16:41 +00008864 env2->Global()->Set(v8_str("x"), v8_str("env2_x"));
jkummerow@chromium.org113035e2013-12-13 15:13:40 +00008865 CompileRun(
rossberg@chromium.org9ed27462014-01-07 14:16:41 +00008866 "function bound_x() { return x; }"
8867 "function get_x() { return this.x; }"
8868 "function get_x_w() { return (function() {return this.x;})(); }");
8869 env1->Global()->Set(v8_str("bound_x"), CompileRun("bound_x"));
jkummerow@chromium.org113035e2013-12-13 15:13:40 +00008870 env1->Global()->Set(v8_str("get_x"), CompileRun("get_x"));
8871 env1->Global()->Set(v8_str("get_x_w"), CompileRun("get_x_w"));
rossberg@chromium.org9ed27462014-01-07 14:16:41 +00008872 env1->Global()->Set(
8873 v8_str("this_x"),
8874 CompileRun("Object.getOwnPropertyDescriptor(this, 'this_x').get"));
jkummerow@chromium.org113035e2013-12-13 15:13:40 +00008875 }
8876
8877 Local<Object> env2_global = env2->Global();
8878 env2_global->TurnOnAccessCheck();
8879 env2->DetachGlobal();
8880
8881 Local<Value> result;
rossberg@chromium.org9ed27462014-01-07 14:16:41 +00008882 result = CompileRun("bound_x()");
8883 CHECK_EQ(v8_str("env2_x"), result);
jkummerow@chromium.org113035e2013-12-13 15:13:40 +00008884 result = CompileRun("get_x()");
8885 CHECK(result->IsUndefined());
8886 result = CompileRun("get_x_w()");
8887 CHECK(result->IsUndefined());
rossberg@chromium.org9ed27462014-01-07 14:16:41 +00008888 result = CompileRun("this_x()");
8889 CHECK_EQ(v8_str("env2_x"), result);
jkummerow@chromium.org113035e2013-12-13 15:13:40 +00008890
8891 // Reattach env2's proxy
8892 env2 = Context::New(env1->GetIsolate(),
8893 0,
8894 v8::Handle<v8::ObjectTemplate>(),
8895 env2_global);
8896 env2->SetSecurityToken(foo);
8897 {
8898 v8::Context::Scope scope(env2);
rossberg@chromium.org9ed27462014-01-07 14:16:41 +00008899 env2->Global()->Set(v8_str("x"), v8_str("env3_x"));
8900 env2->Global()->Set(v8_str("env1"), env1->Global());
8901 result = CompileRun(
8902 "results = [];"
8903 "for (var i = 0; i < 4; i++ ) {"
8904 " results.push(env1.bound_x());"
8905 " results.push(env1.get_x());"
8906 " results.push(env1.get_x_w());"
8907 " results.push(env1.this_x());"
8908 "}"
8909 "results");
8910 Local<v8::Array> results = Local<v8::Array>::Cast(result);
8911 CHECK_EQ(16, results->Length());
8912 for (int i = 0; i < 16; i += 4) {
8913 CHECK_EQ(v8_str("env2_x"), results->Get(i + 0));
8914 CHECK_EQ(v8_str("env1_x"), results->Get(i + 1));
8915 CHECK_EQ(v8_str("env3_x"), results->Get(i + 2));
8916 CHECK_EQ(v8_str("env2_x"), results->Get(i + 3));
8917 }
jkummerow@chromium.org113035e2013-12-13 15:13:40 +00008918 }
8919
rossberg@chromium.org9ed27462014-01-07 14:16:41 +00008920 result = CompileRun(
8921 "results = [];"
8922 "for (var i = 0; i < 4; i++ ) {"
8923 " results.push(bound_x());"
8924 " results.push(get_x());"
8925 " results.push(get_x_w());"
8926 " results.push(this_x());"
8927 "}"
8928 "results");
8929 Local<v8::Array> results = Local<v8::Array>::Cast(result);
8930 CHECK_EQ(16, results->Length());
8931 for (int i = 0; i < 16; i += 4) {
8932 CHECK_EQ(v8_str("env2_x"), results->Get(i + 0));
8933 CHECK_EQ(v8_str("env3_x"), results->Get(i + 1));
8934 CHECK_EQ(v8_str("env3_x"), results->Get(i + 2));
8935 CHECK_EQ(v8_str("env2_x"), results->Get(i + 3));
8936 }
8937
8938 result = CompileRun(
8939 "results = [];"
8940 "for (var i = 0; i < 4; i++ ) {"
8941 " results.push(this.bound_x());"
8942 " results.push(this.get_x());"
8943 " results.push(this.get_x_w());"
8944 " results.push(this.this_x());"
8945 "}"
8946 "results");
8947 results = Local<v8::Array>::Cast(result);
8948 CHECK_EQ(16, results->Length());
8949 for (int i = 0; i < 16; i += 4) {
8950 CHECK_EQ(v8_str("env2_x"), results->Get(i + 0));
8951 CHECK_EQ(v8_str("env1_x"), results->Get(i + 1));
8952 CHECK_EQ(v8_str("env3_x"), results->Get(i + 2));
8953 CHECK_EQ(v8_str("env2_x"), results->Get(i + 3));
8954 }
sgjesse@chromium.orgdf7a2842010-03-25 14:34:15 +00008955}
8956
8957
ricow@chromium.org83aa5492011-02-07 12:42:56 +00008958static bool allowed_access_type[v8::ACCESS_KEYS + 1] = { false };
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008959static bool NamedAccessBlocker(Local<v8::Object> global,
8960 Local<Value> name,
8961 v8::AccessType type,
8962 Local<Value> data) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00008963 return CcTest::isolate()->GetCurrentContext()->Global()->Equals(global) ||
ricow@chromium.org83aa5492011-02-07 12:42:56 +00008964 allowed_access_type[type];
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008965}
8966
8967
8968static bool IndexedAccessBlocker(Local<v8::Object> global,
8969 uint32_t key,
8970 v8::AccessType type,
8971 Local<Value> data) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00008972 return CcTest::isolate()->GetCurrentContext()->Global()->Equals(global) ||
ricow@chromium.org83aa5492011-02-07 12:42:56 +00008973 allowed_access_type[type];
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008974}
8975
8976
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00008977static int g_echo_value_1 = -1;
8978static int g_echo_value_2 = -1;
8979
8980
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00008981static void EchoGetter(
8982 Local<String> name,
8983 const v8::PropertyCallbackInfo<v8::Value>& info) {
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00008984 info.GetReturnValue().Set(v8_num(g_echo_value_1));
8985}
8986
8987
8988static void EchoGetter(const v8::FunctionCallbackInfo<v8::Value>& info) {
8989 info.GetReturnValue().Set(v8_num(g_echo_value_2));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008990}
8991
8992
8993static void EchoSetter(Local<String> name,
8994 Local<Value> value,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00008995 const v8::PropertyCallbackInfo<void>&) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00008996 if (value->IsNumber())
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00008997 g_echo_value_1 = value->Int32Value();
8998}
8999
9000
9001static void EchoSetter(const v8::FunctionCallbackInfo<v8::Value>& info) {
9002 v8::Handle<v8::Value> value = info[0];
9003 if (value->IsNumber())
9004 g_echo_value_2 = value->Int32Value();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009005}
9006
9007
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009008static void UnreachableGetter(
9009 Local<String> name,
9010 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009011 CHECK(false); // This function should not be called..
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009012}
9013
9014
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009015static void UnreachableSetter(Local<String>,
9016 Local<Value>,
9017 const v8::PropertyCallbackInfo<void>&) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009018 CHECK(false); // This function should nto be called.
9019}
9020
9021
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00009022static void UnreachableFunction(
9023 const v8::FunctionCallbackInfo<v8::Value>& info) {
9024 CHECK(false); // This function should not be called..
9025}
9026
9027
ricow@chromium.org83aa5492011-02-07 12:42:56 +00009028TEST(AccessControl) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00009029 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009030 v8::HandleScope handle_scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00009031 v8::Handle<v8::ObjectTemplate> global_template =
9032 v8::ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009033
9034 global_template->SetAccessCheckCallbacks(NamedAccessBlocker,
9035 IndexedAccessBlocker);
9036
9037 // Add an accessor accessible by cross-domain JS code.
9038 global_template->SetAccessor(
9039 v8_str("accessible_prop"),
9040 EchoGetter, EchoSetter,
9041 v8::Handle<Value>(),
9042 v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
9043
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00009044
9045 global_template->SetAccessorProperty(
9046 v8_str("accessible_js_prop"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00009047 v8::FunctionTemplate::New(isolate, EchoGetter),
9048 v8::FunctionTemplate::New(isolate, EchoSetter),
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00009049 v8::None,
9050 v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
9051
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009052 // Add an accessor that is not accessible by cross-domain JS code.
ager@chromium.org870a0b62008-11-04 11:43:05 +00009053 global_template->SetAccessor(v8_str("blocked_prop"),
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009054 UnreachableGetter, UnreachableSetter,
9055 v8::Handle<Value>(),
9056 v8::DEFAULT);
9057
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00009058 global_template->SetAccessorProperty(
9059 v8_str("blocked_js_prop"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00009060 v8::FunctionTemplate::New(isolate, UnreachableFunction),
9061 v8::FunctionTemplate::New(isolate, UnreachableFunction),
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00009062 v8::None,
9063 v8::DEFAULT);
9064
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009065 // Create an environment
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009066 v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009067 context0->Enter();
9068
9069 v8::Handle<v8::Object> global0 = context0->Global();
9070
ricow@chromium.org83aa5492011-02-07 12:42:56 +00009071 // Define a property with JS getter and setter.
9072 CompileRun(
9073 "function getter() { return 'getter'; };\n"
9074 "function setter() { return 'setter'; }\n"
9075 "Object.defineProperty(this, 'js_accessor_p', {get:getter, set:setter})");
9076
9077 Local<Value> getter = global0->Get(v8_str("getter"));
9078 Local<Value> setter = global0->Get(v8_str("setter"));
9079
9080 // And define normal element.
9081 global0->Set(239, v8_str("239"));
9082
9083 // Define an element with JS getter and setter.
9084 CompileRun(
9085 "function el_getter() { return 'el_getter'; };\n"
9086 "function el_setter() { return 'el_setter'; };\n"
9087 "Object.defineProperty(this, '42', {get: el_getter, set: el_setter});");
9088
9089 Local<Value> el_getter = global0->Get(v8_str("el_getter"));
9090 Local<Value> el_setter = global0->Get(v8_str("el_setter"));
9091
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009092 v8::HandleScope scope1(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009093
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009094 v8::Local<Context> context1 = Context::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009095 context1->Enter();
9096
9097 v8::Handle<v8::Object> global1 = context1->Global();
9098 global1->Set(v8_str("other"), global0);
9099
ricow@chromium.org83aa5492011-02-07 12:42:56 +00009100 // Access blocked property.
9101 CompileRun("other.blocked_prop = 1");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009102
ricow@chromium.org83aa5492011-02-07 12:42:56 +00009103 ExpectUndefined("other.blocked_prop");
9104 ExpectUndefined(
9105 "Object.getOwnPropertyDescriptor(other, 'blocked_prop')");
9106 ExpectFalse("propertyIsEnumerable.call(other, 'blocked_prop')");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009107
ricow@chromium.org83aa5492011-02-07 12:42:56 +00009108 // Enable ACCESS_HAS
9109 allowed_access_type[v8::ACCESS_HAS] = true;
9110 ExpectUndefined("other.blocked_prop");
9111 // ... and now we can get the descriptor...
9112 ExpectUndefined(
antonm@chromium.orgdca01352011-01-31 17:15:05 +00009113 "Object.getOwnPropertyDescriptor(other, 'blocked_prop').value");
ricow@chromium.org83aa5492011-02-07 12:42:56 +00009114 // ... and enumerate the property.
9115 ExpectTrue("propertyIsEnumerable.call(other, 'blocked_prop')");
9116 allowed_access_type[v8::ACCESS_HAS] = false;
antonm@chromium.orgdca01352011-01-31 17:15:05 +00009117
ricow@chromium.org83aa5492011-02-07 12:42:56 +00009118 // Access blocked element.
9119 CompileRun("other[239] = 1");
9120
9121 ExpectUndefined("other[239]");
9122 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '239')");
9123 ExpectFalse("propertyIsEnumerable.call(other, '239')");
9124
9125 // Enable ACCESS_HAS
9126 allowed_access_type[v8::ACCESS_HAS] = true;
9127 ExpectUndefined("other[239]");
9128 // ... and now we can get the descriptor...
9129 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '239').value");
9130 // ... and enumerate the property.
9131 ExpectTrue("propertyIsEnumerable.call(other, '239')");
9132 allowed_access_type[v8::ACCESS_HAS] = false;
9133
9134 // Access a property with JS accessor.
9135 CompileRun("other.js_accessor_p = 2");
9136
9137 ExpectUndefined("other.js_accessor_p");
9138 ExpectUndefined(
9139 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p')");
9140
9141 // Enable ACCESS_HAS.
9142 allowed_access_type[v8::ACCESS_HAS] = true;
9143 ExpectUndefined("other.js_accessor_p");
9144 ExpectUndefined(
9145 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get");
9146 ExpectUndefined(
9147 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set");
9148 ExpectUndefined(
9149 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
9150 allowed_access_type[v8::ACCESS_HAS] = false;
9151
9152 // Enable both ACCESS_HAS and ACCESS_GET.
9153 allowed_access_type[v8::ACCESS_HAS] = true;
9154 allowed_access_type[v8::ACCESS_GET] = true;
9155
9156 ExpectString("other.js_accessor_p", "getter");
9157 ExpectObject(
9158 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get", getter);
9159 ExpectUndefined(
9160 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set");
9161 ExpectUndefined(
9162 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
9163
9164 allowed_access_type[v8::ACCESS_GET] = false;
9165 allowed_access_type[v8::ACCESS_HAS] = false;
9166
9167 // Enable both ACCESS_HAS and ACCESS_SET.
9168 allowed_access_type[v8::ACCESS_HAS] = true;
9169 allowed_access_type[v8::ACCESS_SET] = true;
9170
9171 ExpectUndefined("other.js_accessor_p");
9172 ExpectUndefined(
9173 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get");
9174 ExpectObject(
9175 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set", setter);
9176 ExpectUndefined(
9177 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
9178
9179 allowed_access_type[v8::ACCESS_SET] = false;
9180 allowed_access_type[v8::ACCESS_HAS] = false;
9181
9182 // Enable both ACCESS_HAS, ACCESS_GET and ACCESS_SET.
9183 allowed_access_type[v8::ACCESS_HAS] = true;
9184 allowed_access_type[v8::ACCESS_GET] = true;
9185 allowed_access_type[v8::ACCESS_SET] = true;
9186
9187 ExpectString("other.js_accessor_p", "getter");
9188 ExpectObject(
9189 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get", getter);
9190 ExpectObject(
9191 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set", setter);
9192 ExpectUndefined(
9193 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
9194
9195 allowed_access_type[v8::ACCESS_SET] = false;
9196 allowed_access_type[v8::ACCESS_GET] = false;
9197 allowed_access_type[v8::ACCESS_HAS] = false;
9198
9199 // Access an element with JS accessor.
9200 CompileRun("other[42] = 2");
9201
9202 ExpectUndefined("other[42]");
9203 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42')");
9204
9205 // Enable ACCESS_HAS.
9206 allowed_access_type[v8::ACCESS_HAS] = true;
9207 ExpectUndefined("other[42]");
9208 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').get");
9209 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').set");
9210 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
9211 allowed_access_type[v8::ACCESS_HAS] = false;
9212
9213 // Enable both ACCESS_HAS and ACCESS_GET.
9214 allowed_access_type[v8::ACCESS_HAS] = true;
9215 allowed_access_type[v8::ACCESS_GET] = true;
9216
9217 ExpectString("other[42]", "el_getter");
9218 ExpectObject("Object.getOwnPropertyDescriptor(other, '42').get", el_getter);
9219 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').set");
9220 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
9221
9222 allowed_access_type[v8::ACCESS_GET] = false;
9223 allowed_access_type[v8::ACCESS_HAS] = false;
9224
9225 // Enable both ACCESS_HAS and ACCESS_SET.
9226 allowed_access_type[v8::ACCESS_HAS] = true;
9227 allowed_access_type[v8::ACCESS_SET] = true;
9228
9229 ExpectUndefined("other[42]");
9230 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').get");
9231 ExpectObject("Object.getOwnPropertyDescriptor(other, '42').set", el_setter);
9232 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
9233
9234 allowed_access_type[v8::ACCESS_SET] = false;
9235 allowed_access_type[v8::ACCESS_HAS] = false;
9236
9237 // Enable both ACCESS_HAS, ACCESS_GET and ACCESS_SET.
9238 allowed_access_type[v8::ACCESS_HAS] = true;
9239 allowed_access_type[v8::ACCESS_GET] = true;
9240 allowed_access_type[v8::ACCESS_SET] = true;
9241
9242 ExpectString("other[42]", "el_getter");
9243 ExpectObject("Object.getOwnPropertyDescriptor(other, '42').get", el_getter);
9244 ExpectObject("Object.getOwnPropertyDescriptor(other, '42').set", el_setter);
9245 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
9246
9247 allowed_access_type[v8::ACCESS_SET] = false;
9248 allowed_access_type[v8::ACCESS_GET] = false;
9249 allowed_access_type[v8::ACCESS_HAS] = false;
9250
9251 v8::Handle<Value> value;
ager@chromium.org870a0b62008-11-04 11:43:05 +00009252
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009253 // Access accessible property
antonm@chromium.orgdca01352011-01-31 17:15:05 +00009254 value = CompileRun("other.accessible_prop = 3");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009255 CHECK(value->IsNumber());
9256 CHECK_EQ(3, value->Int32Value());
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00009257 CHECK_EQ(3, g_echo_value_1);
9258
9259 // Access accessible js property
9260 value = CompileRun("other.accessible_js_prop = 3");
9261 CHECK(value->IsNumber());
9262 CHECK_EQ(3, value->Int32Value());
9263 CHECK_EQ(3, g_echo_value_2);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009264
antonm@chromium.orgdca01352011-01-31 17:15:05 +00009265 value = CompileRun("other.accessible_prop");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009266 CHECK(value->IsNumber());
9267 CHECK_EQ(3, value->Int32Value());
9268
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00009269 value = CompileRun("other.accessible_js_prop");
9270 CHECK(value->IsNumber());
9271 CHECK_EQ(3, value->Int32Value());
9272
antonm@chromium.orgdca01352011-01-31 17:15:05 +00009273 value = CompileRun(
9274 "Object.getOwnPropertyDescriptor(other, 'accessible_prop').value");
9275 CHECK(value->IsNumber());
9276 CHECK_EQ(3, value->Int32Value());
9277
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00009278 value = CompileRun(
9279 "Object.getOwnPropertyDescriptor(other, 'accessible_js_prop').get()");
9280 CHECK(value->IsNumber());
9281 CHECK_EQ(3, value->Int32Value());
9282
antonm@chromium.orgdca01352011-01-31 17:15:05 +00009283 value = CompileRun("propertyIsEnumerable.call(other, 'accessible_prop')");
ager@chromium.org870a0b62008-11-04 11:43:05 +00009284 CHECK(value->IsTrue());
9285
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00009286 value = CompileRun("propertyIsEnumerable.call(other, 'accessible_js_prop')");
9287 CHECK(value->IsTrue());
9288
ager@chromium.org870a0b62008-11-04 11:43:05 +00009289 // Enumeration doesn't enumerate accessors from inaccessible objects in
9290 // the prototype chain even if the accessors are in themselves accessible.
antonm@chromium.orgdca01352011-01-31 17:15:05 +00009291 value =
ager@chromium.org870a0b62008-11-04 11:43:05 +00009292 CompileRun("(function(){var obj = {'__proto__':other};"
9293 "for (var p in obj)"
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00009294 " if (p == 'accessible_prop' ||"
9295 " p == 'accessible_js_prop' ||"
9296 " p == 'blocked_js_prop' ||"
9297 " p == 'blocked_js_prop') {"
ager@chromium.org870a0b62008-11-04 11:43:05 +00009298 " return false;"
9299 " }"
9300 "return true;})()");
antonm@chromium.orgdca01352011-01-31 17:15:05 +00009301 CHECK(value->IsTrue());
ager@chromium.org870a0b62008-11-04 11:43:05 +00009302
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009303 context1->Exit();
9304 context0->Exit();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009305}
9306
9307
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00009308TEST(AccessControlES5) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00009309 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009310 v8::HandleScope handle_scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00009311 v8::Handle<v8::ObjectTemplate> global_template =
9312 v8::ObjectTemplate::New(isolate);
ricow@chromium.org65001782011-02-15 13:36:41 +00009313
9314 global_template->SetAccessCheckCallbacks(NamedAccessBlocker,
9315 IndexedAccessBlocker);
9316
ricow@chromium.orgf5a18a22011-03-15 10:00:20 +00009317 // Add accessible accessor.
9318 global_template->SetAccessor(
9319 v8_str("accessible_prop"),
9320 EchoGetter, EchoSetter,
9321 v8::Handle<Value>(),
9322 v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
9323
9324
ricow@chromium.org65001782011-02-15 13:36:41 +00009325 // Add an accessor that is not accessible by cross-domain JS code.
9326 global_template->SetAccessor(v8_str("blocked_prop"),
9327 UnreachableGetter, UnreachableSetter,
9328 v8::Handle<Value>(),
9329 v8::DEFAULT);
9330
9331 // Create an environment
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009332 v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
ricow@chromium.org65001782011-02-15 13:36:41 +00009333 context0->Enter();
9334
9335 v8::Handle<v8::Object> global0 = context0->Global();
9336
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009337 v8::Local<Context> context1 = Context::New(isolate);
ricow@chromium.org65001782011-02-15 13:36:41 +00009338 context1->Enter();
9339 v8::Handle<v8::Object> global1 = context1->Global();
9340 global1->Set(v8_str("other"), global0);
9341
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00009342 // Regression test for issue 1154.
ricow@chromium.org65001782011-02-15 13:36:41 +00009343 ExpectTrue("Object.keys(other).indexOf('blocked_prop') == -1");
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00009344
9345 ExpectUndefined("other.blocked_prop");
9346
9347 // Regression test for issue 1027.
9348 CompileRun("Object.defineProperty(\n"
9349 " other, 'blocked_prop', {configurable: false})");
9350 ExpectUndefined("other.blocked_prop");
9351 ExpectUndefined(
9352 "Object.getOwnPropertyDescriptor(other, 'blocked_prop')");
9353
9354 // Regression test for issue 1171.
9355 ExpectTrue("Object.isExtensible(other)");
9356 CompileRun("Object.preventExtensions(other)");
9357 ExpectTrue("Object.isExtensible(other)");
9358
9359 // Object.seal and Object.freeze.
9360 CompileRun("Object.freeze(other)");
9361 ExpectTrue("Object.isExtensible(other)");
9362
9363 CompileRun("Object.seal(other)");
9364 ExpectTrue("Object.isExtensible(other)");
ricow@chromium.orgf5a18a22011-03-15 10:00:20 +00009365
9366 // Regression test for issue 1250.
9367 // Make sure that we can set the accessible accessors value using normal
9368 // assignment.
9369 CompileRun("other.accessible_prop = 42");
jkummerow@chromium.org1e8da742013-08-26 17:13:35 +00009370 CHECK_EQ(42, g_echo_value_1);
ricow@chromium.orgf5a18a22011-03-15 10:00:20 +00009371
9372 v8::Handle<Value> value;
9373 // We follow Safari in ignoring assignments to host object accessors.
9374 CompileRun("Object.defineProperty(other, 'accessible_prop', {value: -1})");
9375 value = CompileRun("other.accessible_prop == 42");
9376 CHECK(value->IsTrue());
ricow@chromium.org65001782011-02-15 13:36:41 +00009377}
9378
9379
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00009380static bool GetOwnPropertyNamesNamedBlocker(Local<v8::Object> global,
9381 Local<Value> name,
9382 v8::AccessType type,
9383 Local<Value> data) {
9384 return false;
9385}
9386
9387
9388static bool GetOwnPropertyNamesIndexedBlocker(Local<v8::Object> global,
9389 uint32_t key,
9390 v8::AccessType type,
9391 Local<Value> data) {
9392 return false;
9393}
9394
9395
9396THREADED_TEST(AccessControlGetOwnPropertyNames) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00009397 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009398 v8::HandleScope handle_scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00009399 v8::Handle<v8::ObjectTemplate> obj_template =
9400 v8::ObjectTemplate::New(isolate);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00009401
ulan@chromium.org0f13e742014-01-03 15:51:11 +00009402 obj_template->Set(v8_str("x"), v8::Integer::New(isolate, 42));
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00009403 obj_template->SetAccessCheckCallbacks(GetOwnPropertyNamesNamedBlocker,
9404 GetOwnPropertyNamesIndexedBlocker);
9405
9406 // Create an environment
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009407 v8::Local<Context> context0 = Context::New(isolate, NULL, obj_template);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00009408 context0->Enter();
9409
9410 v8::Handle<v8::Object> global0 = context0->Global();
9411
machenbach@chromium.org528ce022013-09-23 14:09:36 +00009412 v8::HandleScope scope1(CcTest::isolate());
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00009413
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009414 v8::Local<Context> context1 = Context::New(isolate);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00009415 context1->Enter();
9416
9417 v8::Handle<v8::Object> global1 = context1->Global();
9418 global1->Set(v8_str("other"), global0);
9419 global1->Set(v8_str("object"), obj_template->NewInstance());
9420
9421 v8::Handle<Value> value;
9422
9423 // Attempt to get the property names of the other global object and
9424 // of an object that requires access checks. Accessing the other
9425 // global object should be blocked by access checks on the global
9426 // proxy object. Accessing the object that requires access checks
9427 // is blocked by the access checks on the object itself.
9428 value = CompileRun("Object.getOwnPropertyNames(other).length == 0");
9429 CHECK(value->IsTrue());
9430
9431 value = CompileRun("Object.getOwnPropertyNames(object).length == 0");
9432 CHECK(value->IsTrue());
9433
9434 context1->Exit();
9435 context0->Exit();
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00009436}
9437
9438
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009439static void IndexedPropertyEnumerator(
9440 const v8::PropertyCallbackInfo<v8::Array>& info) {
machenbach@chromium.org9f18d912013-11-28 13:42:41 +00009441 v8::Handle<v8::Array> result = v8::Array::New(info.GetIsolate(), 2);
ulan@chromium.org0f13e742014-01-03 15:51:11 +00009442 result->Set(0, v8::Integer::New(info.GetIsolate(), 7));
9443 result->Set(1, v8::Object::New(info.GetIsolate()));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009444 info.GetReturnValue().Set(result);
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +00009445}
9446
9447
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009448static void NamedPropertyEnumerator(
9449 const v8::PropertyCallbackInfo<v8::Array>& info) {
machenbach@chromium.org9f18d912013-11-28 13:42:41 +00009450 v8::Handle<v8::Array> result = v8::Array::New(info.GetIsolate(), 2);
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00009451 result->Set(0, v8_str("x"));
ulan@chromium.org0f13e742014-01-03 15:51:11 +00009452 result->Set(1, v8::Object::New(info.GetIsolate()));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009453 info.GetReturnValue().Set(result);
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00009454}
9455
9456
9457THREADED_TEST(GetOwnPropertyNamesWithInterceptor) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00009458 v8::Isolate* isolate = CcTest::isolate();
9459 v8::HandleScope handle_scope(isolate);
9460 v8::Handle<v8::ObjectTemplate> obj_template =
9461 v8::ObjectTemplate::New(isolate);
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00009462
ulan@chromium.org0f13e742014-01-03 15:51:11 +00009463 obj_template->Set(v8_str("7"), v8::Integer::New(CcTest::isolate(), 7));
9464 obj_template->Set(v8_str("x"), v8::Integer::New(CcTest::isolate(), 42));
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +00009465 obj_template->SetIndexedPropertyHandler(NULL, NULL, NULL, NULL,
9466 IndexedPropertyEnumerator);
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00009467 obj_template->SetNamedPropertyHandler(NULL, NULL, NULL, NULL,
9468 NamedPropertyEnumerator);
9469
9470 LocalContext context;
9471 v8::Handle<v8::Object> global = context->Global();
9472 global->Set(v8_str("object"), obj_template->NewInstance());
9473
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +00009474 v8::Handle<v8::Value> result =
9475 CompileRun("Object.getOwnPropertyNames(object)");
9476 CHECK(result->IsArray());
9477 v8::Handle<v8::Array> result_array = v8::Handle<v8::Array>::Cast(result);
9478 CHECK_EQ(3, result_array->Length());
9479 CHECK(result_array->Get(0)->IsString());
9480 CHECK(result_array->Get(1)->IsString());
9481 CHECK(result_array->Get(2)->IsString());
9482 CHECK_EQ(v8_str("7"), result_array->Get(0));
9483 CHECK_EQ(v8_str("[object Object]"), result_array->Get(1));
9484 CHECK_EQ(v8_str("x"), result_array->Get(2));
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00009485}
9486
9487
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009488static void ConstTenGetter(Local<String> name,
9489 const v8::PropertyCallbackInfo<v8::Value>& info) {
9490 info.GetReturnValue().Set(v8_num(10));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009491}
9492
9493
9494THREADED_TEST(CrossDomainAccessors) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +00009495 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009496 v8::HandleScope handle_scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009497
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00009498 v8::Handle<v8::FunctionTemplate> func_template =
9499 v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009500
9501 v8::Handle<v8::ObjectTemplate> global_template =
9502 func_template->InstanceTemplate();
9503
9504 v8::Handle<v8::ObjectTemplate> proto_template =
9505 func_template->PrototypeTemplate();
9506
9507 // Add an accessor to proto that's accessible by cross-domain JS code.
9508 proto_template->SetAccessor(v8_str("accessible"),
9509 ConstTenGetter, 0,
9510 v8::Handle<Value>(),
9511 v8::ALL_CAN_READ);
9512
9513 // Add an accessor that is not accessible by cross-domain JS code.
9514 global_template->SetAccessor(v8_str("unreachable"),
9515 UnreachableGetter, 0,
9516 v8::Handle<Value>(),
9517 v8::DEFAULT);
9518
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009519 v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009520 context0->Enter();
9521
9522 Local<v8::Object> global = context0->Global();
9523 // Add a normal property that shadows 'accessible'
9524 global->Set(v8_str("accessible"), v8_num(11));
9525
9526 // Enter a new context.
machenbach@chromium.org528ce022013-09-23 14:09:36 +00009527 v8::HandleScope scope1(CcTest::isolate());
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009528 v8::Local<Context> context1 = Context::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009529 context1->Enter();
9530
9531 v8::Handle<v8::Object> global1 = context1->Global();
9532 global1->Set(v8_str("other"), global);
9533
9534 // Should return 10, instead of 11
9535 v8::Handle<Value> value = v8_compile("other.accessible")->Run();
9536 CHECK(value->IsNumber());
9537 CHECK_EQ(10, value->Int32Value());
9538
9539 value = v8_compile("other.unreachable")->Run();
9540 CHECK(value->IsUndefined());
9541
9542 context1->Exit();
9543 context0->Exit();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009544}
9545
9546
9547static int named_access_count = 0;
9548static int indexed_access_count = 0;
9549
9550static bool NamedAccessCounter(Local<v8::Object> global,
9551 Local<Value> name,
9552 v8::AccessType type,
9553 Local<Value> data) {
9554 named_access_count++;
9555 return true;
9556}
9557
9558
9559static bool IndexedAccessCounter(Local<v8::Object> global,
9560 uint32_t key,
9561 v8::AccessType type,
9562 Local<Value> data) {
9563 indexed_access_count++;
9564 return true;
9565}
9566
9567
9568// This one is too easily disturbed by other tests.
9569TEST(AccessControlIC) {
9570 named_access_count = 0;
9571 indexed_access_count = 0;
9572
machenbach@chromium.org528ce022013-09-23 14:09:36 +00009573 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009574 v8::HandleScope handle_scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009575
9576 // Create an environment.
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009577 v8::Local<Context> context0 = Context::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009578 context0->Enter();
9579
9580 // Create an object that requires access-check functions to be
9581 // called for cross-domain access.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00009582 v8::Handle<v8::ObjectTemplate> object_template =
9583 v8::ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009584 object_template->SetAccessCheckCallbacks(NamedAccessCounter,
9585 IndexedAccessCounter);
9586 Local<v8::Object> object = object_template->NewInstance();
9587
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009588 v8::HandleScope scope1(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009589
9590 // Create another environment.
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009591 v8::Local<Context> context1 = Context::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009592 context1->Enter();
9593
9594 // Make easy access to the object from the other environment.
9595 v8::Handle<v8::Object> global1 = context1->Global();
9596 global1->Set(v8_str("obj"), object);
9597
9598 v8::Handle<Value> value;
9599
9600 // Check that the named access-control function is called every time.
ager@chromium.org8bb60582008-12-11 12:02:20 +00009601 CompileRun("function testProp(obj) {"
9602 " for (var i = 0; i < 10; i++) obj.prop = 1;"
9603 " for (var j = 0; j < 10; j++) obj.prop;"
9604 " return obj.prop"
9605 "}");
9606 value = CompileRun("testProp(obj)");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009607 CHECK(value->IsNumber());
9608 CHECK_EQ(1, value->Int32Value());
9609 CHECK_EQ(21, named_access_count);
9610
9611 // Check that the named access-control function is called every time.
ager@chromium.org8bb60582008-12-11 12:02:20 +00009612 CompileRun("var p = 'prop';"
9613 "function testKeyed(obj) {"
9614 " for (var i = 0; i < 10; i++) obj[p] = 1;"
9615 " for (var j = 0; j < 10; j++) obj[p];"
9616 " return obj[p];"
9617 "}");
9618 // Use obj which requires access checks. No inline caching is used
9619 // in that case.
9620 value = CompileRun("testKeyed(obj)");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009621 CHECK(value->IsNumber());
9622 CHECK_EQ(1, value->Int32Value());
9623 CHECK_EQ(42, named_access_count);
ager@chromium.org8bb60582008-12-11 12:02:20 +00009624 // Force the inline caches into generic state and try again.
9625 CompileRun("testKeyed({ a: 0 })");
9626 CompileRun("testKeyed({ b: 0 })");
9627 value = CompileRun("testKeyed(obj)");
9628 CHECK(value->IsNumber());
9629 CHECK_EQ(1, value->Int32Value());
9630 CHECK_EQ(63, named_access_count);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009631
9632 // Check that the indexed access-control function is called every time.
ager@chromium.org8bb60582008-12-11 12:02:20 +00009633 CompileRun("function testIndexed(obj) {"
9634 " for (var i = 0; i < 10; i++) obj[0] = 1;"
9635 " for (var j = 0; j < 10; j++) obj[0];"
9636 " return obj[0]"
9637 "}");
9638 value = CompileRun("testIndexed(obj)");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009639 CHECK(value->IsNumber());
9640 CHECK_EQ(1, value->Int32Value());
9641 CHECK_EQ(21, indexed_access_count);
ager@chromium.org8bb60582008-12-11 12:02:20 +00009642 // Force the inline caches into generic state.
9643 CompileRun("testIndexed(new Array(1))");
9644 // Test that the indexed access check is called.
9645 value = CompileRun("testIndexed(obj)");
9646 CHECK(value->IsNumber());
9647 CHECK_EQ(1, value->Int32Value());
9648 CHECK_EQ(42, indexed_access_count);
9649
9650 // Check that the named access check is called when invoking
9651 // functions on an object that requires access checks.
9652 CompileRun("obj.f = function() {}");
9653 CompileRun("function testCallNormal(obj) {"
9654 " for (var i = 0; i < 10; i++) obj.f();"
9655 "}");
9656 CompileRun("testCallNormal(obj)");
9657 CHECK_EQ(74, named_access_count);
9658
9659 // Force obj into slow case.
9660 value = CompileRun("delete obj.prop");
9661 CHECK(value->BooleanValue());
9662 // Force inline caches into dictionary probing mode.
9663 CompileRun("var o = { x: 0 }; delete o.x; testProp(o);");
9664 // Test that the named access check is called.
9665 value = CompileRun("testProp(obj);");
9666 CHECK(value->IsNumber());
9667 CHECK_EQ(1, value->Int32Value());
9668 CHECK_EQ(96, named_access_count);
9669
9670 // Force the call inline cache into dictionary probing mode.
9671 CompileRun("o.f = function() {}; testCallNormal(o)");
9672 // Test that the named access check is still called for each
9673 // invocation of the function.
9674 value = CompileRun("testCallNormal(obj)");
9675 CHECK_EQ(106, named_access_count);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009676
9677 context1->Exit();
9678 context0->Exit();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009679}
9680
9681
9682static bool NamedAccessFlatten(Local<v8::Object> global,
9683 Local<Value> name,
9684 v8::AccessType type,
9685 Local<Value> data) {
9686 char buf[100];
9687 int len;
9688
9689 CHECK(name->IsString());
9690
9691 memset(buf, 0x1, sizeof(buf));
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009692 len = name.As<String>()->WriteOneByte(reinterpret_cast<uint8_t*>(buf));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009693 CHECK_EQ(4, len);
9694
9695 uint16_t buf2[100];
9696
9697 memset(buf, 0x1, sizeof(buf));
ager@chromium.orgce5e87b2010-03-10 10:24:18 +00009698 len = name.As<String>()->Write(buf2);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009699 CHECK_EQ(4, len);
9700
9701 return true;
9702}
9703
9704
9705static bool IndexedAccessFlatten(Local<v8::Object> global,
9706 uint32_t key,
9707 v8::AccessType type,
9708 Local<Value> data) {
9709 return true;
9710}
9711
9712
9713// Regression test. In access checks, operations that may cause
9714// garbage collection are not allowed. It used to be the case that
9715// using the Write operation on a string could cause a garbage
9716// collection due to flattening of the string. This is no longer the
9717// case.
9718THREADED_TEST(AccessControlFlatten) {
9719 named_access_count = 0;
9720 indexed_access_count = 0;
9721
machenbach@chromium.org528ce022013-09-23 14:09:36 +00009722 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009723 v8::HandleScope handle_scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009724
9725 // Create an environment.
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009726 v8::Local<Context> context0 = Context::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009727 context0->Enter();
9728
9729 // Create an object that requires access-check functions to be
9730 // called for cross-domain access.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00009731 v8::Handle<v8::ObjectTemplate> object_template =
9732 v8::ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009733 object_template->SetAccessCheckCallbacks(NamedAccessFlatten,
9734 IndexedAccessFlatten);
9735 Local<v8::Object> object = object_template->NewInstance();
9736
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009737 v8::HandleScope scope1(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009738
9739 // Create another environment.
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009740 v8::Local<Context> context1 = Context::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009741 context1->Enter();
9742
9743 // Make easy access to the object from the other environment.
9744 v8::Handle<v8::Object> global1 = context1->Global();
9745 global1->Set(v8_str("obj"), object);
9746
9747 v8::Handle<Value> value;
9748
9749 value = v8_compile("var p = 'as' + 'df';")->Run();
9750 value = v8_compile("obj[p];")->Run();
9751
9752 context1->Exit();
9753 context0->Exit();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009754}
9755
9756
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009757static void AccessControlNamedGetter(
9758 Local<String>,
9759 const v8::PropertyCallbackInfo<v8::Value>& info) {
9760 info.GetReturnValue().Set(42);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009761}
9762
9763
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009764static void AccessControlNamedSetter(
9765 Local<String>,
9766 Local<Value> value,
9767 const v8::PropertyCallbackInfo<v8::Value>& info) {
9768 info.GetReturnValue().Set(value);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009769}
9770
9771
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009772static void AccessControlIndexedGetter(
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009773 uint32_t index,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009774 const v8::PropertyCallbackInfo<v8::Value>& info) {
9775 info.GetReturnValue().Set(v8_num(42));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009776}
9777
9778
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009779static void AccessControlIndexedSetter(
9780 uint32_t,
9781 Local<Value> value,
9782 const v8::PropertyCallbackInfo<v8::Value>& info) {
9783 info.GetReturnValue().Set(value);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009784}
9785
9786
9787THREADED_TEST(AccessControlInterceptorIC) {
9788 named_access_count = 0;
9789 indexed_access_count = 0;
9790
machenbach@chromium.org528ce022013-09-23 14:09:36 +00009791 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009792 v8::HandleScope handle_scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009793
9794 // Create an environment.
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009795 v8::Local<Context> context0 = Context::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009796 context0->Enter();
9797
9798 // Create an object that requires access-check functions to be
9799 // called for cross-domain access. The object also has interceptors
9800 // interceptor.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +00009801 v8::Handle<v8::ObjectTemplate> object_template =
9802 v8::ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009803 object_template->SetAccessCheckCallbacks(NamedAccessCounter,
9804 IndexedAccessCounter);
9805 object_template->SetNamedPropertyHandler(AccessControlNamedGetter,
9806 AccessControlNamedSetter);
9807 object_template->SetIndexedPropertyHandler(AccessControlIndexedGetter,
9808 AccessControlIndexedSetter);
9809 Local<v8::Object> object = object_template->NewInstance();
9810
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009811 v8::HandleScope scope1(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009812
9813 // Create another environment.
ulan@chromium.org57ff8812013-05-10 08:16:55 +00009814 v8::Local<Context> context1 = Context::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009815 context1->Enter();
9816
9817 // Make easy access to the object from the other environment.
9818 v8::Handle<v8::Object> global1 = context1->Global();
9819 global1->Set(v8_str("obj"), object);
9820
9821 v8::Handle<Value> value;
9822
9823 // Check that the named access-control function is called every time
9824 // eventhough there is an interceptor on the object.
9825 value = v8_compile("for (var i = 0; i < 10; i++) obj.x = 1;")->Run();
9826 value = v8_compile("for (var i = 0; i < 10; i++) obj.x;"
9827 "obj.x")->Run();
9828 CHECK(value->IsNumber());
9829 CHECK_EQ(42, value->Int32Value());
9830 CHECK_EQ(21, named_access_count);
9831
9832 value = v8_compile("var p = 'x';")->Run();
9833 value = v8_compile("for (var i = 0; i < 10; i++) obj[p] = 1;")->Run();
9834 value = v8_compile("for (var i = 0; i < 10; i++) obj[p];"
9835 "obj[p]")->Run();
9836 CHECK(value->IsNumber());
9837 CHECK_EQ(42, value->Int32Value());
9838 CHECK_EQ(42, named_access_count);
9839
9840 // Check that the indexed access-control function is called every
9841 // time eventhough there is an interceptor on the object.
9842 value = v8_compile("for (var i = 0; i < 10; i++) obj[0] = 1;")->Run();
9843 value = v8_compile("for (var i = 0; i < 10; i++) obj[0];"
9844 "obj[0]")->Run();
9845 CHECK(value->IsNumber());
9846 CHECK_EQ(42, value->Int32Value());
9847 CHECK_EQ(21, indexed_access_count);
9848
9849 context1->Exit();
9850 context0->Exit();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009851}
9852
9853
9854THREADED_TEST(Version) {
9855 v8::V8::GetVersion();
9856}
9857
9858
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009859static void InstanceFunctionCallback(
9860 const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009861 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009862 args.GetReturnValue().Set(v8_num(12));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009863}
9864
9865
9866THREADED_TEST(InstanceProperties) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009867 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00009868 v8::Isolate* isolate = context->GetIsolate();
9869 v8::HandleScope handle_scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009870
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00009871 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009872 Local<ObjectTemplate> instance = t->InstanceTemplate();
9873
9874 instance->Set(v8_str("x"), v8_num(42));
9875 instance->Set(v8_str("f"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00009876 v8::FunctionTemplate::New(isolate, InstanceFunctionCallback));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009877
9878 Local<Value> o = t->GetFunction()->NewInstance();
9879
9880 context->Global()->Set(v8_str("i"), o);
9881 Local<Value> value = Script::Compile(v8_str("i.x"))->Run();
9882 CHECK_EQ(42, value->Int32Value());
9883
9884 value = Script::Compile(v8_str("i.f()"))->Run();
9885 CHECK_EQ(12, value->Int32Value());
9886}
9887
9888
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009889static void GlobalObjectInstancePropertiesGet(
9890 Local<String> key,
9891 const v8::PropertyCallbackInfo<v8::Value>&) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009892 ApiTestFuzzer::Fuzz();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009893}
9894
9895
9896THREADED_TEST(GlobalObjectInstanceProperties) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00009897 v8::Isolate* isolate = CcTest::isolate();
9898 v8::HandleScope handle_scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009899
9900 Local<Value> global_object;
9901
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00009902 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009903 t->InstanceTemplate()->SetNamedPropertyHandler(
9904 GlobalObjectInstancePropertiesGet);
9905 Local<ObjectTemplate> instance_template = t->InstanceTemplate();
9906 instance_template->Set(v8_str("x"), v8_num(42));
9907 instance_template->Set(v8_str("f"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00009908 v8::FunctionTemplate::New(isolate,
9909 InstanceFunctionCallback));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009910
kasperl@chromium.orga5551262010-12-07 12:49:48 +00009911 // The script to check how Crankshaft compiles missing global function
9912 // invocations. function g is not defined and should throw on call.
9913 const char* script =
9914 "function wrapper(call) {"
9915 " var x = 0, y = 1;"
9916 " for (var i = 0; i < 1000; i++) {"
9917 " x += i * 100;"
9918 " y += i * 100;"
9919 " }"
9920 " if (call) g();"
9921 "}"
9922 "for (var i = 0; i < 17; i++) wrapper(false);"
9923 "var thrown = 0;"
9924 "try { wrapper(true); } catch (e) { thrown = 1; };"
9925 "thrown";
9926
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009927 {
9928 LocalContext env(NULL, instance_template);
9929 // Hold on to the global object so it can be used again in another
9930 // environment initialization.
9931 global_object = env->Global();
9932
9933 Local<Value> value = Script::Compile(v8_str("x"))->Run();
9934 CHECK_EQ(42, value->Int32Value());
9935 value = Script::Compile(v8_str("f()"))->Run();
9936 CHECK_EQ(12, value->Int32Value());
kasperl@chromium.orga5551262010-12-07 12:49:48 +00009937 value = Script::Compile(v8_str(script))->Run();
9938 CHECK_EQ(1, value->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009939 }
9940
9941 {
9942 // Create new environment reusing the global object.
9943 LocalContext env(NULL, instance_template, global_object);
9944 Local<Value> value = Script::Compile(v8_str("x"))->Run();
9945 CHECK_EQ(42, value->Int32Value());
9946 value = Script::Compile(v8_str("f()"))->Run();
9947 CHECK_EQ(12, value->Int32Value());
kasperl@chromium.orga5551262010-12-07 12:49:48 +00009948 value = Script::Compile(v8_str(script))->Run();
9949 CHECK_EQ(1, value->Int32Value());
9950 }
9951}
9952
9953
9954THREADED_TEST(CallKnownGlobalReceiver) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00009955 v8::Isolate* isolate = CcTest::isolate();
9956 v8::HandleScope handle_scope(isolate);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00009957
9958 Local<Value> global_object;
9959
hpayer@chromium.org4f99be92013-12-18 16:23:55 +00009960 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00009961 Local<ObjectTemplate> instance_template = t->InstanceTemplate();
9962
9963 // The script to check that we leave global object not
9964 // global object proxy on stack when we deoptimize from inside
9965 // arguments evaluation.
9966 // To provoke error we need to both force deoptimization
9967 // from arguments evaluation and to force CallIC to take
9968 // CallIC_Miss code path that can't cope with global proxy.
9969 const char* script =
9970 "function bar(x, y) { try { } finally { } }"
9971 "function baz(x) { try { } finally { } }"
9972 "function bom(x) { try { } finally { } }"
9973 "function foo(x) { bar([x], bom(2)); }"
9974 "for (var i = 0; i < 10000; i++) foo(1);"
9975 "foo";
9976
9977 Local<Value> foo;
9978 {
9979 LocalContext env(NULL, instance_template);
9980 // Hold on to the global object so it can be used again in another
9981 // environment initialization.
9982 global_object = env->Global();
9983 foo = Script::Compile(v8_str(script))->Run();
9984 }
9985
9986 {
9987 // Create new environment reusing the global object.
9988 LocalContext env(NULL, instance_template, global_object);
9989 env->Global()->Set(v8_str("foo"), foo);
yangguo@chromium.org659ceec2012-01-26 07:37:54 +00009990 Script::Compile(v8_str("foo()"))->Run();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009991 }
9992}
9993
9994
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009995static void ShadowFunctionCallback(
9996 const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009997 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00009998 args.GetReturnValue().Set(v8_num(42));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00009999}
10000
10001
10002static int shadow_y;
10003static int shadow_y_setter_call_count;
10004static int shadow_y_getter_call_count;
10005
10006
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010007static void ShadowYSetter(Local<String>,
10008 Local<Value>,
10009 const v8::PropertyCallbackInfo<void>&) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010010 shadow_y_setter_call_count++;
10011 shadow_y = 42;
10012}
10013
10014
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010015static void ShadowYGetter(Local<String> name,
10016 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010017 ApiTestFuzzer::Fuzz();
10018 shadow_y_getter_call_count++;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010019 info.GetReturnValue().Set(v8_num(shadow_y));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010020}
10021
10022
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010023static void ShadowIndexedGet(uint32_t index,
10024 const v8::PropertyCallbackInfo<v8::Value>&) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010025}
10026
10027
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010028static void ShadowNamedGet(Local<String> key,
10029 const v8::PropertyCallbackInfo<v8::Value>&) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010030}
10031
10032
10033THREADED_TEST(ShadowObject) {
10034 shadow_y = shadow_y_setter_call_count = shadow_y_getter_call_count = 0;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010035 v8::Isolate* isolate = CcTest::isolate();
10036 v8::HandleScope handle_scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010037
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000010038 Local<ObjectTemplate> global_template = v8::ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010039 LocalContext context(NULL, global_template);
10040
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010041 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010042 t->InstanceTemplate()->SetNamedPropertyHandler(ShadowNamedGet);
10043 t->InstanceTemplate()->SetIndexedPropertyHandler(ShadowIndexedGet);
10044 Local<ObjectTemplate> proto = t->PrototypeTemplate();
10045 Local<ObjectTemplate> instance = t->InstanceTemplate();
10046
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010047 proto->Set(v8_str("f"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010048 v8::FunctionTemplate::New(isolate,
10049 ShadowFunctionCallback,
10050 Local<Value>()));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010051 proto->Set(v8_str("x"), v8_num(12));
10052
10053 instance->SetAccessor(v8_str("y"), ShadowYGetter, ShadowYSetter);
10054
10055 Local<Value> o = t->GetFunction()->NewInstance();
10056 context->Global()->Set(v8_str("__proto__"), o);
10057
10058 Local<Value> value =
ricow@chromium.orgd2be9012011-06-01 06:00:58 +000010059 Script::Compile(v8_str("this.propertyIsEnumerable(0)"))->Run();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010060 CHECK(value->IsBoolean());
10061 CHECK(!value->BooleanValue());
10062
10063 value = Script::Compile(v8_str("x"))->Run();
10064 CHECK_EQ(12, value->Int32Value());
10065
10066 value = Script::Compile(v8_str("f()"))->Run();
10067 CHECK_EQ(42, value->Int32Value());
10068
mmassi@chromium.org7028c052012-06-13 11:51:58 +000010069 Script::Compile(v8_str("y = 43"))->Run();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010070 CHECK_EQ(1, shadow_y_setter_call_count);
10071 value = Script::Compile(v8_str("y"))->Run();
10072 CHECK_EQ(1, shadow_y_getter_call_count);
10073 CHECK_EQ(42, value->Int32Value());
10074}
10075
10076
10077THREADED_TEST(HiddenPrototype) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010078 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010079 v8::Isolate* isolate = context->GetIsolate();
10080 v8::HandleScope handle_scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010081
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010082 Local<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010083 t0->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010084 Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010085 t1->SetHiddenPrototype(true);
10086 t1->InstanceTemplate()->Set(v8_str("y"), v8_num(1));
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010087 Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010088 t2->SetHiddenPrototype(true);
10089 t2->InstanceTemplate()->Set(v8_str("z"), v8_num(2));
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010090 Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010091 t3->InstanceTemplate()->Set(v8_str("u"), v8_num(3));
10092
10093 Local<v8::Object> o0 = t0->GetFunction()->NewInstance();
10094 Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
10095 Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
10096 Local<v8::Object> o3 = t3->GetFunction()->NewInstance();
10097
10098 // Setting the prototype on an object skips hidden prototypes.
10099 CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
10100 o0->Set(v8_str("__proto__"), o1);
10101 CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
10102 CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
10103 o0->Set(v8_str("__proto__"), o2);
10104 CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
10105 CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
10106 CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
10107 o0->Set(v8_str("__proto__"), o3);
10108 CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
10109 CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
10110 CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
10111 CHECK_EQ(3, o0->Get(v8_str("u"))->Int32Value());
10112
10113 // Getting the prototype of o0 should get the first visible one
10114 // which is o3. Therefore, z should not be defined on the prototype
10115 // object.
10116 Local<Value> proto = o0->Get(v8_str("__proto__"));
10117 CHECK(proto->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000010118 CHECK(proto.As<v8::Object>()->Get(v8_str("z"))->IsUndefined());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010119}
10120
10121
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000010122THREADED_TEST(HiddenPrototypeSet) {
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000010123 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010124 v8::Isolate* isolate = context->GetIsolate();
10125 v8::HandleScope handle_scope(isolate);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000010126
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010127 Local<v8::FunctionTemplate> ot = v8::FunctionTemplate::New(isolate);
10128 Local<v8::FunctionTemplate> ht = v8::FunctionTemplate::New(isolate);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000010129 ht->SetHiddenPrototype(true);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010130 Local<v8::FunctionTemplate> pt = v8::FunctionTemplate::New(isolate);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000010131 ht->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
10132
10133 Local<v8::Object> o = ot->GetFunction()->NewInstance();
10134 Local<v8::Object> h = ht->GetFunction()->NewInstance();
10135 Local<v8::Object> p = pt->GetFunction()->NewInstance();
10136 o->Set(v8_str("__proto__"), h);
10137 h->Set(v8_str("__proto__"), p);
10138
10139 // Setting a property that exists on the hidden prototype goes there.
10140 o->Set(v8_str("x"), v8_num(7));
10141 CHECK_EQ(7, o->Get(v8_str("x"))->Int32Value());
10142 CHECK_EQ(7, h->Get(v8_str("x"))->Int32Value());
10143 CHECK(p->Get(v8_str("x"))->IsUndefined());
10144
10145 // Setting a new property should not be forwarded to the hidden prototype.
10146 o->Set(v8_str("y"), v8_num(6));
10147 CHECK_EQ(6, o->Get(v8_str("y"))->Int32Value());
10148 CHECK(h->Get(v8_str("y"))->IsUndefined());
10149 CHECK(p->Get(v8_str("y"))->IsUndefined());
10150
10151 // Setting a property that only exists on a prototype of the hidden prototype
10152 // is treated normally again.
10153 p->Set(v8_str("z"), v8_num(8));
10154 CHECK_EQ(8, o->Get(v8_str("z"))->Int32Value());
10155 CHECK_EQ(8, h->Get(v8_str("z"))->Int32Value());
10156 CHECK_EQ(8, p->Get(v8_str("z"))->Int32Value());
10157 o->Set(v8_str("z"), v8_num(9));
10158 CHECK_EQ(9, o->Get(v8_str("z"))->Int32Value());
10159 CHECK_EQ(8, h->Get(v8_str("z"))->Int32Value());
10160 CHECK_EQ(8, p->Get(v8_str("z"))->Int32Value());
10161}
10162
10163
10164// Regression test for issue 2457.
10165THREADED_TEST(HiddenPrototypeIdentityHash) {
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000010166 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000010167 v8::HandleScope handle_scope(context->GetIsolate());
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000010168
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010169 Handle<FunctionTemplate> t = FunctionTemplate::New(context->GetIsolate());
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000010170 t->SetHiddenPrototype(true);
10171 t->InstanceTemplate()->Set(v8_str("foo"), v8_num(75));
10172 Handle<Object> p = t->GetFunction()->NewInstance();
ulan@chromium.org0f13e742014-01-03 15:51:11 +000010173 Handle<Object> o = Object::New(context->GetIsolate());
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000010174 o->SetPrototype(p);
10175
10176 int hash = o->GetIdentityHash();
10177 USE(hash);
10178 o->Set(v8_str("foo"), v8_num(42));
10179 ASSERT_EQ(hash, o->GetIdentityHash());
10180}
10181
10182
ager@chromium.org5c838252010-02-19 08:53:10 +000010183THREADED_TEST(SetPrototype) {
ager@chromium.org5c838252010-02-19 08:53:10 +000010184 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010185 v8::Isolate* isolate = context->GetIsolate();
10186 v8::HandleScope handle_scope(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +000010187
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010188 Local<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +000010189 t0->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010190 Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +000010191 t1->SetHiddenPrototype(true);
10192 t1->InstanceTemplate()->Set(v8_str("y"), v8_num(1));
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010193 Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +000010194 t2->SetHiddenPrototype(true);
10195 t2->InstanceTemplate()->Set(v8_str("z"), v8_num(2));
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010196 Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +000010197 t3->InstanceTemplate()->Set(v8_str("u"), v8_num(3));
10198
10199 Local<v8::Object> o0 = t0->GetFunction()->NewInstance();
10200 Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
10201 Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
10202 Local<v8::Object> o3 = t3->GetFunction()->NewInstance();
10203
10204 // Setting the prototype on an object does not skip hidden prototypes.
10205 CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
10206 CHECK(o0->SetPrototype(o1));
10207 CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
10208 CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
10209 CHECK(o1->SetPrototype(o2));
10210 CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
10211 CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
10212 CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
10213 CHECK(o2->SetPrototype(o3));
10214 CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
10215 CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
10216 CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
10217 CHECK_EQ(3, o0->Get(v8_str("u"))->Int32Value());
10218
10219 // Getting the prototype of o0 should get the first visible one
10220 // which is o3. Therefore, z should not be defined on the prototype
10221 // object.
10222 Local<Value> proto = o0->Get(v8_str("__proto__"));
10223 CHECK(proto->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000010224 CHECK_EQ(proto.As<v8::Object>(), o3);
ager@chromium.org5c838252010-02-19 08:53:10 +000010225
10226 // However, Object::GetPrototype ignores hidden prototype.
10227 Local<Value> proto0 = o0->GetPrototype();
10228 CHECK(proto0->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000010229 CHECK_EQ(proto0.As<v8::Object>(), o1);
ager@chromium.org5c838252010-02-19 08:53:10 +000010230
10231 Local<Value> proto1 = o1->GetPrototype();
10232 CHECK(proto1->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000010233 CHECK_EQ(proto1.As<v8::Object>(), o2);
ager@chromium.org5c838252010-02-19 08:53:10 +000010234
10235 Local<Value> proto2 = o2->GetPrototype();
10236 CHECK(proto2->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000010237 CHECK_EQ(proto2.As<v8::Object>(), o3);
ager@chromium.org5c838252010-02-19 08:53:10 +000010238}
10239
10240
ricow@chromium.org27bf2882011-11-17 08:34:43 +000010241// Getting property names of an object with a prototype chain that
10242// triggers dictionary elements in GetLocalPropertyNames() shouldn't
10243// crash the runtime.
10244THREADED_TEST(Regress91517) {
10245 i::FLAG_allow_natives_syntax = true;
ricow@chromium.org27bf2882011-11-17 08:34:43 +000010246 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010247 v8::Isolate* isolate = context->GetIsolate();
10248 v8::HandleScope handle_scope(isolate);
ricow@chromium.org27bf2882011-11-17 08:34:43 +000010249
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010250 Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
ricow@chromium.org27bf2882011-11-17 08:34:43 +000010251 t1->SetHiddenPrototype(true);
10252 t1->InstanceTemplate()->Set(v8_str("foo"), v8_num(1));
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010253 Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
ricow@chromium.org27bf2882011-11-17 08:34:43 +000010254 t2->SetHiddenPrototype(true);
10255 t2->InstanceTemplate()->Set(v8_str("fuz1"), v8_num(2));
ulan@chromium.org0f13e742014-01-03 15:51:11 +000010256 t2->InstanceTemplate()->Set(v8_str("objects"), v8::Object::New(isolate));
ricow@chromium.org27bf2882011-11-17 08:34:43 +000010257 t2->InstanceTemplate()->Set(v8_str("fuz2"), v8_num(2));
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010258 Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
ricow@chromium.org27bf2882011-11-17 08:34:43 +000010259 t3->SetHiddenPrototype(true);
10260 t3->InstanceTemplate()->Set(v8_str("boo"), v8_num(3));
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010261 Local<v8::FunctionTemplate> t4 = v8::FunctionTemplate::New(isolate);
ricow@chromium.org27bf2882011-11-17 08:34:43 +000010262 t4->InstanceTemplate()->Set(v8_str("baz"), v8_num(4));
10263
10264 // Force dictionary-based properties.
10265 i::ScopedVector<char> name_buf(1024);
10266 for (int i = 1; i <= 1000; i++) {
10267 i::OS::SNPrintF(name_buf, "sdf%d", i);
10268 t2->InstanceTemplate()->Set(v8_str(name_buf.start()), v8_num(2));
10269 }
10270
10271 Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
10272 Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
10273 Local<v8::Object> o3 = t3->GetFunction()->NewInstance();
10274 Local<v8::Object> o4 = t4->GetFunction()->NewInstance();
10275
10276 // Create prototype chain of hidden prototypes.
10277 CHECK(o4->SetPrototype(o3));
10278 CHECK(o3->SetPrototype(o2));
10279 CHECK(o2->SetPrototype(o1));
10280
10281 // Call the runtime version of GetLocalPropertyNames() on the natively
10282 // created object through JavaScript.
10283 context->Global()->Set(v8_str("obj"), o4);
machenbach@chromium.org03453962014-01-10 14:16:31 +000010284 // PROPERTY_ATTRIBUTES_NONE = 0
10285 CompileRun("var names = %GetLocalPropertyNames(obj, 0);");
ricow@chromium.org27bf2882011-11-17 08:34:43 +000010286
10287 ExpectInt32("names.length", 1006);
10288 ExpectTrue("names.indexOf(\"baz\") >= 0");
10289 ExpectTrue("names.indexOf(\"boo\") >= 0");
10290 ExpectTrue("names.indexOf(\"foo\") >= 0");
10291 ExpectTrue("names.indexOf(\"fuz1\") >= 0");
10292 ExpectTrue("names.indexOf(\"fuz2\") >= 0");
10293 ExpectFalse("names[1005] == undefined");
10294}
10295
10296
ulan@chromium.org0f13e742014-01-03 15:51:11 +000010297// Getting property names of an object with a hidden and inherited
10298// prototype should not duplicate the accessor properties inherited.
10299THREADED_TEST(Regress269562) {
10300 i::FLAG_allow_natives_syntax = true;
10301 LocalContext context;
10302 v8::HandleScope handle_scope(context->GetIsolate());
10303
10304 Local<v8::FunctionTemplate> t1 =
10305 v8::FunctionTemplate::New(context->GetIsolate());
10306 t1->SetHiddenPrototype(true);
10307
10308 Local<v8::ObjectTemplate> i1 = t1->InstanceTemplate();
10309 i1->SetAccessor(v8_str("foo"),
10310 SimpleAccessorGetter, SimpleAccessorSetter);
10311 i1->SetAccessor(v8_str("bar"),
10312 SimpleAccessorGetter, SimpleAccessorSetter);
10313 i1->SetAccessor(v8_str("baz"),
10314 SimpleAccessorGetter, SimpleAccessorSetter);
10315 i1->Set(v8_str("n1"), v8_num(1));
10316 i1->Set(v8_str("n2"), v8_num(2));
10317
10318 Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
10319 Local<v8::FunctionTemplate> t2 =
10320 v8::FunctionTemplate::New(context->GetIsolate());
10321 t2->SetHiddenPrototype(true);
10322
10323 // Inherit from t1 and mark prototype as hidden.
10324 t2->Inherit(t1);
10325 t2->InstanceTemplate()->Set(v8_str("mine"), v8_num(4));
10326
10327 Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
10328 CHECK(o2->SetPrototype(o1));
10329
10330 v8::Local<v8::Symbol> sym = v8::Symbol::New(context->GetIsolate(), "s1");
10331 o1->Set(sym, v8_num(3));
10332 o1->SetHiddenValue(v8_str("h1"),
10333 v8::Integer::New(context->GetIsolate(), 2013));
10334
10335 // Call the runtime version of GetLocalPropertyNames() on
10336 // the natively created object through JavaScript.
10337 context->Global()->Set(v8_str("obj"), o2);
10338 context->Global()->Set(v8_str("sym"), sym);
machenbach@chromium.org03453962014-01-10 14:16:31 +000010339 // PROPERTY_ATTRIBUTES_NONE = 0
10340 CompileRun("var names = %GetLocalPropertyNames(obj, 0);");
ulan@chromium.org0f13e742014-01-03 15:51:11 +000010341
10342 ExpectInt32("names.length", 7);
10343 ExpectTrue("names.indexOf(\"foo\") >= 0");
10344 ExpectTrue("names.indexOf(\"bar\") >= 0");
10345 ExpectTrue("names.indexOf(\"baz\") >= 0");
10346 ExpectTrue("names.indexOf(\"n1\") >= 0");
10347 ExpectTrue("names.indexOf(\"n2\") >= 0");
10348 ExpectTrue("names.indexOf(sym) >= 0");
10349 ExpectTrue("names.indexOf(\"mine\") >= 0");
10350}
10351
10352
ricow@chromium.org2c99e282011-07-28 09:15:17 +000010353THREADED_TEST(FunctionReadOnlyPrototype) {
ager@chromium.org04921a82011-06-27 13:21:41 +000010354 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010355 v8::Isolate* isolate = context->GetIsolate();
10356 v8::HandleScope handle_scope(isolate);
ager@chromium.org04921a82011-06-27 13:21:41 +000010357
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010358 Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000010359 t1->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(isolate, 42));
ricow@chromium.org2c99e282011-07-28 09:15:17 +000010360 t1->ReadOnlyPrototype();
ager@chromium.org04921a82011-06-27 13:21:41 +000010361 context->Global()->Set(v8_str("func1"), t1->GetFunction());
ricow@chromium.org2c99e282011-07-28 09:15:17 +000010362 // Configured value of ReadOnly flag.
ager@chromium.org04921a82011-06-27 13:21:41 +000010363 CHECK(CompileRun(
10364 "(function() {"
10365 " descriptor = Object.getOwnPropertyDescriptor(func1, 'prototype');"
ricow@chromium.org2c99e282011-07-28 09:15:17 +000010366 " return (descriptor['writable'] == false);"
ager@chromium.org04921a82011-06-27 13:21:41 +000010367 "})()")->BooleanValue());
ricow@chromium.org2c99e282011-07-28 09:15:17 +000010368 CHECK_EQ(42, CompileRun("func1.prototype.x")->Int32Value());
10369 CHECK_EQ(42,
10370 CompileRun("func1.prototype = {}; func1.prototype.x")->Int32Value());
ager@chromium.org04921a82011-06-27 13:21:41 +000010371
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010372 Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000010373 t2->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(isolate, 42));
ager@chromium.org04921a82011-06-27 13:21:41 +000010374 context->Global()->Set(v8_str("func2"), t2->GetFunction());
ricow@chromium.org2c99e282011-07-28 09:15:17 +000010375 // Default value of ReadOnly flag.
ager@chromium.org04921a82011-06-27 13:21:41 +000010376 CHECK(CompileRun(
10377 "(function() {"
10378 " descriptor = Object.getOwnPropertyDescriptor(func2, 'prototype');"
ricow@chromium.org2c99e282011-07-28 09:15:17 +000010379 " return (descriptor['writable'] == true);"
ager@chromium.org04921a82011-06-27 13:21:41 +000010380 "})()")->BooleanValue());
ricow@chromium.org2c99e282011-07-28 09:15:17 +000010381 CHECK_EQ(42, CompileRun("func2.prototype.x")->Int32Value());
ager@chromium.org04921a82011-06-27 13:21:41 +000010382}
10383
10384
ager@chromium.org5c838252010-02-19 08:53:10 +000010385THREADED_TEST(SetPrototypeThrows) {
ager@chromium.org5c838252010-02-19 08:53:10 +000010386 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010387 v8::Isolate* isolate = context->GetIsolate();
10388 v8::HandleScope handle_scope(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +000010389
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010390 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +000010391
10392 Local<v8::Object> o0 = t->GetFunction()->NewInstance();
10393 Local<v8::Object> o1 = t->GetFunction()->NewInstance();
10394
10395 CHECK(o0->SetPrototype(o1));
10396 // If setting the prototype leads to the cycle, SetPrototype should
10397 // return false and keep VM in sane state.
10398 v8::TryCatch try_catch;
10399 CHECK(!o1->SetPrototype(o0));
10400 CHECK(!try_catch.HasCaught());
machenbach@chromium.org528ce022013-09-23 14:09:36 +000010401 ASSERT(!CcTest::i_isolate()->has_pending_exception());
ager@chromium.org5c838252010-02-19 08:53:10 +000010402
10403 CHECK_EQ(42, CompileRun("function f() { return 42; }; f()")->Int32Value());
10404}
10405
10406
verwaest@chromium.org662436e2013-08-28 08:41:27 +000010407THREADED_TEST(FunctionRemovePrototype) {
10408 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010409 v8::Isolate* isolate = context->GetIsolate();
10410 v8::HandleScope handle_scope(isolate);
verwaest@chromium.org662436e2013-08-28 08:41:27 +000010411
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010412 Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
verwaest@chromium.org662436e2013-08-28 08:41:27 +000010413 t1->RemovePrototype();
10414 Local<v8::Function> fun = t1->GetFunction();
10415 context->Global()->Set(v8_str("fun"), fun);
10416 CHECK(!CompileRun("'prototype' in fun")->BooleanValue());
10417
10418 v8::TryCatch try_catch;
10419 CompileRun("new fun()");
10420 CHECK(try_catch.HasCaught());
10421
10422 try_catch.Reset();
10423 fun->NewInstance();
10424 CHECK(try_catch.HasCaught());
10425}
10426
10427
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010428THREADED_TEST(GetterSetterExceptions) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010429 LocalContext context;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000010430 v8::Isolate* isolate = context->GetIsolate();
10431 v8::HandleScope handle_scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010432 CompileRun(
10433 "function Foo() { };"
10434 "function Throw() { throw 5; };"
10435 "var x = { };"
10436 "x.__defineSetter__('set', Throw);"
10437 "x.__defineGetter__('get', Throw);");
10438 Local<v8::Object> x =
10439 Local<v8::Object>::Cast(context->Global()->Get(v8_str("x")));
10440 v8::TryCatch try_catch;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000010441 x->Set(v8_str("set"), v8::Integer::New(isolate, 8));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010442 x->Get(v8_str("get"));
ulan@chromium.org0f13e742014-01-03 15:51:11 +000010443 x->Set(v8_str("set"), v8::Integer::New(isolate, 8));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010444 x->Get(v8_str("get"));
ulan@chromium.org0f13e742014-01-03 15:51:11 +000010445 x->Set(v8_str("set"), v8::Integer::New(isolate, 8));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010446 x->Get(v8_str("get"));
ulan@chromium.org0f13e742014-01-03 15:51:11 +000010447 x->Set(v8_str("set"), v8::Integer::New(isolate, 8));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010448 x->Get(v8_str("get"));
10449}
10450
10451
10452THREADED_TEST(Constructor) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010453 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010454 v8::Isolate* isolate = context->GetIsolate();
10455 v8::HandleScope handle_scope(isolate);
10456 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010457 templ->SetClassName(v8_str("Fun"));
10458 Local<Function> cons = templ->GetFunction();
10459 context->Global()->Set(v8_str("Fun"), cons);
10460 Local<v8::Object> inst = cons->NewInstance();
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000010461 i::Handle<i::JSObject> obj(v8::Utils::OpenHandle(*inst));
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000010462 CHECK(obj->IsJSObject());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010463 Local<Value> value = CompileRun("(new Fun()).constructor === Fun");
10464 CHECK(value->BooleanValue());
10465}
10466
lrn@chromium.org1c092762011-05-09 09:42:16 +000010467
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010468static void ConstructorCallback(
10469 const v8::FunctionCallbackInfo<v8::Value>& args) {
lrn@chromium.org1c092762011-05-09 09:42:16 +000010470 ApiTestFuzzer::Fuzz();
10471 Local<Object> This;
10472
10473 if (args.IsConstructCall()) {
10474 Local<Object> Holder = args.Holder();
ulan@chromium.org0f13e742014-01-03 15:51:11 +000010475 This = Object::New(args.GetIsolate());
lrn@chromium.org1c092762011-05-09 09:42:16 +000010476 Local<Value> proto = Holder->GetPrototype();
10477 if (proto->IsObject()) {
10478 This->SetPrototype(proto);
10479 }
10480 } else {
10481 This = args.This();
10482 }
10483
10484 This->Set(v8_str("a"), args[0]);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010485 args.GetReturnValue().Set(This);
lrn@chromium.org1c092762011-05-09 09:42:16 +000010486}
10487
10488
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010489static void FakeConstructorCallback(
10490 const v8::FunctionCallbackInfo<v8::Value>& args) {
lrn@chromium.org1c092762011-05-09 09:42:16 +000010491 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010492 args.GetReturnValue().Set(args[0]);
lrn@chromium.org1c092762011-05-09 09:42:16 +000010493}
10494
10495
10496THREADED_TEST(ConstructorForObject) {
lrn@chromium.org1c092762011-05-09 09:42:16 +000010497 LocalContext context;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000010498 v8::Isolate* isolate = context->GetIsolate();
10499 v8::HandleScope handle_scope(isolate);
lrn@chromium.org1c092762011-05-09 09:42:16 +000010500
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000010501 { Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
lrn@chromium.org1c092762011-05-09 09:42:16 +000010502 instance_template->SetCallAsFunctionHandler(ConstructorCallback);
10503 Local<Object> instance = instance_template->NewInstance();
10504 context->Global()->Set(v8_str("obj"), instance);
10505 v8::TryCatch try_catch;
10506 Local<Value> value;
10507 CHECK(!try_catch.HasCaught());
10508
10509 // Call the Object's constructor with a 32-bit signed integer.
10510 value = CompileRun("(function() { var o = new obj(28); return o.a; })()");
10511 CHECK(!try_catch.HasCaught());
10512 CHECK(value->IsInt32());
10513 CHECK_EQ(28, value->Int32Value());
10514
10515 Local<Value> args1[] = { v8_num(28) };
10516 Local<Value> value_obj1 = instance->CallAsConstructor(1, args1);
10517 CHECK(value_obj1->IsObject());
10518 Local<Object> object1 = Local<Object>::Cast(value_obj1);
10519 value = object1->Get(v8_str("a"));
10520 CHECK(value->IsInt32());
10521 CHECK(!try_catch.HasCaught());
10522 CHECK_EQ(28, value->Int32Value());
10523
10524 // Call the Object's constructor with a String.
10525 value = CompileRun(
10526 "(function() { var o = new obj('tipli'); return o.a; })()");
10527 CHECK(!try_catch.HasCaught());
10528 CHECK(value->IsString());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000010529 String::Utf8Value string_value1(value->ToString());
lrn@chromium.org1c092762011-05-09 09:42:16 +000010530 CHECK_EQ("tipli", *string_value1);
10531
10532 Local<Value> args2[] = { v8_str("tipli") };
10533 Local<Value> value_obj2 = instance->CallAsConstructor(1, args2);
10534 CHECK(value_obj2->IsObject());
10535 Local<Object> object2 = Local<Object>::Cast(value_obj2);
10536 value = object2->Get(v8_str("a"));
10537 CHECK(!try_catch.HasCaught());
10538 CHECK(value->IsString());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000010539 String::Utf8Value string_value2(value->ToString());
lrn@chromium.org1c092762011-05-09 09:42:16 +000010540 CHECK_EQ("tipli", *string_value2);
10541
10542 // Call the Object's constructor with a Boolean.
10543 value = CompileRun("(function() { var o = new obj(true); return o.a; })()");
10544 CHECK(!try_catch.HasCaught());
10545 CHECK(value->IsBoolean());
10546 CHECK_EQ(true, value->BooleanValue());
10547
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000010548 Handle<Value> args3[] = { v8::True(isolate) };
lrn@chromium.org1c092762011-05-09 09:42:16 +000010549 Local<Value> value_obj3 = instance->CallAsConstructor(1, args3);
10550 CHECK(value_obj3->IsObject());
10551 Local<Object> object3 = Local<Object>::Cast(value_obj3);
10552 value = object3->Get(v8_str("a"));
10553 CHECK(!try_catch.HasCaught());
10554 CHECK(value->IsBoolean());
10555 CHECK_EQ(true, value->BooleanValue());
10556
10557 // Call the Object's constructor with undefined.
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000010558 Handle<Value> args4[] = { v8::Undefined(isolate) };
lrn@chromium.org1c092762011-05-09 09:42:16 +000010559 Local<Value> value_obj4 = instance->CallAsConstructor(1, args4);
10560 CHECK(value_obj4->IsObject());
10561 Local<Object> object4 = Local<Object>::Cast(value_obj4);
10562 value = object4->Get(v8_str("a"));
10563 CHECK(!try_catch.HasCaught());
10564 CHECK(value->IsUndefined());
10565
10566 // Call the Object's constructor with null.
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000010567 Handle<Value> args5[] = { v8::Null(isolate) };
lrn@chromium.org1c092762011-05-09 09:42:16 +000010568 Local<Value> value_obj5 = instance->CallAsConstructor(1, args5);
10569 CHECK(value_obj5->IsObject());
10570 Local<Object> object5 = Local<Object>::Cast(value_obj5);
10571 value = object5->Get(v8_str("a"));
10572 CHECK(!try_catch.HasCaught());
10573 CHECK(value->IsNull());
10574 }
10575
10576 // Check exception handling when there is no constructor set for the Object.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000010577 { Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
lrn@chromium.org1c092762011-05-09 09:42:16 +000010578 Local<Object> instance = instance_template->NewInstance();
10579 context->Global()->Set(v8_str("obj2"), instance);
10580 v8::TryCatch try_catch;
10581 Local<Value> value;
10582 CHECK(!try_catch.HasCaught());
10583
10584 value = CompileRun("new obj2(28)");
10585 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000010586 String::Utf8Value exception_value1(try_catch.Exception());
lrn@chromium.org1c092762011-05-09 09:42:16 +000010587 CHECK_EQ("TypeError: object is not a function", *exception_value1);
10588 try_catch.Reset();
10589
10590 Local<Value> args[] = { v8_num(29) };
10591 value = instance->CallAsConstructor(1, args);
10592 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000010593 String::Utf8Value exception_value2(try_catch.Exception());
lrn@chromium.org1c092762011-05-09 09:42:16 +000010594 CHECK_EQ("TypeError: #<Object> is not a function", *exception_value2);
10595 try_catch.Reset();
10596 }
10597
10598 // Check the case when constructor throws exception.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000010599 { Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
lrn@chromium.org1c092762011-05-09 09:42:16 +000010600 instance_template->SetCallAsFunctionHandler(ThrowValue);
10601 Local<Object> instance = instance_template->NewInstance();
10602 context->Global()->Set(v8_str("obj3"), instance);
10603 v8::TryCatch try_catch;
10604 Local<Value> value;
10605 CHECK(!try_catch.HasCaught());
10606
10607 value = CompileRun("new obj3(22)");
10608 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000010609 String::Utf8Value exception_value1(try_catch.Exception());
lrn@chromium.org1c092762011-05-09 09:42:16 +000010610 CHECK_EQ("22", *exception_value1);
10611 try_catch.Reset();
10612
10613 Local<Value> args[] = { v8_num(23) };
10614 value = instance->CallAsConstructor(1, args);
10615 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000010616 String::Utf8Value exception_value2(try_catch.Exception());
lrn@chromium.org1c092762011-05-09 09:42:16 +000010617 CHECK_EQ("23", *exception_value2);
10618 try_catch.Reset();
10619 }
10620
10621 // Check whether constructor returns with an object or non-object.
10622 { Local<FunctionTemplate> function_template =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010623 FunctionTemplate::New(isolate, FakeConstructorCallback);
lrn@chromium.org1c092762011-05-09 09:42:16 +000010624 Local<Function> function = function_template->GetFunction();
10625 Local<Object> instance1 = function;
10626 context->Global()->Set(v8_str("obj4"), instance1);
10627 v8::TryCatch try_catch;
10628 Local<Value> value;
10629 CHECK(!try_catch.HasCaught());
10630
10631 CHECK(instance1->IsObject());
10632 CHECK(instance1->IsFunction());
10633
10634 value = CompileRun("new obj4(28)");
10635 CHECK(!try_catch.HasCaught());
10636 CHECK(value->IsObject());
10637
10638 Local<Value> args1[] = { v8_num(28) };
10639 value = instance1->CallAsConstructor(1, args1);
10640 CHECK(!try_catch.HasCaught());
10641 CHECK(value->IsObject());
10642
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000010643 Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
lrn@chromium.org1c092762011-05-09 09:42:16 +000010644 instance_template->SetCallAsFunctionHandler(FakeConstructorCallback);
10645 Local<Object> instance2 = instance_template->NewInstance();
10646 context->Global()->Set(v8_str("obj5"), instance2);
10647 CHECK(!try_catch.HasCaught());
10648
10649 CHECK(instance2->IsObject());
10650 CHECK(!instance2->IsFunction());
10651
10652 value = CompileRun("new obj5(28)");
10653 CHECK(!try_catch.HasCaught());
10654 CHECK(!value->IsObject());
10655
10656 Local<Value> args2[] = { v8_num(28) };
10657 value = instance2->CallAsConstructor(1, args2);
10658 CHECK(!try_catch.HasCaught());
10659 CHECK(!value->IsObject());
10660 }
10661}
10662
10663
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010664THREADED_TEST(FunctionDescriptorException) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010665 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010666 v8::Isolate* isolate = context->GetIsolate();
10667 v8::HandleScope handle_scope(isolate);
10668 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010669 templ->SetClassName(v8_str("Fun"));
10670 Local<Function> cons = templ->GetFunction();
10671 context->Global()->Set(v8_str("Fun"), cons);
10672 Local<Value> value = CompileRun(
10673 "function test() {"
10674 " try {"
10675 " (new Fun()).blah()"
10676 " } catch (e) {"
10677 " var str = String(e);"
machenbach@chromium.orga03ba1e2014-02-01 08:54:43 +000010678 // " if (str.indexOf('TypeError') == -1) return 1;"
10679 // " if (str.indexOf('[object Fun]') != -1) return 2;"
10680 // " if (str.indexOf('#<Fun>') == -1) return 3;"
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010681 " return 0;"
10682 " }"
10683 " return 4;"
10684 "}"
10685 "test();");
10686 CHECK_EQ(0, value->Int32Value());
10687}
10688
10689
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010690THREADED_TEST(EvalAliasedDynamic) {
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010691 LocalContext current;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000010692 v8::HandleScope scope(current->GetIsolate());
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010693
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010694 // Tests where aliased eval can only be resolved dynamically.
10695 Local<Script> script =
10696 Script::Compile(v8_str("function f(x) { "
10697 " var foo = 2;"
10698 " with (x) { return eval('foo'); }"
10699 "}"
10700 "foo = 0;"
10701 "result1 = f(new Object());"
ager@chromium.orge2902be2009-06-08 12:21:35 +000010702 "result2 = f(this);"
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010703 "var x = new Object();"
10704 "x.eval = function(x) { return 1; };"
10705 "result3 = f(x);"));
10706 script->Run();
10707 CHECK_EQ(2, current->Global()->Get(v8_str("result1"))->Int32Value());
10708 CHECK_EQ(0, current->Global()->Get(v8_str("result2"))->Int32Value());
10709 CHECK_EQ(1, current->Global()->Get(v8_str("result3"))->Int32Value());
10710
10711 v8::TryCatch try_catch;
10712 script =
10713 Script::Compile(v8_str("function f(x) { "
10714 " var bar = 2;"
10715 " with (x) { return eval('bar'); }"
10716 "}"
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000010717 "result4 = f(this)"));
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010718 script->Run();
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000010719 CHECK(!try_catch.HasCaught());
10720 CHECK_EQ(2, current->Global()->Get(v8_str("result4"))->Int32Value());
10721
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010722 try_catch.Reset();
10723}
10724
10725
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010726THREADED_TEST(CrossEval) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000010727 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010728 LocalContext other;
10729 LocalContext current;
10730
10731 Local<String> token = v8_str("<security token>");
10732 other->SetSecurityToken(token);
10733 current->SetSecurityToken(token);
10734
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000010735 // Set up reference from current to other.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010736 current->Global()->Set(v8_str("other"), other->Global());
10737
10738 // Check that new variables are introduced in other context.
10739 Local<Script> script =
10740 Script::Compile(v8_str("other.eval('var foo = 1234')"));
10741 script->Run();
10742 Local<Value> foo = other->Global()->Get(v8_str("foo"));
10743 CHECK_EQ(1234, foo->Int32Value());
10744 CHECK(!current->Global()->Has(v8_str("foo")));
10745
10746 // Check that writing to non-existing properties introduces them in
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010747 // the other context.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010748 script =
10749 Script::Compile(v8_str("other.eval('na = 1234')"));
10750 script->Run();
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010751 CHECK_EQ(1234, other->Global()->Get(v8_str("na"))->Int32Value());
10752 CHECK(!current->Global()->Has(v8_str("na")));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010753
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010754 // Check that global variables in current context are not visible in other
10755 // context.
10756 v8::TryCatch try_catch;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010757 script =
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010758 Script::Compile(v8_str("var bar = 42; other.eval('bar');"));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010759 Local<Value> result = script->Run();
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010760 CHECK(try_catch.HasCaught());
10761 try_catch.Reset();
10762
10763 // Check that local variables in current context are not visible in other
10764 // context.
10765 script =
10766 Script::Compile(v8_str("(function() { "
10767 " var baz = 87;"
10768 " return other.eval('baz');"
10769 "})();"));
10770 result = script->Run();
10771 CHECK(try_catch.HasCaught());
10772 try_catch.Reset();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010773
10774 // Check that global variables in the other environment are visible
10775 // when evaluting code.
10776 other->Global()->Set(v8_str("bis"), v8_num(1234));
10777 script = Script::Compile(v8_str("other.eval('bis')"));
10778 CHECK_EQ(1234, script->Run()->Int32Value());
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010779 CHECK(!try_catch.HasCaught());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010780
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010781 // Check that the 'this' pointer points to the global object evaluating
10782 // code.
10783 other->Global()->Set(v8_str("t"), other->Global());
10784 script = Script::Compile(v8_str("other.eval('this == t')"));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010785 result = script->Run();
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010786 CHECK(result->IsTrue());
10787 CHECK(!try_catch.HasCaught());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010788
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010789 // Check that variables introduced in with-statement are not visible in
10790 // other context.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010791 script =
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010792 Script::Compile(v8_str("with({x:2}){other.eval('x')}"));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010793 result = script->Run();
ager@chromium.orga74f0da2008-12-03 16:05:52 +000010794 CHECK(try_catch.HasCaught());
10795 try_catch.Reset();
ager@chromium.org3bf7b912008-11-17 09:09:45 +000010796
10797 // Check that you cannot use 'eval.call' with another object than the
10798 // current global object.
ager@chromium.org3bf7b912008-11-17 09:09:45 +000010799 script =
10800 Script::Compile(v8_str("other.y = 1; eval.call(other, 'y')"));
10801 result = script->Run();
10802 CHECK(try_catch.HasCaught());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010803}
10804
10805
ager@chromium.orge2902be2009-06-08 12:21:35 +000010806// Test that calling eval in a context which has been detached from
10807// its global throws an exception. This behavior is consistent with
10808// other JavaScript implementations.
10809THREADED_TEST(EvalInDetachedGlobal) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000010810 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000010811 v8::HandleScope scope(isolate);
ager@chromium.orge2902be2009-06-08 12:21:35 +000010812
ulan@chromium.org57ff8812013-05-10 08:16:55 +000010813 v8::Local<Context> context0 = Context::New(isolate);
10814 v8::Local<Context> context1 = Context::New(isolate);
ager@chromium.orge2902be2009-06-08 12:21:35 +000010815
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000010816 // Set up function in context0 that uses eval from context0.
ager@chromium.orge2902be2009-06-08 12:21:35 +000010817 context0->Enter();
10818 v8::Handle<v8::Value> fun =
10819 CompileRun("var x = 42;"
10820 "(function() {"
10821 " var e = eval;"
10822 " return function(s) { return e(s); }"
10823 "})()");
10824 context0->Exit();
10825
10826 // Put the function into context1 and call it before and after
10827 // detaching the global. Before detaching, the call succeeds and
10828 // after detaching and exception is thrown.
10829 context1->Enter();
10830 context1->Global()->Set(v8_str("fun"), fun);
10831 v8::Handle<v8::Value> x_value = CompileRun("fun('x')");
10832 CHECK_EQ(42, x_value->Int32Value());
10833 context0->DetachGlobal();
10834 v8::TryCatch catcher;
10835 x_value = CompileRun("fun('x')");
10836 CHECK(x_value.IsEmpty());
10837 CHECK(catcher.HasCaught());
10838 context1->Exit();
ager@chromium.orge2902be2009-06-08 12:21:35 +000010839}
10840
10841
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010842THREADED_TEST(CrossLazyLoad) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000010843 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010844 LocalContext other;
10845 LocalContext current;
10846
10847 Local<String> token = v8_str("<security token>");
10848 other->SetSecurityToken(token);
10849 current->SetSecurityToken(token);
10850
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000010851 // Set up reference from current to other.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010852 current->Global()->Set(v8_str("other"), other->Global());
10853
10854 // Trigger lazy loading in other context.
10855 Local<Script> script =
10856 Script::Compile(v8_str("other.eval('new Date(42)')"));
10857 Local<Value> value = script->Run();
10858 CHECK_EQ(42.0, value->NumberValue());
10859}
10860
10861
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010862static void call_as_function(const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010863 ApiTestFuzzer::Fuzz();
sgjesse@chromium.org05521fc2009-05-21 07:37:44 +000010864 if (args.IsConstructCall()) {
10865 if (args[0]->IsInt32()) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010866 args.GetReturnValue().Set(v8_num(-args[0]->Int32Value()));
10867 return;
sgjesse@chromium.org05521fc2009-05-21 07:37:44 +000010868 }
10869 }
10870
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000010871 args.GetReturnValue().Set(args[0]);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010872}
10873
10874
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +000010875static void ReturnThis(const v8::FunctionCallbackInfo<v8::Value>& args) {
10876 args.GetReturnValue().Set(args.This());
10877}
10878
10879
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010880// Test that a call handler can be set for objects which will allow
10881// non-function objects created through the API to be called as
10882// functions.
10883THREADED_TEST(CallAsFunction) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010884 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010885 v8::Isolate* isolate = context->GetIsolate();
10886 v8::HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010887
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010888 { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
lrn@chromium.org1c092762011-05-09 09:42:16 +000010889 Local<ObjectTemplate> instance_template = t->InstanceTemplate();
10890 instance_template->SetCallAsFunctionHandler(call_as_function);
10891 Local<v8::Object> instance = t->GetFunction()->NewInstance();
10892 context->Global()->Set(v8_str("obj"), instance);
10893 v8::TryCatch try_catch;
10894 Local<Value> value;
10895 CHECK(!try_catch.HasCaught());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010896
lrn@chromium.org1c092762011-05-09 09:42:16 +000010897 value = CompileRun("obj(42)");
10898 CHECK(!try_catch.HasCaught());
10899 CHECK_EQ(42, value->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010900
lrn@chromium.org1c092762011-05-09 09:42:16 +000010901 value = CompileRun("(function(o){return o(49)})(obj)");
10902 CHECK(!try_catch.HasCaught());
10903 CHECK_EQ(49, value->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010904
lrn@chromium.org1c092762011-05-09 09:42:16 +000010905 // test special case of call as function
10906 value = CompileRun("[obj]['0'](45)");
10907 CHECK(!try_catch.HasCaught());
10908 CHECK_EQ(45, value->Int32Value());
ager@chromium.org9258b6b2008-09-11 09:11:10 +000010909
lrn@chromium.org1c092762011-05-09 09:42:16 +000010910 value = CompileRun("obj.call = Function.prototype.call;"
10911 "obj.call(null, 87)");
10912 CHECK(!try_catch.HasCaught());
10913 CHECK_EQ(87, value->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010914
lrn@chromium.org1c092762011-05-09 09:42:16 +000010915 // Regression tests for bug #1116356: Calling call through call/apply
10916 // must work for non-function receivers.
10917 const char* apply_99 = "Function.prototype.call.apply(obj, [this, 99])";
10918 value = CompileRun(apply_99);
10919 CHECK(!try_catch.HasCaught());
10920 CHECK_EQ(99, value->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000010921
lrn@chromium.org1c092762011-05-09 09:42:16 +000010922 const char* call_17 = "Function.prototype.call.call(obj, this, 17)";
10923 value = CompileRun(call_17);
10924 CHECK(!try_catch.HasCaught());
10925 CHECK_EQ(17, value->Int32Value());
ager@chromium.org9085a012009-05-11 19:22:57 +000010926
lrn@chromium.org1c092762011-05-09 09:42:16 +000010927 // Check that the call-as-function handler can be called through
10928 // new.
10929 value = CompileRun("new obj(43)");
10930 CHECK(!try_catch.HasCaught());
10931 CHECK_EQ(-43, value->Int32Value());
10932
10933 // Check that the call-as-function handler can be called through
10934 // the API.
10935 v8::Handle<Value> args[] = { v8_num(28) };
10936 value = instance->CallAsFunction(instance, 1, args);
10937 CHECK(!try_catch.HasCaught());
10938 CHECK_EQ(28, value->Int32Value());
10939 }
10940
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010941 { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000010942 Local<ObjectTemplate> instance_template(t->InstanceTemplate());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000010943 USE(instance_template);
lrn@chromium.org1c092762011-05-09 09:42:16 +000010944 Local<v8::Object> instance = t->GetFunction()->NewInstance();
10945 context->Global()->Set(v8_str("obj2"), instance);
10946 v8::TryCatch try_catch;
10947 Local<Value> value;
10948 CHECK(!try_catch.HasCaught());
10949
10950 // Call an object without call-as-function handler through the JS
10951 value = CompileRun("obj2(28)");
10952 CHECK(value.IsEmpty());
10953 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000010954 String::Utf8Value exception_value1(try_catch.Exception());
machenbach@chromium.orga03ba1e2014-02-01 08:54:43 +000010955 // TODO(verwaest): Better message
10956 CHECK_EQ("TypeError: object is not a function",
lrn@chromium.org1c092762011-05-09 09:42:16 +000010957 *exception_value1);
10958 try_catch.Reset();
10959
10960 // Call an object without call-as-function handler through the API
10961 value = CompileRun("obj2(28)");
10962 v8::Handle<Value> args[] = { v8_num(28) };
10963 value = instance->CallAsFunction(instance, 1, args);
10964 CHECK(value.IsEmpty());
10965 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000010966 String::Utf8Value exception_value2(try_catch.Exception());
lrn@chromium.org1c092762011-05-09 09:42:16 +000010967 CHECK_EQ("TypeError: [object Object] is not a function", *exception_value2);
10968 try_catch.Reset();
10969 }
10970
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010971 { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
lrn@chromium.org1c092762011-05-09 09:42:16 +000010972 Local<ObjectTemplate> instance_template = t->InstanceTemplate();
10973 instance_template->SetCallAsFunctionHandler(ThrowValue);
10974 Local<v8::Object> instance = t->GetFunction()->NewInstance();
10975 context->Global()->Set(v8_str("obj3"), instance);
10976 v8::TryCatch try_catch;
10977 Local<Value> value;
10978 CHECK(!try_catch.HasCaught());
10979
10980 // Catch the exception which is thrown by call-as-function handler
10981 value = CompileRun("obj3(22)");
10982 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000010983 String::Utf8Value exception_value1(try_catch.Exception());
lrn@chromium.org1c092762011-05-09 09:42:16 +000010984 CHECK_EQ("22", *exception_value1);
10985 try_catch.Reset();
10986
10987 v8::Handle<Value> args[] = { v8_num(23) };
10988 value = instance->CallAsFunction(instance, 1, args);
10989 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000010990 String::Utf8Value exception_value2(try_catch.Exception());
lrn@chromium.org1c092762011-05-09 09:42:16 +000010991 CHECK_EQ("23", *exception_value2);
10992 try_catch.Reset();
10993 }
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +000010994
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000010995 { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +000010996 Local<ObjectTemplate> instance_template = t->InstanceTemplate();
10997 instance_template->SetCallAsFunctionHandler(ReturnThis);
10998 Local<v8::Object> instance = t->GetFunction()->NewInstance();
10999
11000 Local<v8::Value> a1 =
11001 instance->CallAsFunction(v8::Undefined(isolate), 0, NULL);
11002 CHECK(a1->StrictEquals(instance));
11003 Local<v8::Value> a2 =
11004 instance->CallAsFunction(v8::Null(isolate), 0, NULL);
11005 CHECK(a2->StrictEquals(instance));
11006 Local<v8::Value> a3 =
11007 instance->CallAsFunction(v8_num(42), 0, NULL);
11008 CHECK(a3->StrictEquals(instance));
11009 Local<v8::Value> a4 =
11010 instance->CallAsFunction(v8_str("hello"), 0, NULL);
11011 CHECK(a4->StrictEquals(instance));
11012 Local<v8::Value> a5 =
11013 instance->CallAsFunction(v8::True(isolate), 0, NULL);
11014 CHECK(a5->StrictEquals(instance));
11015 }
11016
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000011017 { CompileRun(
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +000011018 "function ReturnThisSloppy() {"
11019 " return this;"
11020 "}"
11021 "function ReturnThisStrict() {"
11022 " 'use strict';"
11023 " return this;"
11024 "}");
11025 Local<Function> ReturnThisSloppy =
11026 Local<Function>::Cast(
11027 context->Global()->Get(v8_str("ReturnThisSloppy")));
11028 Local<Function> ReturnThisStrict =
11029 Local<Function>::Cast(
11030 context->Global()->Get(v8_str("ReturnThisStrict")));
11031
11032 Local<v8::Value> a1 =
11033 ReturnThisSloppy->CallAsFunction(v8::Undefined(isolate), 0, NULL);
11034 CHECK(a1->StrictEquals(context->Global()));
11035 Local<v8::Value> a2 =
11036 ReturnThisSloppy->CallAsFunction(v8::Null(isolate), 0, NULL);
11037 CHECK(a2->StrictEquals(context->Global()));
11038 Local<v8::Value> a3 =
11039 ReturnThisSloppy->CallAsFunction(v8_num(42), 0, NULL);
11040 CHECK(a3->IsNumberObject());
11041 CHECK_EQ(42.0, a3.As<v8::NumberObject>()->ValueOf());
11042 Local<v8::Value> a4 =
11043 ReturnThisSloppy->CallAsFunction(v8_str("hello"), 0, NULL);
11044 CHECK(a4->IsStringObject());
11045 CHECK(a4.As<v8::StringObject>()->ValueOf()->StrictEquals(v8_str("hello")));
11046 Local<v8::Value> a5 =
11047 ReturnThisSloppy->CallAsFunction(v8::True(isolate), 0, NULL);
11048 CHECK(a5->IsBooleanObject());
11049 CHECK(a5.As<v8::BooleanObject>()->ValueOf());
11050
11051 Local<v8::Value> a6 =
11052 ReturnThisStrict->CallAsFunction(v8::Undefined(isolate), 0, NULL);
11053 CHECK(a6->IsUndefined());
11054 Local<v8::Value> a7 =
11055 ReturnThisStrict->CallAsFunction(v8::Null(isolate), 0, NULL);
11056 CHECK(a7->IsNull());
11057 Local<v8::Value> a8 =
11058 ReturnThisStrict->CallAsFunction(v8_num(42), 0, NULL);
11059 CHECK(a8->StrictEquals(v8_num(42)));
11060 Local<v8::Value> a9 =
11061 ReturnThisStrict->CallAsFunction(v8_str("hello"), 0, NULL);
11062 CHECK(a9->StrictEquals(v8_str("hello")));
11063 Local<v8::Value> a10 =
11064 ReturnThisStrict->CallAsFunction(v8::True(isolate), 0, NULL);
11065 CHECK(a10->StrictEquals(v8::True(isolate)));
11066 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011067}
11068
11069
karlklose@chromium.org83a47282011-05-11 11:54:09 +000011070// Check whether a non-function object is callable.
11071THREADED_TEST(CallableObject) {
karlklose@chromium.org83a47282011-05-11 11:54:09 +000011072 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000011073 v8::Isolate* isolate = context->GetIsolate();
11074 v8::HandleScope scope(isolate);
karlklose@chromium.org83a47282011-05-11 11:54:09 +000011075
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011076 { Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
karlklose@chromium.org83a47282011-05-11 11:54:09 +000011077 instance_template->SetCallAsFunctionHandler(call_as_function);
11078 Local<Object> instance = instance_template->NewInstance();
11079 v8::TryCatch try_catch;
11080
11081 CHECK(instance->IsCallable());
11082 CHECK(!try_catch.HasCaught());
11083 }
11084
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011085 { Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
karlklose@chromium.org83a47282011-05-11 11:54:09 +000011086 Local<Object> instance = instance_template->NewInstance();
11087 v8::TryCatch try_catch;
11088
11089 CHECK(!instance->IsCallable());
11090 CHECK(!try_catch.HasCaught());
11091 }
11092
11093 { Local<FunctionTemplate> function_template =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000011094 FunctionTemplate::New(isolate, call_as_function);
karlklose@chromium.org83a47282011-05-11 11:54:09 +000011095 Local<Function> function = function_template->GetFunction();
11096 Local<Object> instance = function;
11097 v8::TryCatch try_catch;
11098
11099 CHECK(instance->IsCallable());
11100 CHECK(!try_catch.HasCaught());
11101 }
11102
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000011103 { Local<FunctionTemplate> function_template = FunctionTemplate::New(isolate);
karlklose@chromium.org83a47282011-05-11 11:54:09 +000011104 Local<Function> function = function_template->GetFunction();
11105 Local<Object> instance = function;
11106 v8::TryCatch try_catch;
11107
11108 CHECK(instance->IsCallable());
11109 CHECK(!try_catch.HasCaught());
11110 }
11111}
11112
11113
machenbach@chromium.org4610c282014-01-09 10:39:51 +000011114static int Recurse(v8::Isolate* isolate, int depth, int iterations) {
11115 v8::HandleScope scope(isolate);
11116 if (depth == 0) return v8::HandleScope::NumberOfHandles(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011117 for (int i = 0; i < iterations; i++) {
machenbach@chromium.org4610c282014-01-09 10:39:51 +000011118 Local<v8::Number> n(v8::Integer::New(isolate, 42));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011119 }
machenbach@chromium.org4610c282014-01-09 10:39:51 +000011120 return Recurse(isolate, depth - 1, iterations);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011121}
11122
11123
11124THREADED_TEST(HandleIteration) {
11125 static const int kIterations = 500;
11126 static const int kNesting = 200;
machenbach@chromium.org4610c282014-01-09 10:39:51 +000011127 LocalContext context;
11128 v8::Isolate* isolate = context->GetIsolate();
11129 v8::HandleScope scope0(isolate);
11130 CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011131 {
machenbach@chromium.org4610c282014-01-09 10:39:51 +000011132 v8::HandleScope scope1(isolate);
11133 CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011134 for (int i = 0; i < kIterations; i++) {
ulan@chromium.org0f13e742014-01-03 15:51:11 +000011135 Local<v8::Number> n(v8::Integer::New(CcTest::isolate(), 42));
machenbach@chromium.org4610c282014-01-09 10:39:51 +000011136 CHECK_EQ(i + 1, v8::HandleScope::NumberOfHandles(isolate));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011137 }
11138
machenbach@chromium.org4610c282014-01-09 10:39:51 +000011139 CHECK_EQ(kIterations, v8::HandleScope::NumberOfHandles(isolate));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011140 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000011141 v8::HandleScope scope2(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011142 for (int j = 0; j < kIterations; j++) {
ulan@chromium.org0f13e742014-01-03 15:51:11 +000011143 Local<v8::Number> n(v8::Integer::New(CcTest::isolate(), 42));
machenbach@chromium.org4610c282014-01-09 10:39:51 +000011144 CHECK_EQ(j + 1 + kIterations,
11145 v8::HandleScope::NumberOfHandles(isolate));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011146 }
11147 }
machenbach@chromium.org4610c282014-01-09 10:39:51 +000011148 CHECK_EQ(kIterations, v8::HandleScope::NumberOfHandles(isolate));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011149 }
machenbach@chromium.org4610c282014-01-09 10:39:51 +000011150 CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
11151 CHECK_EQ(kNesting * kIterations, Recurse(isolate, kNesting, kIterations));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011152}
11153
11154
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011155static void InterceptorHasOwnPropertyGetter(
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011156 Local<String> name,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011157 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011158 ApiTestFuzzer::Fuzz();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011159}
11160
11161
11162THREADED_TEST(InterceptorHasOwnProperty) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011163 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000011164 v8::Isolate* isolate = context->GetIsolate();
11165 v8::HandleScope scope(isolate);
11166 Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011167 Local<v8::ObjectTemplate> instance_templ = fun_templ->InstanceTemplate();
11168 instance_templ->SetNamedPropertyHandler(InterceptorHasOwnPropertyGetter);
11169 Local<Function> function = fun_templ->GetFunction();
11170 context->Global()->Set(v8_str("constructor"), function);
11171 v8::Handle<Value> value = CompileRun(
11172 "var o = new constructor();"
11173 "o.hasOwnProperty('ostehaps');");
11174 CHECK_EQ(false, value->BooleanValue());
11175 value = CompileRun(
11176 "o.ostehaps = 42;"
11177 "o.hasOwnProperty('ostehaps');");
11178 CHECK_EQ(true, value->BooleanValue());
11179 value = CompileRun(
11180 "var p = new constructor();"
11181 "p.hasOwnProperty('ostehaps');");
11182 CHECK_EQ(false, value->BooleanValue());
11183}
11184
11185
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011186static void InterceptorHasOwnPropertyGetterGC(
ager@chromium.org9085a012009-05-11 19:22:57 +000011187 Local<String> name,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011188 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.org9085a012009-05-11 19:22:57 +000011189 ApiTestFuzzer::Fuzz();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000011190 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org9085a012009-05-11 19:22:57 +000011191}
11192
11193
11194THREADED_TEST(InterceptorHasOwnPropertyCausingGC) {
ager@chromium.org9085a012009-05-11 19:22:57 +000011195 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000011196 v8::Isolate* isolate = context->GetIsolate();
11197 v8::HandleScope scope(isolate);
11198 Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(isolate);
ager@chromium.org9085a012009-05-11 19:22:57 +000011199 Local<v8::ObjectTemplate> instance_templ = fun_templ->InstanceTemplate();
11200 instance_templ->SetNamedPropertyHandler(InterceptorHasOwnPropertyGetterGC);
11201 Local<Function> function = fun_templ->GetFunction();
11202 context->Global()->Set(v8_str("constructor"), function);
11203 // Let's first make some stuff so we can be sure to get a good GC.
11204 CompileRun(
11205 "function makestr(size) {"
11206 " switch (size) {"
11207 " case 1: return 'f';"
11208 " case 2: return 'fo';"
11209 " case 3: return 'foo';"
11210 " }"
11211 " return makestr(size >> 1) + makestr((size + 1) >> 1);"
11212 "}"
11213 "var x = makestr(12345);"
11214 "x = makestr(31415);"
11215 "x = makestr(23456);");
11216 v8::Handle<Value> value = CompileRun(
11217 "var o = new constructor();"
11218 "o.__proto__ = new String(x);"
11219 "o.hasOwnProperty('ostehaps');");
11220 CHECK_EQ(false, value->BooleanValue());
11221}
11222
11223
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011224typedef void (*NamedPropertyGetter)(
11225 Local<String> property,
11226 const v8::PropertyCallbackInfo<v8::Value>& info);
ager@chromium.orge2902be2009-06-08 12:21:35 +000011227
11228
11229static void CheckInterceptorLoadIC(NamedPropertyGetter getter,
11230 const char* source,
11231 int expected) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011232 v8::Isolate* isolate = CcTest::isolate();
11233 v8::HandleScope scope(isolate);
11234 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
vegorov@chromium.org21b5e952010-11-23 10:24:40 +000011235 templ->SetNamedPropertyHandler(getter, 0, 0, 0, 0, v8_str("data"));
ager@chromium.orge2902be2009-06-08 12:21:35 +000011236 LocalContext context;
11237 context->Global()->Set(v8_str("o"), templ->NewInstance());
11238 v8::Handle<Value> value = CompileRun(source);
11239 CHECK_EQ(expected, value->Int32Value());
11240}
11241
11242
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011243static void InterceptorLoadICGetter(
11244 Local<String> name,
11245 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011246 ApiTestFuzzer::Fuzz();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000011247 v8::Isolate* isolate = CcTest::isolate();
jkummerow@chromium.org28faa982012-04-13 09:58:30 +000011248 CHECK_EQ(isolate, info.GetIsolate());
vegorov@chromium.org21b5e952010-11-23 10:24:40 +000011249 CHECK_EQ(v8_str("data"), info.Data());
11250 CHECK_EQ(v8_str("x"), name);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000011251 info.GetReturnValue().Set(v8::Integer::New(isolate, 42));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011252}
11253
11254
11255// This test should hit the load IC for the interceptor case.
11256THREADED_TEST(InterceptorLoadIC) {
ager@chromium.orge2902be2009-06-08 12:21:35 +000011257 CheckInterceptorLoadIC(InterceptorLoadICGetter,
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011258 "var result = 0;"
11259 "for (var i = 0; i < 1000; i++) {"
11260 " result = o.x;"
ager@chromium.orge2902be2009-06-08 12:21:35 +000011261 "}",
11262 42);
11263}
11264
11265
11266// Below go several tests which verify that JITing for various
11267// configurations of interceptor and explicit fields works fine
11268// (those cases are special cased to get better performance).
11269
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011270static void InterceptorLoadXICGetter(
11271 Local<String> name,
11272 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.orge2902be2009-06-08 12:21:35 +000011273 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011274 info.GetReturnValue().Set(
11275 v8_str("x")->Equals(name) ?
ulan@chromium.org0f13e742014-01-03 15:51:11 +000011276 v8::Handle<v8::Value>(v8::Integer::New(info.GetIsolate(), 42)) :
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011277 v8::Handle<v8::Value>());
ager@chromium.orge2902be2009-06-08 12:21:35 +000011278}
11279
11280
11281THREADED_TEST(InterceptorLoadICWithFieldOnHolder) {
11282 CheckInterceptorLoadIC(InterceptorLoadXICGetter,
11283 "var result = 0;"
11284 "o.y = 239;"
11285 "for (var i = 0; i < 1000; i++) {"
11286 " result = o.y;"
11287 "}",
11288 239);
11289}
11290
11291
11292THREADED_TEST(InterceptorLoadICWithSubstitutedProto) {
11293 CheckInterceptorLoadIC(InterceptorLoadXICGetter,
11294 "var result = 0;"
11295 "o.__proto__ = { 'y': 239 };"
11296 "for (var i = 0; i < 1000; i++) {"
11297 " result = o.y + o.x;"
11298 "}",
11299 239 + 42);
11300}
11301
11302
11303THREADED_TEST(InterceptorLoadICWithPropertyOnProto) {
11304 CheckInterceptorLoadIC(InterceptorLoadXICGetter,
11305 "var result = 0;"
11306 "o.__proto__.y = 239;"
11307 "for (var i = 0; i < 1000; i++) {"
11308 " result = o.y + o.x;"
11309 "}",
11310 239 + 42);
11311}
11312
11313
11314THREADED_TEST(InterceptorLoadICUndefined) {
11315 CheckInterceptorLoadIC(InterceptorLoadXICGetter,
11316 "var result = 0;"
11317 "for (var i = 0; i < 1000; i++) {"
11318 " result = (o.y == undefined) ? 239 : 42;"
11319 "}",
11320 239);
11321}
11322
11323
11324THREADED_TEST(InterceptorLoadICWithOverride) {
11325 CheckInterceptorLoadIC(InterceptorLoadXICGetter,
11326 "fst = new Object(); fst.__proto__ = o;"
11327 "snd = new Object(); snd.__proto__ = fst;"
11328 "var result1 = 0;"
11329 "for (var i = 0; i < 1000; i++) {"
11330 " result1 = snd.x;"
11331 "}"
11332 "fst.x = 239;"
11333 "var result = 0;"
11334 "for (var i = 0; i < 1000; i++) {"
11335 " result = snd.x;"
11336 "}"
11337 "result + result1",
11338 239 + 42);
11339}
11340
11341
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011342// Test the case when we stored field into
11343// a stub, but interceptor produced value on its own.
11344THREADED_TEST(InterceptorLoadICFieldNotNeeded) {
11345 CheckInterceptorLoadIC(InterceptorLoadXICGetter,
11346 "proto = new Object();"
11347 "o.__proto__ = proto;"
11348 "proto.x = 239;"
11349 "for (var i = 0; i < 1000; i++) {"
11350 " o.x;"
11351 // Now it should be ICed and keep a reference to x defined on proto
11352 "}"
11353 "var result = 0;"
11354 "for (var i = 0; i < 1000; i++) {"
11355 " result += o.x;"
11356 "}"
11357 "result;",
11358 42 * 1000);
11359}
11360
11361
11362// Test the case when we stored field into
11363// a stub, but it got invalidated later on.
11364THREADED_TEST(InterceptorLoadICInvalidatedField) {
11365 CheckInterceptorLoadIC(InterceptorLoadXICGetter,
11366 "proto1 = new Object();"
11367 "proto2 = new Object();"
11368 "o.__proto__ = proto1;"
11369 "proto1.__proto__ = proto2;"
11370 "proto2.y = 239;"
11371 "for (var i = 0; i < 1000; i++) {"
11372 " o.y;"
11373 // Now it should be ICed and keep a reference to y defined on proto2
11374 "}"
11375 "proto1.y = 42;"
11376 "var result = 0;"
11377 "for (var i = 0; i < 1000; i++) {"
11378 " result += o.y;"
11379 "}"
11380 "result;",
11381 42 * 1000);
11382}
11383
11384
ager@chromium.orgb26c50a2010-03-26 09:27:16 +000011385static int interceptor_load_not_handled_calls = 0;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011386static void InterceptorLoadNotHandled(
11387 Local<String> name,
11388 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.orgb26c50a2010-03-26 09:27:16 +000011389 ++interceptor_load_not_handled_calls;
ager@chromium.orgb26c50a2010-03-26 09:27:16 +000011390}
11391
11392
11393// Test how post-interceptor lookups are done in the non-cacheable
11394// case: the interceptor should not be invoked during this lookup.
11395THREADED_TEST(InterceptorLoadICPostInterceptor) {
11396 interceptor_load_not_handled_calls = 0;
11397 CheckInterceptorLoadIC(InterceptorLoadNotHandled,
11398 "receiver = new Object();"
11399 "receiver.__proto__ = o;"
11400 "proto = new Object();"
11401 "/* Make proto a slow-case object. */"
11402 "for (var i = 0; i < 1000; i++) {"
11403 " proto[\"xxxxxxxx\" + i] = [];"
11404 "}"
11405 "proto.x = 17;"
11406 "o.__proto__ = proto;"
11407 "var result = 0;"
11408 "for (var i = 0; i < 1000; i++) {"
11409 " result += receiver.x;"
11410 "}"
11411 "result;",
11412 17 * 1000);
11413 CHECK_EQ(1000, interceptor_load_not_handled_calls);
11414}
11415
11416
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011417// Test the case when we stored field into
11418// a stub, but it got invalidated later on due to override on
11419// global object which is between interceptor and fields' holders.
11420THREADED_TEST(InterceptorLoadICInvalidatedFieldViaGlobal) {
11421 CheckInterceptorLoadIC(InterceptorLoadXICGetter,
11422 "o.__proto__ = this;" // set a global to be a proto of o.
11423 "this.__proto__.y = 239;"
11424 "for (var i = 0; i < 10; i++) {"
11425 " if (o.y != 239) throw 'oops: ' + o.y;"
11426 // Now it should be ICed and keep a reference to y defined on field_holder.
11427 "}"
11428 "this.y = 42;" // Assign on a global.
11429 "var result = 0;"
11430 "for (var i = 0; i < 10; i++) {"
11431 " result += o.y;"
11432 "}"
11433 "result;",
11434 42 * 10);
11435}
11436
11437
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011438static void SetOnThis(Local<String> name,
11439 Local<Value> value,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011440 const v8::PropertyCallbackInfo<void>& info) {
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011441 info.This()->ForceSet(name, value);
11442}
11443
11444
11445THREADED_TEST(InterceptorLoadICWithCallbackOnHolder) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011446 v8::Isolate* isolate = CcTest::isolate();
11447 v8::HandleScope scope(isolate);
11448 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011449 templ->SetNamedPropertyHandler(InterceptorLoadXICGetter);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011450 templ->SetAccessor(v8_str("y"), Return239Callback);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011451 LocalContext context;
11452 context->Global()->Set(v8_str("o"), templ->NewInstance());
ricow@chromium.org30ce4112010-05-31 10:38:25 +000011453
11454 // Check the case when receiver and interceptor's holder
11455 // are the same objects.
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011456 v8::Handle<Value> value = CompileRun(
11457 "var result = 0;"
11458 "for (var i = 0; i < 7; i++) {"
11459 " result = o.y;"
11460 "}");
11461 CHECK_EQ(239, value->Int32Value());
ricow@chromium.org30ce4112010-05-31 10:38:25 +000011462
11463 // Check the case when interceptor's holder is in proto chain
11464 // of receiver.
11465 value = CompileRun(
11466 "r = { __proto__: o };"
11467 "var result = 0;"
11468 "for (var i = 0; i < 7; i++) {"
11469 " result = r.y;"
11470 "}");
11471 CHECK_EQ(239, value->Int32Value());
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011472}
11473
11474
11475THREADED_TEST(InterceptorLoadICWithCallbackOnProto) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011476 v8::Isolate* isolate = CcTest::isolate();
11477 v8::HandleScope scope(isolate);
11478 v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011479 templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011480 v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New(isolate);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011481 templ_p->SetAccessor(v8_str("y"), Return239Callback);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011482
11483 LocalContext context;
11484 context->Global()->Set(v8_str("o"), templ_o->NewInstance());
11485 context->Global()->Set(v8_str("p"), templ_p->NewInstance());
11486
ricow@chromium.org30ce4112010-05-31 10:38:25 +000011487 // Check the case when receiver and interceptor's holder
11488 // are the same objects.
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011489 v8::Handle<Value> value = CompileRun(
11490 "o.__proto__ = p;"
11491 "var result = 0;"
11492 "for (var i = 0; i < 7; i++) {"
11493 " result = o.x + o.y;"
11494 "}");
11495 CHECK_EQ(239 + 42, value->Int32Value());
ricow@chromium.org30ce4112010-05-31 10:38:25 +000011496
11497 // Check the case when interceptor's holder is in proto chain
11498 // of receiver.
11499 value = CompileRun(
11500 "r = { __proto__: o };"
11501 "var result = 0;"
11502 "for (var i = 0; i < 7; i++) {"
11503 " result = r.x + r.y;"
11504 "}");
11505 CHECK_EQ(239 + 42, value->Int32Value());
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011506}
11507
11508
11509THREADED_TEST(InterceptorLoadICForCallbackWithOverride) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011510 v8::Isolate* isolate = CcTest::isolate();
11511 v8::HandleScope scope(isolate);
11512 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011513 templ->SetNamedPropertyHandler(InterceptorLoadXICGetter);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011514 templ->SetAccessor(v8_str("y"), Return239Callback);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011515
11516 LocalContext context;
11517 context->Global()->Set(v8_str("o"), templ->NewInstance());
11518
11519 v8::Handle<Value> value = CompileRun(
11520 "fst = new Object(); fst.__proto__ = o;"
11521 "snd = new Object(); snd.__proto__ = fst;"
11522 "var result1 = 0;"
11523 "for (var i = 0; i < 7; i++) {"
11524 " result1 = snd.x;"
11525 "}"
11526 "fst.x = 239;"
11527 "var result = 0;"
11528 "for (var i = 0; i < 7; i++) {"
11529 " result = snd.x;"
11530 "}"
11531 "result + result1");
11532 CHECK_EQ(239 + 42, value->Int32Value());
11533}
11534
11535
11536// Test the case when we stored callback into
11537// a stub, but interceptor produced value on its own.
11538THREADED_TEST(InterceptorLoadICCallbackNotNeeded) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011539 v8::Isolate* isolate = CcTest::isolate();
11540 v8::HandleScope scope(isolate);
11541 v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011542 templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011543 v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New(isolate);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011544 templ_p->SetAccessor(v8_str("y"), Return239Callback);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011545
11546 LocalContext context;
11547 context->Global()->Set(v8_str("o"), templ_o->NewInstance());
11548 context->Global()->Set(v8_str("p"), templ_p->NewInstance());
11549
11550 v8::Handle<Value> value = CompileRun(
11551 "o.__proto__ = p;"
11552 "for (var i = 0; i < 7; i++) {"
11553 " o.x;"
11554 // Now it should be ICed and keep a reference to x defined on p
11555 "}"
11556 "var result = 0;"
11557 "for (var i = 0; i < 7; i++) {"
11558 " result += o.x;"
11559 "}"
11560 "result");
11561 CHECK_EQ(42 * 7, value->Int32Value());
11562}
11563
11564
11565// Test the case when we stored callback into
11566// a stub, but it got invalidated later on.
11567THREADED_TEST(InterceptorLoadICInvalidatedCallback) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011568 v8::Isolate* isolate = CcTest::isolate();
11569 v8::HandleScope scope(isolate);
11570 v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011571 templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011572 v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New(isolate);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011573 templ_p->SetAccessor(v8_str("y"), Return239Callback, SetOnThis);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011574
11575 LocalContext context;
11576 context->Global()->Set(v8_str("o"), templ_o->NewInstance());
11577 context->Global()->Set(v8_str("p"), templ_p->NewInstance());
11578
11579 v8::Handle<Value> value = CompileRun(
11580 "inbetween = new Object();"
11581 "o.__proto__ = inbetween;"
11582 "inbetween.__proto__ = p;"
11583 "for (var i = 0; i < 10; i++) {"
11584 " o.y;"
11585 // Now it should be ICed and keep a reference to y defined on p
11586 "}"
11587 "inbetween.y = 42;"
11588 "var result = 0;"
11589 "for (var i = 0; i < 10; i++) {"
11590 " result += o.y;"
11591 "}"
11592 "result");
11593 CHECK_EQ(42 * 10, value->Int32Value());
11594}
11595
11596
11597// Test the case when we stored callback into
11598// a stub, but it got invalidated later on due to override on
11599// global object which is between interceptor and callbacks' holders.
11600THREADED_TEST(InterceptorLoadICInvalidatedCallbackViaGlobal) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011601 v8::Isolate* isolate = CcTest::isolate();
11602 v8::HandleScope scope(isolate);
11603 v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011604 templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011605 v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New(isolate);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011606 templ_p->SetAccessor(v8_str("y"), Return239Callback, SetOnThis);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011607
11608 LocalContext context;
11609 context->Global()->Set(v8_str("o"), templ_o->NewInstance());
11610 context->Global()->Set(v8_str("p"), templ_p->NewInstance());
11611
11612 v8::Handle<Value> value = CompileRun(
11613 "o.__proto__ = this;"
11614 "this.__proto__ = p;"
11615 "for (var i = 0; i < 10; i++) {"
11616 " if (o.y != 239) throw 'oops: ' + o.y;"
11617 // Now it should be ICed and keep a reference to y defined on p
11618 "}"
11619 "this.y = 42;"
11620 "var result = 0;"
11621 "for (var i = 0; i < 10; i++) {"
11622 " result += o.y;"
11623 "}"
11624 "result");
11625 CHECK_EQ(42 * 10, value->Int32Value());
11626}
11627
11628
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011629static void InterceptorLoadICGetter0(
11630 Local<String> name,
11631 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.orge2902be2009-06-08 12:21:35 +000011632 ApiTestFuzzer::Fuzz();
11633 CHECK(v8_str("x")->Equals(name));
ulan@chromium.org0f13e742014-01-03 15:51:11 +000011634 info.GetReturnValue().Set(v8::Integer::New(info.GetIsolate(), 0));
ager@chromium.orge2902be2009-06-08 12:21:35 +000011635}
11636
11637
11638THREADED_TEST(InterceptorReturningZero) {
11639 CheckInterceptorLoadIC(InterceptorLoadICGetter0,
11640 "o.x == undefined ? 1 : 0",
11641 0);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011642}
11643
11644
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011645static void InterceptorStoreICSetter(
11646 Local<String> key,
11647 Local<Value> value,
11648 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011649 CHECK(v8_str("x")->Equals(key));
11650 CHECK_EQ(42, value->Int32Value());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011651 info.GetReturnValue().Set(value);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011652}
11653
11654
11655// This test should hit the store IC for the interceptor case.
11656THREADED_TEST(InterceptorStoreIC) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011657 v8::Isolate* isolate = CcTest::isolate();
11658 v8::HandleScope scope(isolate);
11659 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011660 templ->SetNamedPropertyHandler(InterceptorLoadICGetter,
vegorov@chromium.org21b5e952010-11-23 10:24:40 +000011661 InterceptorStoreICSetter,
11662 0, 0, 0, v8_str("data"));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011663 LocalContext context;
11664 context->Global()->Set(v8_str("o"), templ->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000011665 CompileRun(
11666 "for (var i = 0; i < 1000; i++) {"
11667 " o.x = 42;"
11668 "}");
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011669}
11670
11671
ager@chromium.orgeadaf222009-06-16 09:43:10 +000011672THREADED_TEST(InterceptorStoreICWithNoSetter) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011673 v8::Isolate* isolate = CcTest::isolate();
11674 v8::HandleScope scope(isolate);
11675 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.orgeadaf222009-06-16 09:43:10 +000011676 templ->SetNamedPropertyHandler(InterceptorLoadXICGetter);
11677 LocalContext context;
11678 context->Global()->Set(v8_str("o"), templ->NewInstance());
11679 v8::Handle<Value> value = CompileRun(
11680 "for (var i = 0; i < 1000; i++) {"
11681 " o.y = 239;"
11682 "}"
11683 "42 + o.y");
11684 CHECK_EQ(239 + 42, value->Int32Value());
11685}
11686
11687
11688
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011689
11690v8::Handle<Value> call_ic_function;
11691v8::Handle<Value> call_ic_function2;
11692v8::Handle<Value> call_ic_function3;
11693
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011694static void InterceptorCallICGetter(
11695 Local<String> name,
11696 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011697 ApiTestFuzzer::Fuzz();
11698 CHECK(v8_str("x")->Equals(name));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011699 info.GetReturnValue().Set(call_ic_function);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011700}
11701
11702
11703// This test should hit the call IC for the interceptor case.
11704THREADED_TEST(InterceptorCallIC) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011705 v8::Isolate* isolate = CcTest::isolate();
11706 v8::HandleScope scope(isolate);
11707 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000011708 templ->SetNamedPropertyHandler(InterceptorCallICGetter);
11709 LocalContext context;
11710 context->Global()->Set(v8_str("o"), templ->NewInstance());
11711 call_ic_function =
11712 v8_compile("function f(x) { return x + 1; }; f")->Run();
11713 v8::Handle<Value> value = CompileRun(
11714 "var result = 0;"
11715 "for (var i = 0; i < 1000; i++) {"
11716 " result = o.x(41);"
11717 "}");
11718 CHECK_EQ(42, value->Int32Value());
11719}
11720
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011721
11722// This test checks that if interceptor doesn't provide
11723// a value, we can fetch regular value.
11724THREADED_TEST(InterceptorCallICSeesOthers) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011725 v8::Isolate* isolate = CcTest::isolate();
11726 v8::HandleScope scope(isolate);
11727 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011728 templ->SetNamedPropertyHandler(NoBlockGetterX);
11729 LocalContext context;
11730 context->Global()->Set(v8_str("o"), templ->NewInstance());
11731 v8::Handle<Value> value = CompileRun(
11732 "o.x = function f(x) { return x + 1; };"
11733 "var result = 0;"
11734 "for (var i = 0; i < 7; i++) {"
11735 " result = o.x(41);"
11736 "}");
11737 CHECK_EQ(42, value->Int32Value());
11738}
11739
11740
11741static v8::Handle<Value> call_ic_function4;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011742static void InterceptorCallICGetter4(
11743 Local<String> name,
11744 const v8::PropertyCallbackInfo<v8::Value>& info) {
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011745 ApiTestFuzzer::Fuzz();
11746 CHECK(v8_str("x")->Equals(name));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011747 info.GetReturnValue().Set(call_ic_function4);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011748}
11749
11750
11751// This test checks that if interceptor provides a function,
11752// even if we cached shadowed variant, interceptor's function
11753// is invoked
11754THREADED_TEST(InterceptorCallICCacheableNotNeeded) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011755 v8::Isolate* isolate = CcTest::isolate();
11756 v8::HandleScope scope(isolate);
11757 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011758 templ->SetNamedPropertyHandler(InterceptorCallICGetter4);
11759 LocalContext context;
11760 context->Global()->Set(v8_str("o"), templ->NewInstance());
11761 call_ic_function4 =
11762 v8_compile("function f(x) { return x - 1; }; f")->Run();
11763 v8::Handle<Value> value = CompileRun(
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +000011764 "Object.getPrototypeOf(o).x = function(x) { return x + 1; };"
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011765 "var result = 0;"
11766 "for (var i = 0; i < 1000; i++) {"
11767 " result = o.x(42);"
11768 "}");
11769 CHECK_EQ(41, value->Int32Value());
11770}
11771
11772
11773// Test the case when we stored cacheable lookup into
11774// a stub, but it got invalidated later on
11775THREADED_TEST(InterceptorCallICInvalidatedCacheable) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011776 v8::Isolate* isolate = CcTest::isolate();
11777 v8::HandleScope scope(isolate);
11778 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011779 templ->SetNamedPropertyHandler(NoBlockGetterX);
11780 LocalContext context;
11781 context->Global()->Set(v8_str("o"), templ->NewInstance());
11782 v8::Handle<Value> value = CompileRun(
11783 "proto1 = new Object();"
11784 "proto2 = new Object();"
11785 "o.__proto__ = proto1;"
11786 "proto1.__proto__ = proto2;"
11787 "proto2.y = function(x) { return x + 1; };"
11788 // Invoke it many times to compile a stub
11789 "for (var i = 0; i < 7; i++) {"
11790 " o.y(42);"
11791 "}"
11792 "proto1.y = function(x) { return x - 1; };"
11793 "var result = 0;"
11794 "for (var i = 0; i < 7; i++) {"
11795 " result += o.y(42);"
11796 "}");
11797 CHECK_EQ(41 * 7, value->Int32Value());
11798}
11799
11800
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011801// This test checks that if interceptor doesn't provide a function,
11802// cached constant function is used
11803THREADED_TEST(InterceptorCallICConstantFunctionUsed) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011804 v8::Isolate* isolate = CcTest::isolate();
11805 v8::HandleScope scope(isolate);
11806 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011807 templ->SetNamedPropertyHandler(NoBlockGetterX);
11808 LocalContext context;
11809 context->Global()->Set(v8_str("o"), templ->NewInstance());
11810 v8::Handle<Value> value = CompileRun(
11811 "function inc(x) { return x + 1; };"
11812 "inc(1);"
11813 "o.x = inc;"
11814 "var result = 0;"
11815 "for (var i = 0; i < 1000; i++) {"
11816 " result = o.x(42);"
11817 "}");
11818 CHECK_EQ(43, value->Int32Value());
11819}
11820
11821
ulan@chromium.org2efb9002012-01-19 15:36:35 +000011822static v8::Handle<Value> call_ic_function5;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011823static void InterceptorCallICGetter5(
11824 Local<String> name,
11825 const v8::PropertyCallbackInfo<v8::Value>& info) {
ulan@chromium.org2efb9002012-01-19 15:36:35 +000011826 ApiTestFuzzer::Fuzz();
11827 if (v8_str("x")->Equals(name))
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011828 info.GetReturnValue().Set(call_ic_function5);
ulan@chromium.org2efb9002012-01-19 15:36:35 +000011829}
11830
11831
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011832// This test checks that if interceptor provides a function,
11833// even if we cached constant function, interceptor's function
11834// is invoked
11835THREADED_TEST(InterceptorCallICConstantFunctionNotNeeded) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011836 v8::Isolate* isolate = CcTest::isolate();
11837 v8::HandleScope scope(isolate);
11838 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011839 templ->SetNamedPropertyHandler(InterceptorCallICGetter5);
11840 LocalContext context;
11841 context->Global()->Set(v8_str("o"), templ->NewInstance());
11842 call_ic_function5 =
11843 v8_compile("function f(x) { return x - 1; }; f")->Run();
11844 v8::Handle<Value> value = CompileRun(
11845 "function inc(x) { return x + 1; };"
11846 "inc(1);"
11847 "o.x = inc;"
11848 "var result = 0;"
11849 "for (var i = 0; i < 1000; i++) {"
11850 " result = o.x(42);"
11851 "}");
11852 CHECK_EQ(41, value->Int32Value());
11853}
11854
11855
ulan@chromium.org2efb9002012-01-19 15:36:35 +000011856static v8::Handle<Value> call_ic_function6;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011857static void InterceptorCallICGetter6(
11858 Local<String> name,
11859 const v8::PropertyCallbackInfo<v8::Value>& info) {
ulan@chromium.org2efb9002012-01-19 15:36:35 +000011860 ApiTestFuzzer::Fuzz();
11861 if (v8_str("x")->Equals(name))
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011862 info.GetReturnValue().Set(call_ic_function6);
ulan@chromium.org2efb9002012-01-19 15:36:35 +000011863}
11864
11865
11866// Same test as above, except the code is wrapped in a function
11867// to test the optimized compiler.
11868THREADED_TEST(InterceptorCallICConstantFunctionNotNeededWrapped) {
11869 i::FLAG_allow_natives_syntax = true;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011870 v8::Isolate* isolate = CcTest::isolate();
11871 v8::HandleScope scope(isolate);
11872 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
ulan@chromium.org2efb9002012-01-19 15:36:35 +000011873 templ->SetNamedPropertyHandler(InterceptorCallICGetter6);
11874 LocalContext context;
11875 context->Global()->Set(v8_str("o"), templ->NewInstance());
11876 call_ic_function6 =
11877 v8_compile("function f(x) { return x - 1; }; f")->Run();
11878 v8::Handle<Value> value = CompileRun(
11879 "function inc(x) { return x + 1; };"
11880 "inc(1);"
11881 "o.x = inc;"
11882 "function test() {"
11883 " var result = 0;"
11884 " for (var i = 0; i < 1000; i++) {"
11885 " result = o.x(42);"
11886 " }"
11887 " return result;"
11888 "};"
11889 "test();"
11890 "test();"
11891 "test();"
11892 "%OptimizeFunctionOnNextCall(test);"
11893 "test()");
11894 CHECK_EQ(41, value->Int32Value());
11895}
11896
11897
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011898// Test the case when we stored constant function into
11899// a stub, but it got invalidated later on
11900THREADED_TEST(InterceptorCallICInvalidatedConstantFunction) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011901 v8::Isolate* isolate = CcTest::isolate();
11902 v8::HandleScope scope(isolate);
11903 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011904 templ->SetNamedPropertyHandler(NoBlockGetterX);
11905 LocalContext context;
11906 context->Global()->Set(v8_str("o"), templ->NewInstance());
11907 v8::Handle<Value> value = CompileRun(
11908 "function inc(x) { return x + 1; };"
11909 "inc(1);"
11910 "proto1 = new Object();"
11911 "proto2 = new Object();"
11912 "o.__proto__ = proto1;"
11913 "proto1.__proto__ = proto2;"
11914 "proto2.y = inc;"
11915 // Invoke it many times to compile a stub
11916 "for (var i = 0; i < 7; i++) {"
11917 " o.y(42);"
11918 "}"
11919 "proto1.y = function(x) { return x - 1; };"
11920 "var result = 0;"
11921 "for (var i = 0; i < 7; i++) {"
11922 " result += o.y(42);"
11923 "}");
11924 CHECK_EQ(41 * 7, value->Int32Value());
11925}
11926
11927
11928// Test the case when we stored constant function into
11929// a stub, but it got invalidated later on due to override on
11930// global object which is between interceptor and constant function' holders.
11931THREADED_TEST(InterceptorCallICInvalidatedConstantFunctionViaGlobal) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011932 v8::Isolate* isolate = CcTest::isolate();
11933 v8::HandleScope scope(isolate);
11934 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
kasperl@chromium.orge959c182009-07-27 08:59:04 +000011935 templ->SetNamedPropertyHandler(NoBlockGetterX);
11936 LocalContext context;
11937 context->Global()->Set(v8_str("o"), templ->NewInstance());
11938 v8::Handle<Value> value = CompileRun(
11939 "function inc(x) { return x + 1; };"
11940 "inc(1);"
11941 "o.__proto__ = this;"
11942 "this.__proto__.y = inc;"
11943 // Invoke it many times to compile a stub
11944 "for (var i = 0; i < 7; i++) {"
11945 " if (o.y(42) != 43) throw 'oops: ' + o.y(42);"
11946 "}"
11947 "this.y = function(x) { return x - 1; };"
11948 "var result = 0;"
11949 "for (var i = 0; i < 7; i++) {"
11950 " result += o.y(42);"
11951 "}");
11952 CHECK_EQ(41 * 7, value->Int32Value());
11953}
11954
11955
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000011956// Test the case when actual function to call sits on global object.
11957THREADED_TEST(InterceptorCallICCachedFromGlobal) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000011958 v8::Isolate* isolate = CcTest::isolate();
11959 v8::HandleScope scope(isolate);
11960 v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000011961 templ_o->SetNamedPropertyHandler(NoBlockGetterX);
11962
11963 LocalContext context;
11964 context->Global()->Set(v8_str("o"), templ_o->NewInstance());
11965
11966 v8::Handle<Value> value = CompileRun(
11967 "try {"
11968 " o.__proto__ = this;"
11969 " for (var i = 0; i < 10; i++) {"
11970 " var v = o.parseFloat('239');"
11971 " if (v != 239) throw v;"
11972 // Now it should be ICed and keep a reference to parseFloat.
11973 " }"
11974 " var result = 0;"
11975 " for (var i = 0; i < 10; i++) {"
11976 " result += o.parseFloat('239');"
11977 " }"
11978 " result"
11979 "} catch(e) {"
11980 " e"
11981 "};");
11982 CHECK_EQ(239 * 10, value->Int32Value());
11983}
11984
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011985static void InterceptorCallICFastApi(
11986 Local<String> name,
11987 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.org5c838252010-02-19 08:53:10 +000011988 ApiTestFuzzer::Fuzz();
dslomov@chromium.orgb752d402013-06-18 11:54:54 +000011989 CheckReturnValue(info, FUNCTION_ADDR(InterceptorCallICFastApi));
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000011990 int* call_count =
11991 reinterpret_cast<int*>(v8::External::Cast(*info.Data())->Value());
ager@chromium.org5c838252010-02-19 08:53:10 +000011992 ++(*call_count);
11993 if ((*call_count) % 20 == 0) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000011994 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org5c838252010-02-19 08:53:10 +000011995 }
ager@chromium.org5c838252010-02-19 08:53:10 +000011996}
11997
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000011998static void FastApiCallback_TrivialSignature(
11999 const v8::FunctionCallbackInfo<v8::Value>& args) {
ager@chromium.org5c838252010-02-19 08:53:10 +000012000 ApiTestFuzzer::Fuzz();
dslomov@chromium.orgb752d402013-06-18 11:54:54 +000012001 CheckReturnValue(args, FUNCTION_ADDR(FastApiCallback_TrivialSignature));
machenbach@chromium.org528ce022013-09-23 14:09:36 +000012002 v8::Isolate* isolate = CcTest::isolate();
jkummerow@chromium.org28faa982012-04-13 09:58:30 +000012003 CHECK_EQ(isolate, args.GetIsolate());
ager@chromium.org5c838252010-02-19 08:53:10 +000012004 CHECK_EQ(args.This(), args.Holder());
12005 CHECK(args.Data()->Equals(v8_str("method_data")));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012006 args.GetReturnValue().Set(args[0]->Int32Value() + 1);
ager@chromium.org5c838252010-02-19 08:53:10 +000012007}
12008
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012009static void FastApiCallback_SimpleSignature(
12010 const v8::FunctionCallbackInfo<v8::Value>& args) {
ager@chromium.org5c838252010-02-19 08:53:10 +000012011 ApiTestFuzzer::Fuzz();
dslomov@chromium.orgb752d402013-06-18 11:54:54 +000012012 CheckReturnValue(args, FUNCTION_ADDR(FastApiCallback_SimpleSignature));
machenbach@chromium.org528ce022013-09-23 14:09:36 +000012013 v8::Isolate* isolate = CcTest::isolate();
jkummerow@chromium.org28faa982012-04-13 09:58:30 +000012014 CHECK_EQ(isolate, args.GetIsolate());
ager@chromium.org5c838252010-02-19 08:53:10 +000012015 CHECK_EQ(args.This()->GetPrototype(), args.Holder());
12016 CHECK(args.Data()->Equals(v8_str("method_data")));
12017 // Note, we're using HasRealNamedProperty instead of Has to avoid
12018 // invoking the interceptor again.
12019 CHECK(args.Holder()->HasRealNamedProperty(v8_str("foo")));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012020 args.GetReturnValue().Set(args[0]->Int32Value() + 1);
ager@chromium.org5c838252010-02-19 08:53:10 +000012021}
12022
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012023
ager@chromium.org5c838252010-02-19 08:53:10 +000012024// Helper to maximize the odds of object moving.
12025static void GenerateSomeGarbage() {
12026 CompileRun(
12027 "var garbage;"
12028 "for (var i = 0; i < 1000; i++) {"
12029 " garbage = [1/i, \"garbage\" + i, garbage, {foo: garbage}];"
12030 "}"
12031 "garbage = undefined;");
12032}
12033
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000012034
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012035void DirectApiCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +000012036 static int count = 0;
12037 if (count++ % 3 == 0) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000012038 CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
yangguo@chromium.orgd2899aa2012-06-21 11:16:20 +000012039 // This should move the stub
ricow@chromium.org83aa5492011-02-07 12:42:56 +000012040 GenerateSomeGarbage(); // This should ensure the old stub memory is flushed
12041 }
ricow@chromium.org83aa5492011-02-07 12:42:56 +000012042}
12043
12044
12045THREADED_TEST(CallICFastApi_DirectCall_GCMoveStub) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +000012046 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012047 v8::Isolate* isolate = context->GetIsolate();
12048 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012049 v8::Handle<v8::ObjectTemplate> nativeobject_templ =
12050 v8::ObjectTemplate::New(isolate);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012051 nativeobject_templ->Set(isolate, "callback",
12052 v8::FunctionTemplate::New(isolate,
12053 DirectApiCallback));
ricow@chromium.org83aa5492011-02-07 12:42:56 +000012054 v8::Local<v8::Object> nativeobject_obj = nativeobject_templ->NewInstance();
12055 context->Global()->Set(v8_str("nativeobject"), nativeobject_obj);
12056 // call the api function multiple times to ensure direct call stub creation.
12057 CompileRun(
12058 "function f() {"
12059 " for (var i = 1; i <= 30; i++) {"
12060 " nativeobject.callback();"
12061 " }"
12062 "}"
12063 "f();");
12064}
12065
12066
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012067void ThrowingDirectApiCallback(
12068 const v8::FunctionCallbackInfo<v8::Value>& args) {
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000012069 args.GetIsolate()->ThrowException(v8_str("g"));
ricow@chromium.org83aa5492011-02-07 12:42:56 +000012070}
12071
12072
12073THREADED_TEST(CallICFastApi_DirectCall_Throw) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +000012074 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012075 v8::Isolate* isolate = context->GetIsolate();
12076 v8::HandleScope scope(isolate);
12077 v8::Handle<v8::ObjectTemplate> nativeobject_templ =
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012078 v8::ObjectTemplate::New(isolate);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012079 nativeobject_templ->Set(isolate, "callback",
12080 v8::FunctionTemplate::New(isolate,
12081 ThrowingDirectApiCallback));
ricow@chromium.org83aa5492011-02-07 12:42:56 +000012082 v8::Local<v8::Object> nativeobject_obj = nativeobject_templ->NewInstance();
12083 context->Global()->Set(v8_str("nativeobject"), nativeobject_obj);
12084 // call the api function multiple times to ensure direct call stub creation.
12085 v8::Handle<Value> result = CompileRun(
12086 "var result = '';"
12087 "function f() {"
12088 " for (var i = 1; i <= 5; i++) {"
12089 " try { nativeobject.callback(); } catch (e) { result += e; }"
12090 " }"
12091 "}"
12092 "f(); result;");
12093 CHECK_EQ(v8_str("ggggg"), result);
12094}
12095
12096
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +000012097static Handle<Value> DoDirectGetter() {
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000012098 if (++p_getter_count % 3 == 0) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000012099 CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000012100 GenerateSomeGarbage();
12101 }
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +000012102 return v8_str("Direct Getter Result");
12103}
12104
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +000012105static void DirectGetterCallback(
12106 Local<String> name,
12107 const v8::PropertyCallbackInfo<v8::Value>& info) {
dslomov@chromium.orgb752d402013-06-18 11:54:54 +000012108 CheckReturnValue(info, FUNCTION_ADDR(DirectGetterCallback));
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +000012109 info.GetReturnValue().Set(DoDirectGetter());
12110}
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000012111
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +000012112
12113template<typename Accessor>
12114static void LoadICFastApi_DirectCall_GCMoveStub(Accessor accessor) {
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000012115 LocalContext context;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012116 v8::Isolate* isolate = context->GetIsolate();
12117 v8::HandleScope scope(isolate);
12118 v8::Handle<v8::ObjectTemplate> obj = v8::ObjectTemplate::New(isolate);
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +000012119 obj->SetAccessor(v8_str("p1"), accessor);
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000012120 context->Global()->Set(v8_str("o1"), obj->NewInstance());
12121 p_getter_count = 0;
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +000012122 v8::Handle<v8::Value> result = CompileRun(
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000012123 "function f() {"
12124 " for (var i = 0; i < 30; i++) o1.p1;"
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +000012125 " return o1.p1"
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000012126 "}"
12127 "f();");
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +000012128 CHECK_EQ(v8_str("Direct Getter Result"), result);
12129 CHECK_EQ(31, p_getter_count);
12130}
12131
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012132
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012133THREADED_PROFILED_TEST(LoadICFastApi_DirectCall_GCMoveStub) {
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +000012134 LoadICFastApi_DirectCall_GCMoveStub(DirectGetterCallback);
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000012135}
12136
12137
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012138void ThrowingDirectGetterCallback(
12139 Local<String> name,
12140 const v8::PropertyCallbackInfo<v8::Value>& info) {
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000012141 info.GetIsolate()->ThrowException(v8_str("g"));
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000012142}
12143
12144
12145THREADED_TEST(LoadICFastApi_DirectCall_Throw) {
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000012146 LocalContext context;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012147 v8::Isolate* isolate = context->GetIsolate();
12148 v8::HandleScope scope(isolate);
12149 v8::Handle<v8::ObjectTemplate> obj = v8::ObjectTemplate::New(isolate);
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +000012150 obj->SetAccessor(v8_str("p1"), ThrowingDirectGetterCallback);
12151 context->Global()->Set(v8_str("o1"), obj->NewInstance());
12152 v8::Handle<Value> result = CompileRun(
12153 "var result = '';"
12154 "for (var i = 0; i < 5; i++) {"
12155 " try { o1.p1; } catch (e) { result += e; }"
12156 "}"
12157 "result;");
12158 CHECK_EQ(v8_str("ggggg"), result);
12159}
12160
12161
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012162THREADED_PROFILED_TEST(InterceptorCallICFastApi_TrivialSignature) {
ager@chromium.org5c838252010-02-19 08:53:10 +000012163 int interceptor_call_count = 0;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012164 v8::Isolate* isolate = CcTest::isolate();
12165 v8::HandleScope scope(isolate);
12166 v8::Handle<v8::FunctionTemplate> fun_templ =
12167 v8::FunctionTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +000012168 v8::Handle<v8::FunctionTemplate> method_templ =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012169 v8::FunctionTemplate::New(isolate,
12170 FastApiCallback_TrivialSignature,
ager@chromium.org5c838252010-02-19 08:53:10 +000012171 v8_str("method_data"),
12172 v8::Handle<v8::Signature>());
12173 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12174 proto_templ->Set(v8_str("method"), method_templ);
12175 v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
machenbach@chromium.org0cc09502013-11-13 12:20:55 +000012176 templ->SetNamedPropertyHandler(
12177 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012178 v8::External::New(isolate, &interceptor_call_count));
ager@chromium.org5c838252010-02-19 08:53:10 +000012179 LocalContext context;
12180 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12181 GenerateSomeGarbage();
12182 context->Global()->Set(v8_str("o"), fun->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012183 CompileRun(
ager@chromium.org5c838252010-02-19 08:53:10 +000012184 "var result = 0;"
12185 "for (var i = 0; i < 100; i++) {"
12186 " result = o.method(41);"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012187 "}");
ager@chromium.org5c838252010-02-19 08:53:10 +000012188 CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
12189 CHECK_EQ(100, interceptor_call_count);
12190}
12191
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012192
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012193THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature) {
ager@chromium.org5c838252010-02-19 08:53:10 +000012194 int interceptor_call_count = 0;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012195 v8::Isolate* isolate = CcTest::isolate();
12196 v8::HandleScope scope(isolate);
12197 v8::Handle<v8::FunctionTemplate> fun_templ =
12198 v8::FunctionTemplate::New(isolate);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000012199 v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012200 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12201 v8::Signature::New(isolate, fun_templ));
ager@chromium.org5c838252010-02-19 08:53:10 +000012202 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12203 proto_templ->Set(v8_str("method"), method_templ);
mmassi@chromium.org49a44672012-12-04 13:52:03 +000012204 fun_templ->SetHiddenPrototype(true);
ager@chromium.org5c838252010-02-19 08:53:10 +000012205 v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
machenbach@chromium.org0cc09502013-11-13 12:20:55 +000012206 templ->SetNamedPropertyHandler(
12207 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012208 v8::External::New(isolate, &interceptor_call_count));
ager@chromium.org5c838252010-02-19 08:53:10 +000012209 LocalContext context;
12210 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12211 GenerateSomeGarbage();
12212 context->Global()->Set(v8_str("o"), fun->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012213 CompileRun(
ager@chromium.org5c838252010-02-19 08:53:10 +000012214 "o.foo = 17;"
12215 "var receiver = {};"
12216 "receiver.__proto__ = o;"
12217 "var result = 0;"
12218 "for (var i = 0; i < 100; i++) {"
12219 " result = receiver.method(41);"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012220 "}");
ager@chromium.org5c838252010-02-19 08:53:10 +000012221 CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
12222 CHECK_EQ(100, interceptor_call_count);
12223}
12224
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012225
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012226THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss1) {
ager@chromium.org5c838252010-02-19 08:53:10 +000012227 int interceptor_call_count = 0;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012228 v8::Isolate* isolate = CcTest::isolate();
12229 v8::HandleScope scope(isolate);
12230 v8::Handle<v8::FunctionTemplate> fun_templ =
12231 v8::FunctionTemplate::New(isolate);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000012232 v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012233 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12234 v8::Signature::New(isolate, fun_templ));
ager@chromium.org5c838252010-02-19 08:53:10 +000012235 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12236 proto_templ->Set(v8_str("method"), method_templ);
mmassi@chromium.org49a44672012-12-04 13:52:03 +000012237 fun_templ->SetHiddenPrototype(true);
ager@chromium.org5c838252010-02-19 08:53:10 +000012238 v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
machenbach@chromium.org0cc09502013-11-13 12:20:55 +000012239 templ->SetNamedPropertyHandler(
12240 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012241 v8::External::New(isolate, &interceptor_call_count));
ager@chromium.org5c838252010-02-19 08:53:10 +000012242 LocalContext context;
12243 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12244 GenerateSomeGarbage();
12245 context->Global()->Set(v8_str("o"), fun->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012246 CompileRun(
ager@chromium.org5c838252010-02-19 08:53:10 +000012247 "o.foo = 17;"
12248 "var receiver = {};"
12249 "receiver.__proto__ = o;"
12250 "var result = 0;"
12251 "var saved_result = 0;"
12252 "for (var i = 0; i < 100; i++) {"
12253 " result = receiver.method(41);"
12254 " if (i == 50) {"
12255 " saved_result = result;"
12256 " receiver = {method: function(x) { return x - 1 }};"
12257 " }"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012258 "}");
ager@chromium.org5c838252010-02-19 08:53:10 +000012259 CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
12260 CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
12261 CHECK_GE(interceptor_call_count, 50);
12262}
12263
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012264
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012265THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss2) {
ager@chromium.org5c838252010-02-19 08:53:10 +000012266 int interceptor_call_count = 0;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012267 v8::Isolate* isolate = CcTest::isolate();
12268 v8::HandleScope scope(isolate);
12269 v8::Handle<v8::FunctionTemplate> fun_templ =
12270 v8::FunctionTemplate::New(isolate);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000012271 v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012272 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12273 v8::Signature::New(isolate, fun_templ));
ager@chromium.org5c838252010-02-19 08:53:10 +000012274 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12275 proto_templ->Set(v8_str("method"), method_templ);
mmassi@chromium.org49a44672012-12-04 13:52:03 +000012276 fun_templ->SetHiddenPrototype(true);
ager@chromium.org5c838252010-02-19 08:53:10 +000012277 v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
machenbach@chromium.org0cc09502013-11-13 12:20:55 +000012278 templ->SetNamedPropertyHandler(
12279 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012280 v8::External::New(isolate, &interceptor_call_count));
ager@chromium.org5c838252010-02-19 08:53:10 +000012281 LocalContext context;
12282 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12283 GenerateSomeGarbage();
12284 context->Global()->Set(v8_str("o"), fun->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012285 CompileRun(
ager@chromium.org5c838252010-02-19 08:53:10 +000012286 "o.foo = 17;"
12287 "var receiver = {};"
12288 "receiver.__proto__ = o;"
12289 "var result = 0;"
12290 "var saved_result = 0;"
12291 "for (var i = 0; i < 100; i++) {"
12292 " result = receiver.method(41);"
12293 " if (i == 50) {"
12294 " saved_result = result;"
12295 " o.method = function(x) { return x - 1 };"
12296 " }"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012297 "}");
ager@chromium.org5c838252010-02-19 08:53:10 +000012298 CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
12299 CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
12300 CHECK_GE(interceptor_call_count, 50);
12301}
12302
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012303
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012304THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss3) {
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000012305 int interceptor_call_count = 0;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012306 v8::Isolate* isolate = CcTest::isolate();
12307 v8::HandleScope scope(isolate);
12308 v8::Handle<v8::FunctionTemplate> fun_templ =
12309 v8::FunctionTemplate::New(isolate);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000012310 v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012311 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12312 v8::Signature::New(isolate, fun_templ));
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000012313 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12314 proto_templ->Set(v8_str("method"), method_templ);
mmassi@chromium.org49a44672012-12-04 13:52:03 +000012315 fun_templ->SetHiddenPrototype(true);
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000012316 v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
machenbach@chromium.org0cc09502013-11-13 12:20:55 +000012317 templ->SetNamedPropertyHandler(
12318 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012319 v8::External::New(isolate, &interceptor_call_count));
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000012320 LocalContext context;
12321 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12322 GenerateSomeGarbage();
12323 context->Global()->Set(v8_str("o"), fun->NewInstance());
12324 v8::TryCatch try_catch;
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012325 CompileRun(
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000012326 "o.foo = 17;"
12327 "var receiver = {};"
12328 "receiver.__proto__ = o;"
12329 "var result = 0;"
12330 "var saved_result = 0;"
12331 "for (var i = 0; i < 100; i++) {"
12332 " result = receiver.method(41);"
12333 " if (i == 50) {"
12334 " saved_result = result;"
12335 " receiver = 333;"
12336 " }"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012337 "}");
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000012338 CHECK(try_catch.HasCaught());
machenbach@chromium.orga03ba1e2014-02-01 08:54:43 +000012339 // TODO(verwaest): Adjust message.
12340 CHECK_EQ(v8_str("TypeError: undefined is not a function"),
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000012341 try_catch.Exception()->ToString());
12342 CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
12343 CHECK_GE(interceptor_call_count, 50);
12344}
12345
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012346
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012347THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_TypeError) {
ager@chromium.org5c838252010-02-19 08:53:10 +000012348 int interceptor_call_count = 0;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012349 v8::Isolate* isolate = CcTest::isolate();
12350 v8::HandleScope scope(isolate);
12351 v8::Handle<v8::FunctionTemplate> fun_templ =
12352 v8::FunctionTemplate::New(isolate);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000012353 v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012354 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12355 v8::Signature::New(isolate, fun_templ));
ager@chromium.org5c838252010-02-19 08:53:10 +000012356 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12357 proto_templ->Set(v8_str("method"), method_templ);
mmassi@chromium.org49a44672012-12-04 13:52:03 +000012358 fun_templ->SetHiddenPrototype(true);
ager@chromium.org5c838252010-02-19 08:53:10 +000012359 v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
machenbach@chromium.org0cc09502013-11-13 12:20:55 +000012360 templ->SetNamedPropertyHandler(
12361 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012362 v8::External::New(isolate, &interceptor_call_count));
ager@chromium.org5c838252010-02-19 08:53:10 +000012363 LocalContext context;
12364 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12365 GenerateSomeGarbage();
12366 context->Global()->Set(v8_str("o"), fun->NewInstance());
12367 v8::TryCatch try_catch;
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012368 CompileRun(
ager@chromium.org5c838252010-02-19 08:53:10 +000012369 "o.foo = 17;"
12370 "var receiver = {};"
12371 "receiver.__proto__ = o;"
12372 "var result = 0;"
12373 "var saved_result = 0;"
12374 "for (var i = 0; i < 100; i++) {"
12375 " result = receiver.method(41);"
12376 " if (i == 50) {"
12377 " saved_result = result;"
12378 " receiver = {method: receiver.method};"
12379 " }"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012380 "}");
ager@chromium.org5c838252010-02-19 08:53:10 +000012381 CHECK(try_catch.HasCaught());
12382 CHECK_EQ(v8_str("TypeError: Illegal invocation"),
12383 try_catch.Exception()->ToString());
12384 CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
12385 CHECK_GE(interceptor_call_count, 50);
12386}
12387
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012388
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012389THREADED_PROFILED_TEST(CallICFastApi_TrivialSignature) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012390 v8::Isolate* isolate = CcTest::isolate();
12391 v8::HandleScope scope(isolate);
12392 v8::Handle<v8::FunctionTemplate> fun_templ =
12393 v8::FunctionTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +000012394 v8::Handle<v8::FunctionTemplate> method_templ =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012395 v8::FunctionTemplate::New(isolate,
12396 FastApiCallback_TrivialSignature,
ager@chromium.org5c838252010-02-19 08:53:10 +000012397 v8_str("method_data"),
12398 v8::Handle<v8::Signature>());
12399 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12400 proto_templ->Set(v8_str("method"), method_templ);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000012401 v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012402 USE(templ);
ager@chromium.org5c838252010-02-19 08:53:10 +000012403 LocalContext context;
12404 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12405 GenerateSomeGarbage();
12406 context->Global()->Set(v8_str("o"), fun->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012407 CompileRun(
ager@chromium.org5c838252010-02-19 08:53:10 +000012408 "var result = 0;"
12409 "for (var i = 0; i < 100; i++) {"
12410 " result = o.method(41);"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012411 "}");
ager@chromium.org5c838252010-02-19 08:53:10 +000012412
12413 CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
12414}
12415
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012416
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012417THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012418 v8::Isolate* isolate = CcTest::isolate();
12419 v8::HandleScope scope(isolate);
12420 v8::Handle<v8::FunctionTemplate> fun_templ =
12421 v8::FunctionTemplate::New(isolate);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000012422 v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012423 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12424 v8::Signature::New(isolate, fun_templ));
ager@chromium.org5c838252010-02-19 08:53:10 +000012425 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12426 proto_templ->Set(v8_str("method"), method_templ);
mmassi@chromium.org49a44672012-12-04 13:52:03 +000012427 fun_templ->SetHiddenPrototype(true);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000012428 v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012429 CHECK(!templ.IsEmpty());
ager@chromium.org5c838252010-02-19 08:53:10 +000012430 LocalContext context;
12431 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12432 GenerateSomeGarbage();
12433 context->Global()->Set(v8_str("o"), fun->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012434 CompileRun(
ager@chromium.org5c838252010-02-19 08:53:10 +000012435 "o.foo = 17;"
12436 "var receiver = {};"
12437 "receiver.__proto__ = o;"
12438 "var result = 0;"
12439 "for (var i = 0; i < 100; i++) {"
12440 " result = receiver.method(41);"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012441 "}");
ager@chromium.org5c838252010-02-19 08:53:10 +000012442
12443 CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
12444}
12445
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012446
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012447THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_Miss1) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012448 v8::Isolate* isolate = CcTest::isolate();
12449 v8::HandleScope scope(isolate);
12450 v8::Handle<v8::FunctionTemplate> fun_templ =
12451 v8::FunctionTemplate::New(isolate);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000012452 v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012453 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12454 v8::Signature::New(isolate, fun_templ));
ager@chromium.org5c838252010-02-19 08:53:10 +000012455 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12456 proto_templ->Set(v8_str("method"), method_templ);
mmassi@chromium.org49a44672012-12-04 13:52:03 +000012457 fun_templ->SetHiddenPrototype(true);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000012458 v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012459 CHECK(!templ.IsEmpty());
ager@chromium.org5c838252010-02-19 08:53:10 +000012460 LocalContext context;
12461 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12462 GenerateSomeGarbage();
12463 context->Global()->Set(v8_str("o"), fun->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012464 CompileRun(
ager@chromium.org5c838252010-02-19 08:53:10 +000012465 "o.foo = 17;"
12466 "var receiver = {};"
12467 "receiver.__proto__ = o;"
12468 "var result = 0;"
12469 "var saved_result = 0;"
12470 "for (var i = 0; i < 100; i++) {"
12471 " result = receiver.method(41);"
12472 " if (i == 50) {"
12473 " saved_result = result;"
12474 " receiver = {method: function(x) { return x - 1 }};"
12475 " }"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012476 "}");
ager@chromium.org5c838252010-02-19 08:53:10 +000012477 CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
12478 CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
12479}
12480
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012481
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012482THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_Miss2) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012483 v8::Isolate* isolate = CcTest::isolate();
12484 v8::HandleScope scope(isolate);
12485 v8::Handle<v8::FunctionTemplate> fun_templ =
12486 v8::FunctionTemplate::New(isolate);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000012487 v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012488 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12489 v8::Signature::New(isolate, fun_templ));
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000012490 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12491 proto_templ->Set(v8_str("method"), method_templ);
mmassi@chromium.org49a44672012-12-04 13:52:03 +000012492 fun_templ->SetHiddenPrototype(true);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000012493 v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012494 CHECK(!templ.IsEmpty());
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000012495 LocalContext context;
12496 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12497 GenerateSomeGarbage();
12498 context->Global()->Set(v8_str("o"), fun->NewInstance());
12499 v8::TryCatch try_catch;
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012500 CompileRun(
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000012501 "o.foo = 17;"
12502 "var receiver = {};"
12503 "receiver.__proto__ = o;"
12504 "var result = 0;"
12505 "var saved_result = 0;"
12506 "for (var i = 0; i < 100; i++) {"
12507 " result = receiver.method(41);"
12508 " if (i == 50) {"
12509 " saved_result = result;"
12510 " receiver = 333;"
12511 " }"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012512 "}");
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000012513 CHECK(try_catch.HasCaught());
machenbach@chromium.orga03ba1e2014-02-01 08:54:43 +000012514 // TODO(verwaest): Adjust message.
12515 CHECK_EQ(v8_str("TypeError: undefined is not a function"),
sgjesse@chromium.org534ae572010-02-24 22:09:39 +000012516 try_catch.Exception()->ToString());
12517 CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
12518}
12519
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012520
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012521THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_TypeError) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012522 v8::Isolate* isolate = CcTest::isolate();
12523 v8::HandleScope scope(isolate);
12524 v8::Handle<v8::FunctionTemplate> fun_templ =
12525 v8::FunctionTemplate::New(isolate);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000012526 v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012527 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12528 v8::Signature::New(isolate, fun_templ));
mmassi@chromium.org49a44672012-12-04 13:52:03 +000012529 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12530 proto_templ->Set(v8_str("method"), method_templ);
12531 fun_templ->SetHiddenPrototype(true);
12532 v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
12533 CHECK(!templ.IsEmpty());
12534 LocalContext context;
12535 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12536 GenerateSomeGarbage();
12537 context->Global()->Set(v8_str("o"), fun->NewInstance());
12538 v8::TryCatch try_catch;
12539 CompileRun(
12540 "o.foo = 17;"
12541 "var receiver = {};"
12542 "receiver.__proto__ = o;"
12543 "var result = 0;"
12544 "var saved_result = 0;"
12545 "for (var i = 0; i < 100; i++) {"
12546 " result = receiver.method(41);"
12547 " if (i == 50) {"
12548 " saved_result = result;"
12549 " receiver = Object.create(receiver);"
12550 " }"
12551 "}");
12552 CHECK(try_catch.HasCaught());
12553 CHECK_EQ(v8_str("TypeError: Illegal invocation"),
12554 try_catch.Exception()->ToString());
12555 CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
12556}
12557
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000012558
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012559v8::Handle<Value> keyed_call_ic_function;
12560
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012561static void InterceptorKeyedCallICGetter(
12562 Local<String> name,
12563 const v8::PropertyCallbackInfo<v8::Value>& info) {
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012564 ApiTestFuzzer::Fuzz();
12565 if (v8_str("x")->Equals(name)) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012566 info.GetReturnValue().Set(keyed_call_ic_function);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012567 }
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012568}
12569
12570
12571// Test the case when we stored cacheable lookup into
12572// a stub, but the function name changed (to another cacheable function).
12573THREADED_TEST(InterceptorKeyedCallICKeyChange1) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012574 v8::Isolate* isolate = CcTest::isolate();
12575 v8::HandleScope scope(isolate);
12576 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012577 templ->SetNamedPropertyHandler(NoBlockGetterX);
12578 LocalContext context;
12579 context->Global()->Set(v8_str("o"), templ->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012580 CompileRun(
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012581 "proto = new Object();"
12582 "proto.y = function(x) { return x + 1; };"
12583 "proto.z = function(x) { return x - 1; };"
12584 "o.__proto__ = proto;"
12585 "var result = 0;"
12586 "var method = 'y';"
12587 "for (var i = 0; i < 10; i++) {"
12588 " if (i == 5) { method = 'z'; };"
12589 " result += o[method](41);"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012590 "}");
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012591 CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
12592}
12593
12594
12595// Test the case when we stored cacheable lookup into
12596// a stub, but the function name changed (and the new function is present
12597// both before and after the interceptor in the prototype chain).
12598THREADED_TEST(InterceptorKeyedCallICKeyChange2) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012599 v8::Isolate* isolate = CcTest::isolate();
12600 v8::HandleScope scope(isolate);
12601 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012602 templ->SetNamedPropertyHandler(InterceptorKeyedCallICGetter);
12603 LocalContext context;
12604 context->Global()->Set(v8_str("proto1"), templ->NewInstance());
12605 keyed_call_ic_function =
12606 v8_compile("function f(x) { return x - 1; }; f")->Run();
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012607 CompileRun(
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012608 "o = new Object();"
12609 "proto2 = new Object();"
12610 "o.y = function(x) { return x + 1; };"
12611 "proto2.y = function(x) { return x + 2; };"
12612 "o.__proto__ = proto1;"
12613 "proto1.__proto__ = proto2;"
12614 "var result = 0;"
12615 "var method = 'x';"
12616 "for (var i = 0; i < 10; i++) {"
12617 " if (i == 5) { method = 'y'; };"
12618 " result += o[method](41);"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012619 "}");
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012620 CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
12621}
12622
12623
12624// Same as InterceptorKeyedCallICKeyChange1 only the cacheable function sit
12625// on the global object.
12626THREADED_TEST(InterceptorKeyedCallICKeyChangeOnGlobal) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012627 v8::Isolate* isolate = CcTest::isolate();
12628 v8::HandleScope scope(isolate);
12629 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012630 templ->SetNamedPropertyHandler(NoBlockGetterX);
12631 LocalContext context;
12632 context->Global()->Set(v8_str("o"), templ->NewInstance());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012633 CompileRun(
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012634 "function inc(x) { return x + 1; };"
12635 "inc(1);"
12636 "function dec(x) { return x - 1; };"
12637 "dec(1);"
12638 "o.__proto__ = this;"
12639 "this.__proto__.x = inc;"
12640 "this.__proto__.y = dec;"
12641 "var result = 0;"
12642 "var method = 'x';"
12643 "for (var i = 0; i < 10; i++) {"
12644 " if (i == 5) { method = 'y'; };"
12645 " result += o[method](41);"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012646 "}");
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012647 CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
12648}
12649
12650
12651// Test the case when actual function to call sits on global object.
12652THREADED_TEST(InterceptorKeyedCallICFromGlobal) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012653 v8::Isolate* isolate = CcTest::isolate();
12654 v8::HandleScope scope(isolate);
12655 v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012656 templ_o->SetNamedPropertyHandler(NoBlockGetterX);
12657 LocalContext context;
12658 context->Global()->Set(v8_str("o"), templ_o->NewInstance());
12659
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012660 CompileRun(
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012661 "function len(x) { return x.length; };"
12662 "o.__proto__ = this;"
12663 "var m = 'parseFloat';"
12664 "var result = 0;"
12665 "for (var i = 0; i < 10; i++) {"
12666 " if (i == 5) {"
12667 " m = 'len';"
12668 " saved_result = result;"
12669 " };"
12670 " result = o[m]('239');"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012671 "}");
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012672 CHECK_EQ(3, context->Global()->Get(v8_str("result"))->Int32Value());
12673 CHECK_EQ(239, context->Global()->Get(v8_str("saved_result"))->Int32Value());
12674}
12675
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012676
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012677// Test the map transition before the interceptor.
12678THREADED_TEST(InterceptorKeyedCallICMapChangeBefore) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012679 v8::Isolate* isolate = CcTest::isolate();
12680 v8::HandleScope scope(isolate);
12681 v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012682 templ_o->SetNamedPropertyHandler(NoBlockGetterX);
12683 LocalContext context;
12684 context->Global()->Set(v8_str("proto"), templ_o->NewInstance());
12685
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012686 CompileRun(
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012687 "var o = new Object();"
12688 "o.__proto__ = proto;"
12689 "o.method = function(x) { return x + 1; };"
12690 "var m = 'method';"
12691 "var result = 0;"
12692 "for (var i = 0; i < 10; i++) {"
12693 " if (i == 5) { o.method = function(x) { return x - 1; }; };"
12694 " result += o[m](41);"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012695 "}");
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012696 CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
12697}
12698
12699
12700// Test the map transition after the interceptor.
12701THREADED_TEST(InterceptorKeyedCallICMapChangeAfter) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012702 v8::Isolate* isolate = CcTest::isolate();
12703 v8::HandleScope scope(isolate);
12704 v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012705 templ_o->SetNamedPropertyHandler(NoBlockGetterX);
12706 LocalContext context;
12707 context->Global()->Set(v8_str("o"), templ_o->NewInstance());
12708
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012709 CompileRun(
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012710 "var proto = new Object();"
12711 "o.__proto__ = proto;"
12712 "proto.method = function(x) { return x + 1; };"
12713 "var m = 'method';"
12714 "var result = 0;"
12715 "for (var i = 0; i < 10; i++) {"
12716 " if (i == 5) { proto.method = function(x) { return x - 1; }; };"
12717 " result += o[m](41);"
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000012718 "}");
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +000012719 CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
12720}
12721
12722
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012723static int interceptor_call_count = 0;
12724
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012725static void InterceptorICRefErrorGetter(
12726 Local<String> name,
12727 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012728 ApiTestFuzzer::Fuzz();
12729 if (v8_str("x")->Equals(name) && interceptor_call_count++ < 20) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012730 info.GetReturnValue().Set(call_ic_function2);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012731 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012732}
12733
12734
12735// This test should hit load and call ICs for the interceptor case.
12736// Once in a while, the interceptor will reply that a property was not
12737// found in which case we should get a reference error.
12738THREADED_TEST(InterceptorICReferenceErrors) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012739 v8::Isolate* isolate = CcTest::isolate();
12740 v8::HandleScope scope(isolate);
12741 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012742 templ->SetNamedPropertyHandler(InterceptorICRefErrorGetter);
12743 LocalContext context(0, templ, v8::Handle<Value>());
12744 call_ic_function2 = v8_compile("function h(x) { return x; }; h")->Run();
12745 v8::Handle<Value> value = CompileRun(
12746 "function f() {"
12747 " for (var i = 0; i < 1000; i++) {"
12748 " try { x; } catch(e) { return true; }"
12749 " }"
12750 " return false;"
12751 "};"
12752 "f();");
12753 CHECK_EQ(true, value->BooleanValue());
12754 interceptor_call_count = 0;
12755 value = CompileRun(
12756 "function g() {"
12757 " for (var i = 0; i < 1000; i++) {"
12758 " try { x(42); } catch(e) { return true; }"
12759 " }"
12760 " return false;"
12761 "};"
12762 "g();");
12763 CHECK_EQ(true, value->BooleanValue());
12764}
12765
12766
12767static int interceptor_ic_exception_get_count = 0;
12768
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012769static void InterceptorICExceptionGetter(
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012770 Local<String> name,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012771 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012772 ApiTestFuzzer::Fuzz();
12773 if (v8_str("x")->Equals(name) && ++interceptor_ic_exception_get_count < 20) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012774 info.GetReturnValue().Set(call_ic_function3);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012775 }
12776 if (interceptor_ic_exception_get_count == 20) {
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000012777 info.GetIsolate()->ThrowException(v8_num(42));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012778 return;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012779 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012780}
12781
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012782
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012783// Test interceptor load/call IC where the interceptor throws an
12784// exception once in a while.
12785THREADED_TEST(InterceptorICGetterExceptions) {
12786 interceptor_ic_exception_get_count = 0;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012787 v8::Isolate* isolate = CcTest::isolate();
12788 v8::HandleScope scope(isolate);
12789 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012790 templ->SetNamedPropertyHandler(InterceptorICExceptionGetter);
12791 LocalContext context(0, templ, v8::Handle<Value>());
12792 call_ic_function3 = v8_compile("function h(x) { return x; }; h")->Run();
12793 v8::Handle<Value> value = CompileRun(
12794 "function f() {"
12795 " for (var i = 0; i < 100; i++) {"
12796 " try { x; } catch(e) { return true; }"
12797 " }"
12798 " return false;"
12799 "};"
12800 "f();");
12801 CHECK_EQ(true, value->BooleanValue());
12802 interceptor_ic_exception_get_count = 0;
12803 value = CompileRun(
12804 "function f() {"
12805 " for (var i = 0; i < 100; i++) {"
12806 " try { x(42); } catch(e) { return true; }"
12807 " }"
12808 " return false;"
12809 "};"
12810 "f();");
12811 CHECK_EQ(true, value->BooleanValue());
12812}
12813
12814
12815static int interceptor_ic_exception_set_count = 0;
12816
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012817static void InterceptorICExceptionSetter(
12818 Local<String> key,
12819 Local<Value> value,
12820 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012821 ApiTestFuzzer::Fuzz();
12822 if (++interceptor_ic_exception_set_count > 20) {
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000012823 info.GetIsolate()->ThrowException(v8_num(42));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012824 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012825}
12826
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012827
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012828// Test interceptor store IC where the interceptor throws an exception
12829// once in a while.
12830THREADED_TEST(InterceptorICSetterExceptions) {
12831 interceptor_ic_exception_set_count = 0;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012832 v8::Isolate* isolate = CcTest::isolate();
12833 v8::HandleScope scope(isolate);
12834 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012835 templ->SetNamedPropertyHandler(0, InterceptorICExceptionSetter);
12836 LocalContext context(0, templ, v8::Handle<Value>());
12837 v8::Handle<Value> value = CompileRun(
12838 "function f() {"
12839 " for (var i = 0; i < 100; i++) {"
12840 " try { x = 42; } catch(e) { return true; }"
12841 " }"
12842 " return false;"
12843 "};"
12844 "f();");
12845 CHECK_EQ(true, value->BooleanValue());
12846}
12847
12848
12849// Test that we ignore null interceptors.
12850THREADED_TEST(NullNamedInterceptor) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012851 v8::Isolate* isolate = CcTest::isolate();
12852 v8::HandleScope scope(isolate);
12853 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012854 templ->SetNamedPropertyHandler(
12855 static_cast<v8::NamedPropertyGetterCallback>(0));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012856 LocalContext context;
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000012857 templ->Set(CcTest::isolate(), "x", v8_num(42));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012858 v8::Handle<v8::Object> obj = templ->NewInstance();
12859 context->Global()->Set(v8_str("obj"), obj);
12860 v8::Handle<Value> value = CompileRun("obj.x");
12861 CHECK(value->IsInt32());
12862 CHECK_EQ(42, value->Int32Value());
12863}
12864
12865
12866// Test that we ignore null interceptors.
12867THREADED_TEST(NullIndexedInterceptor) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000012868 v8::Isolate* isolate = CcTest::isolate();
12869 v8::HandleScope scope(isolate);
12870 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012871 templ->SetIndexedPropertyHandler(
12872 static_cast<v8::IndexedPropertyGetterCallback>(0));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012873 LocalContext context;
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000012874 templ->Set(CcTest::isolate(), "42", v8_num(42));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000012875 v8::Handle<v8::Object> obj = templ->NewInstance();
12876 context->Global()->Set(v8_str("obj"), obj);
12877 v8::Handle<Value> value = CompileRun("obj[42]");
12878 CHECK(value->IsInt32());
12879 CHECK_EQ(42, value->Int32Value());
12880}
12881
12882
ricow@chromium.org30ce4112010-05-31 10:38:25 +000012883THREADED_TEST(NamedPropertyHandlerGetterAttributes) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012884 v8::Isolate* isolate = CcTest::isolate();
12885 v8::HandleScope scope(isolate);
12886 v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
ricow@chromium.org30ce4112010-05-31 10:38:25 +000012887 templ->InstanceTemplate()->SetNamedPropertyHandler(InterceptorLoadXICGetter);
12888 LocalContext env;
12889 env->Global()->Set(v8_str("obj"),
12890 templ->GetFunction()->NewInstance());
12891 ExpectTrue("obj.x === 42");
12892 ExpectTrue("!obj.propertyIsEnumerable('x')");
12893}
12894
12895
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012896static void ThrowingGetter(Local<String> name,
12897 const v8::PropertyCallbackInfo<v8::Value>& info) {
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012898 ApiTestFuzzer::Fuzz();
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000012899 info.GetIsolate()->ThrowException(Handle<Value>());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012900 info.GetReturnValue().SetUndefined();
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012901}
12902
12903
12904THREADED_TEST(VariousGetPropertiesAndThrowingCallbacks) {
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012905 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000012906 HandleScope scope(context->GetIsolate());
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012907
ulan@chromium.org0f13e742014-01-03 15:51:11 +000012908 Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012909 Local<ObjectTemplate> instance_templ = templ->InstanceTemplate();
12910 instance_templ->SetAccessor(v8_str("f"), ThrowingGetter);
12911
12912 Local<Object> instance = templ->GetFunction()->NewInstance();
12913
ulan@chromium.org0f13e742014-01-03 15:51:11 +000012914 Local<Object> another = Object::New(context->GetIsolate());
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012915 another->SetPrototype(instance);
12916
12917 Local<Object> with_js_getter = CompileRun(
12918 "o = {};\n"
12919 "o.__defineGetter__('f', function() { throw undefined; });\n"
12920 "o\n").As<Object>();
12921 CHECK(!with_js_getter.IsEmpty());
12922
12923 TryCatch try_catch;
12924
12925 Local<Value> result = instance->GetRealNamedProperty(v8_str("f"));
12926 CHECK(try_catch.HasCaught());
12927 try_catch.Reset();
12928 CHECK(result.IsEmpty());
12929
12930 result = another->GetRealNamedProperty(v8_str("f"));
12931 CHECK(try_catch.HasCaught());
12932 try_catch.Reset();
12933 CHECK(result.IsEmpty());
12934
12935 result = another->GetRealNamedPropertyInPrototypeChain(v8_str("f"));
12936 CHECK(try_catch.HasCaught());
12937 try_catch.Reset();
12938 CHECK(result.IsEmpty());
12939
12940 result = another->Get(v8_str("f"));
12941 CHECK(try_catch.HasCaught());
12942 try_catch.Reset();
12943 CHECK(result.IsEmpty());
12944
12945 result = with_js_getter->GetRealNamedProperty(v8_str("f"));
12946 CHECK(try_catch.HasCaught());
12947 try_catch.Reset();
12948 CHECK(result.IsEmpty());
12949
12950 result = with_js_getter->Get(v8_str("f"));
12951 CHECK(try_catch.HasCaught());
12952 try_catch.Reset();
12953 CHECK(result.IsEmpty());
12954}
12955
12956
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000012957static void ThrowingCallbackWithTryCatch(
12958 const v8::FunctionCallbackInfo<v8::Value>& args) {
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012959 TryCatch try_catch;
12960 // Verboseness is important: it triggers message delivery which can call into
12961 // external code.
12962 try_catch.SetVerbose(true);
12963 CompileRun("throw 'from JS';");
12964 CHECK(try_catch.HasCaught());
machenbach@chromium.org528ce022013-09-23 14:09:36 +000012965 CHECK(!CcTest::i_isolate()->has_pending_exception());
12966 CHECK(!CcTest::i_isolate()->has_scheduled_exception());
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012967}
12968
12969
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +000012970static int call_depth;
12971
12972
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012973static void WithTryCatch(Handle<Message> message, Handle<Value> data) {
12974 TryCatch try_catch;
12975}
12976
12977
12978static void ThrowFromJS(Handle<Message> message, Handle<Value> data) {
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +000012979 if (--call_depth) CompileRun("throw 'ThrowInJS';");
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012980}
12981
12982
12983static void ThrowViaApi(Handle<Message> message, Handle<Value> data) {
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000012984 if (--call_depth) CcTest::isolate()->ThrowException(v8_str("ThrowViaApi"));
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012985}
12986
12987
12988static void WebKitLike(Handle<Message> message, Handle<Value> data) {
12989 Handle<String> errorMessageString = message->Get();
12990 CHECK(!errorMessageString.IsEmpty());
12991 message->GetStackTrace();
12992 message->GetScriptResourceName();
12993}
12994
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000012995
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012996THREADED_TEST(ExceptionsDoNotPropagatePastTryCatch) {
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000012997 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000012998 v8::Isolate* isolate = context->GetIsolate();
12999 HandleScope scope(isolate);
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000013000
13001 Local<Function> func =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000013002 FunctionTemplate::New(isolate,
13003 ThrowingCallbackWithTryCatch)->GetFunction();
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000013004 context->Global()->Set(v8_str("func"), func);
13005
13006 MessageCallback callbacks[] =
13007 { NULL, WebKitLike, ThrowViaApi, ThrowFromJS, WithTryCatch };
13008 for (unsigned i = 0; i < sizeof(callbacks)/sizeof(callbacks[0]); i++) {
13009 MessageCallback callback = callbacks[i];
13010 if (callback != NULL) {
13011 V8::AddMessageListener(callback);
13012 }
ricow@chromium.orgdcebac02011-04-20 09:44:50 +000013013 // Some small number to control number of times message handler should
13014 // throw an exception.
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +000013015 call_depth = 5;
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000013016 ExpectFalse(
13017 "var thrown = false;\n"
13018 "try { func(); } catch(e) { thrown = true; }\n"
13019 "thrown\n");
13020 if (callback != NULL) {
13021 V8::RemoveMessageListeners(callback);
13022 }
13023 }
13024}
13025
13026
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013027static void ParentGetter(Local<String> name,
13028 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013029 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013030 info.GetReturnValue().Set(v8_num(1));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013031}
13032
13033
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013034static void ChildGetter(Local<String> name,
13035 const v8::PropertyCallbackInfo<v8::Value>& info) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013036 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013037 info.GetReturnValue().Set(v8_num(42));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013038}
13039
13040
13041THREADED_TEST(Overriding) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +000013042 i::FLAG_es5_readonly = true;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013043 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000013044 v8::Isolate* isolate = context->GetIsolate();
13045 v8::HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013046
13047 // Parent template.
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000013048 Local<v8::FunctionTemplate> parent_templ = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013049 Local<ObjectTemplate> parent_instance_templ =
13050 parent_templ->InstanceTemplate();
13051 parent_instance_templ->SetAccessor(v8_str("f"), ParentGetter);
13052
13053 // Template that inherits from the parent template.
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000013054 Local<v8::FunctionTemplate> child_templ = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013055 Local<ObjectTemplate> child_instance_templ =
13056 child_templ->InstanceTemplate();
13057 child_templ->Inherit(parent_templ);
13058 // Override 'f'. The child version of 'f' should get called for child
13059 // instances.
13060 child_instance_templ->SetAccessor(v8_str("f"), ChildGetter);
13061 // Add 'g' twice. The 'g' added last should get called for instances.
13062 child_instance_templ->SetAccessor(v8_str("g"), ParentGetter);
13063 child_instance_templ->SetAccessor(v8_str("g"), ChildGetter);
13064
13065 // Add 'h' as an accessor to the proto template with ReadOnly attributes
13066 // so 'h' can be shadowed on the instance object.
13067 Local<ObjectTemplate> child_proto_templ = child_templ->PrototypeTemplate();
13068 child_proto_templ->SetAccessor(v8_str("h"), ParentGetter, 0,
13069 v8::Handle<Value>(), v8::DEFAULT, v8::ReadOnly);
13070
13071 // Add 'i' as an accessor to the instance template with ReadOnly attributes
13072 // but the attribute does not have effect because it is duplicated with
13073 // NULL setter.
13074 child_instance_templ->SetAccessor(v8_str("i"), ChildGetter, 0,
13075 v8::Handle<Value>(), v8::DEFAULT, v8::ReadOnly);
13076
13077
13078
13079 // Instantiate the child template.
13080 Local<v8::Object> instance = child_templ->GetFunction()->NewInstance();
13081
13082 // Check that the child function overrides the parent one.
13083 context->Global()->Set(v8_str("o"), instance);
13084 Local<Value> value = v8_compile("o.f")->Run();
13085 // Check that the 'g' that was added last is hit.
13086 CHECK_EQ(42, value->Int32Value());
13087 value = v8_compile("o.g")->Run();
13088 CHECK_EQ(42, value->Int32Value());
13089
mmassi@chromium.org7028c052012-06-13 11:51:58 +000013090 // Check that 'h' cannot be shadowed.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013091 value = v8_compile("o.h = 3; o.h")->Run();
mmassi@chromium.org7028c052012-06-13 11:51:58 +000013092 CHECK_EQ(1, value->Int32Value());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013093
mmassi@chromium.org7028c052012-06-13 11:51:58 +000013094 // Check that 'i' cannot be shadowed or changed.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013095 value = v8_compile("o.i = 3; o.i")->Run();
13096 CHECK_EQ(42, value->Int32Value());
13097}
13098
13099
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013100static void IsConstructHandler(
13101 const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013102 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013103 args.GetReturnValue().Set(args.IsConstructCall());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013104}
13105
13106
13107THREADED_TEST(IsConstructCall) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000013108 v8::Isolate* isolate = CcTest::isolate();
13109 v8::HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013110
13111 // Function template with call handler.
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000013112 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013113 templ->SetCallHandler(IsConstructHandler);
13114
13115 LocalContext context;
13116
13117 context->Global()->Set(v8_str("f"), templ->GetFunction());
13118 Local<Value> value = v8_compile("f()")->Run();
13119 CHECK(!value->BooleanValue());
13120 value = v8_compile("new f()")->Run();
13121 CHECK(value->BooleanValue());
13122}
13123
13124
13125THREADED_TEST(ObjectProtoToString) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000013126 v8::Isolate* isolate = CcTest::isolate();
13127 v8::HandleScope scope(isolate);
13128 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013129 templ->SetClassName(v8_str("MyClass"));
13130
13131 LocalContext context;
13132
13133 Local<String> customized_tostring = v8_str("customized toString");
13134
13135 // Replace Object.prototype.toString
13136 v8_compile("Object.prototype.toString = function() {"
13137 " return 'customized toString';"
13138 "}")->Run();
13139
13140 // Normal ToString call should call replaced Object.prototype.toString
13141 Local<v8::Object> instance = templ->GetFunction()->NewInstance();
13142 Local<String> value = instance->ToString();
13143 CHECK(value->IsString() && value->Equals(customized_tostring));
13144
13145 // ObjectProtoToString should not call replace toString function.
13146 value = instance->ObjectProtoToString();
13147 CHECK(value->IsString() && value->Equals(v8_str("[object MyClass]")));
13148
13149 // Check global
13150 value = context->Global()->ObjectProtoToString();
13151 CHECK(value->IsString() && value->Equals(v8_str("[object global]")));
13152
13153 // Check ordinary object
13154 Local<Value> object = v8_compile("new Object()")->Run();
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000013155 value = object.As<v8::Object>()->ObjectProtoToString();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013156 CHECK(value->IsString() && value->Equals(v8_str("[object Object]")));
13157}
13158
13159
ager@chromium.orgbeb25712010-11-29 08:02:25 +000013160THREADED_TEST(ObjectGetConstructorName) {
ager@chromium.orgbeb25712010-11-29 08:02:25 +000013161 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013162 v8::HandleScope scope(context->GetIsolate());
ager@chromium.orgbeb25712010-11-29 08:02:25 +000013163 v8_compile("function Parent() {};"
13164 "function Child() {};"
13165 "Child.prototype = new Parent();"
13166 "var outer = { inner: function() { } };"
13167 "var p = new Parent();"
13168 "var c = new Child();"
13169 "var x = new outer.inner();")->Run();
13170
13171 Local<v8::Value> p = context->Global()->Get(v8_str("p"));
13172 CHECK(p->IsObject() && p->ToObject()->GetConstructorName()->Equals(
13173 v8_str("Parent")));
13174
13175 Local<v8::Value> c = context->Global()->Get(v8_str("c"));
13176 CHECK(c->IsObject() && c->ToObject()->GetConstructorName()->Equals(
13177 v8_str("Child")));
13178
13179 Local<v8::Value> x = context->Global()->Get(v8_str("x"));
13180 CHECK(x->IsObject() && x->ToObject()->GetConstructorName()->Equals(
13181 v8_str("outer.inner")));
13182}
13183
13184
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013185bool ApiTestFuzzer::fuzzing_ = false;
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000013186i::Semaphore ApiTestFuzzer::all_tests_done_(0);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013187int ApiTestFuzzer::active_tests_;
13188int ApiTestFuzzer::tests_being_run_;
13189int ApiTestFuzzer::current_;
13190
13191
13192// We are in a callback and want to switch to another thread (if we
13193// are currently running the thread fuzzing test).
13194void ApiTestFuzzer::Fuzz() {
13195 if (!fuzzing_) return;
13196 ApiTestFuzzer* test = RegisterThreadedTest::nth(current_)->fuzzer_;
13197 test->ContextSwitch();
13198}
13199
13200
13201// Let the next thread go. Since it is also waiting on the V8 lock it may
13202// not start immediately.
13203bool ApiTestFuzzer::NextThread() {
13204 int test_position = GetNextTestNumber();
ager@chromium.orgc4c92722009-11-18 14:12:51 +000013205 const char* test_name = RegisterThreadedTest::nth(current_)->name();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013206 if (test_position == current_) {
ager@chromium.orgc4c92722009-11-18 14:12:51 +000013207 if (kLogThreading)
13208 printf("Stay with %s\n", test_name);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013209 return false;
13210 }
ager@chromium.orgc4c92722009-11-18 14:12:51 +000013211 if (kLogThreading) {
13212 printf("Switch from %s to %s\n",
13213 test_name,
13214 RegisterThreadedTest::nth(test_position)->name());
13215 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013216 current_ = test_position;
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000013217 RegisterThreadedTest::nth(current_)->fuzzer_->gate_.Signal();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013218 return true;
13219}
13220
13221
13222void ApiTestFuzzer::Run() {
13223 // When it is our turn...
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000013224 gate_.Wait();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013225 {
13226 // ... get the V8 lock and start running the test.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013227 v8::Locker locker(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013228 CallTest();
13229 }
13230 // This test finished.
13231 active_ = false;
13232 active_tests_--;
13233 // If it was the last then signal that fact.
13234 if (active_tests_ == 0) {
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000013235 all_tests_done_.Signal();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013236 } else {
13237 // Otherwise select a new test and start that.
13238 NextThread();
13239 }
13240}
13241
13242
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013243static unsigned linear_congruential_generator;
13244
13245
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000013246void ApiTestFuzzer::SetUp(PartOfTest part) {
kasperl@chromium.orgb9123622008-09-17 14:05:56 +000013247 linear_congruential_generator = i::FLAG_testing_prng_seed;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013248 fuzzing_ = true;
lrn@chromium.org1c092762011-05-09 09:42:16 +000013249 int count = RegisterThreadedTest::count();
13250 int start = count * part / (LAST_PART + 1);
13251 int end = (count * (part + 1) / (LAST_PART + 1)) - 1;
13252 active_tests_ = tests_being_run_ = end - start + 1;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013253 for (int i = 0; i < tests_being_run_; i++) {
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000013254 RegisterThreadedTest::nth(i)->fuzzer_ = new ApiTestFuzzer(i + start);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013255 }
13256 for (int i = 0; i < active_tests_; i++) {
13257 RegisterThreadedTest::nth(i)->fuzzer_->Start();
13258 }
13259}
13260
13261
13262static void CallTestNumber(int test_number) {
13263 (RegisterThreadedTest::nth(test_number)->callback())();
13264}
13265
13266
13267void ApiTestFuzzer::RunAllTests() {
13268 // Set off the first test.
13269 current_ = -1;
13270 NextThread();
13271 // Wait till they are all done.
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000013272 all_tests_done_.Wait();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013273}
13274
13275
13276int ApiTestFuzzer::GetNextTestNumber() {
13277 int next_test;
13278 do {
13279 next_test = (linear_congruential_generator >> 16) % tests_being_run_;
13280 linear_congruential_generator *= 1664525u;
13281 linear_congruential_generator += 1013904223u;
13282 } while (!RegisterThreadedTest::nth(next_test)->fuzzer_->active_);
13283 return next_test;
13284}
13285
13286
13287void ApiTestFuzzer::ContextSwitch() {
13288 // If the new thread is the same as the current thread there is nothing to do.
13289 if (NextThread()) {
13290 // Now it can start.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013291 v8::Unlocker unlocker(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013292 // Wait till someone starts us again.
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000013293 gate_.Wait();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013294 // And we're off.
13295 }
13296}
13297
13298
13299void ApiTestFuzzer::TearDown() {
13300 fuzzing_ = false;
ager@chromium.org41826e72009-03-30 13:30:57 +000013301 for (int i = 0; i < RegisterThreadedTest::count(); i++) {
13302 ApiTestFuzzer *fuzzer = RegisterThreadedTest::nth(i)->fuzzer_;
13303 if (fuzzer != NULL) fuzzer->Join();
13304 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013305}
13306
13307
13308// Lets not be needlessly self-referential.
mmassi@chromium.org2f0efde2013-02-06 14:12:58 +000013309TEST(Threading1) {
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000013310 ApiTestFuzzer::SetUp(ApiTestFuzzer::FIRST_PART);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013311 ApiTestFuzzer::RunAllTests();
13312 ApiTestFuzzer::TearDown();
13313}
13314
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000013315
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013316TEST(Threading2) {
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000013317 ApiTestFuzzer::SetUp(ApiTestFuzzer::SECOND_PART);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013318 ApiTestFuzzer::RunAllTests();
13319 ApiTestFuzzer::TearDown();
13320}
13321
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000013322
lrn@chromium.org1c092762011-05-09 09:42:16 +000013323TEST(Threading3) {
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000013324 ApiTestFuzzer::SetUp(ApiTestFuzzer::THIRD_PART);
lrn@chromium.org1c092762011-05-09 09:42:16 +000013325 ApiTestFuzzer::RunAllTests();
13326 ApiTestFuzzer::TearDown();
13327}
13328
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000013329
lrn@chromium.org1c092762011-05-09 09:42:16 +000013330TEST(Threading4) {
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000013331 ApiTestFuzzer::SetUp(ApiTestFuzzer::FOURTH_PART);
lrn@chromium.org1c092762011-05-09 09:42:16 +000013332 ApiTestFuzzer::RunAllTests();
13333 ApiTestFuzzer::TearDown();
13334}
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013335
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000013336
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013337void ApiTestFuzzer::CallTest() {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013338 v8::Isolate::Scope scope(CcTest::isolate());
ager@chromium.orgc4c92722009-11-18 14:12:51 +000013339 if (kLogThreading)
13340 printf("Start test %d\n", test_number_);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013341 CallTestNumber(test_number_);
ager@chromium.orgc4c92722009-11-18 14:12:51 +000013342 if (kLogThreading)
13343 printf("End test %d\n", test_number_);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013344}
13345
13346
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013347static void ThrowInJS(const v8::FunctionCallbackInfo<v8::Value>& args) {
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000013348 v8::Isolate* isolate = args.GetIsolate();
13349 CHECK(v8::Locker::IsLocked(isolate));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013350 ApiTestFuzzer::Fuzz();
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000013351 v8::Unlocker unlocker(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013352 const char* code = "throw 7;";
13353 {
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000013354 v8::Locker nested_locker(isolate);
13355 v8::HandleScope scope(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013356 v8::Handle<Value> exception;
13357 { v8::TryCatch try_catch;
13358 v8::Handle<Value> value = CompileRun(code);
13359 CHECK(value.IsEmpty());
13360 CHECK(try_catch.HasCaught());
13361 // Make sure to wrap the exception in a new handle because
13362 // the handle returned from the TryCatch is destroyed
13363 // when the TryCatch is destroyed.
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000013364 exception = Local<Value>::New(isolate, try_catch.Exception());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013365 }
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000013366 args.GetIsolate()->ThrowException(exception);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013367 }
13368}
13369
13370
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013371static void ThrowInJSNoCatch(const v8::FunctionCallbackInfo<v8::Value>& args) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013372 CHECK(v8::Locker::IsLocked(CcTest::isolate()));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013373 ApiTestFuzzer::Fuzz();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013374 v8::Unlocker unlocker(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013375 const char* code = "throw 7;";
13376 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013377 v8::Locker nested_locker(CcTest::isolate());
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013378 v8::HandleScope scope(args.GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013379 v8::Handle<Value> value = CompileRun(code);
13380 CHECK(value.IsEmpty());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013381 args.GetReturnValue().Set(v8_str("foo"));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013382 }
13383}
13384
13385
13386// These are locking tests that don't need to be run again
13387// as part of the locking aggregation tests.
13388TEST(NestedLockers) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000013389 v8::Isolate* isolate = CcTest::isolate();
13390 v8::Locker locker(isolate);
13391 CHECK(v8::Locker::IsLocked(isolate));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013392 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013393 v8::HandleScope scope(env->GetIsolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000013394 Local<v8::FunctionTemplate> fun_templ =
13395 v8::FunctionTemplate::New(isolate, ThrowInJS);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013396 Local<Function> fun = fun_templ->GetFunction();
13397 env->Global()->Set(v8_str("throw_in_js"), fun);
13398 Local<Script> script = v8_compile("(function () {"
13399 " try {"
13400 " throw_in_js();"
13401 " return 42;"
13402 " } catch (e) {"
13403 " return e * 13;"
13404 " }"
13405 "})();");
13406 CHECK_EQ(91, script->Run()->Int32Value());
13407}
13408
13409
13410// These are locking tests that don't need to be run again
13411// as part of the locking aggregation tests.
13412TEST(NestedLockersNoTryCatch) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013413 v8::Locker locker(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013414 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013415 v8::HandleScope scope(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013416 Local<v8::FunctionTemplate> fun_templ =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000013417 v8::FunctionTemplate::New(env->GetIsolate(), ThrowInJSNoCatch);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013418 Local<Function> fun = fun_templ->GetFunction();
13419 env->Global()->Set(v8_str("throw_in_js"), fun);
13420 Local<Script> script = v8_compile("(function () {"
13421 " try {"
13422 " throw_in_js();"
13423 " return 42;"
13424 " } catch (e) {"
13425 " return e * 13;"
13426 " }"
13427 "})();");
13428 CHECK_EQ(91, script->Run()->Int32Value());
13429}
13430
13431
13432THREADED_TEST(RecursiveLocking) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013433 v8::Locker locker(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013434 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013435 v8::Locker locker2(CcTest::isolate());
13436 CHECK(v8::Locker::IsLocked(CcTest::isolate()));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013437 }
13438}
13439
13440
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013441static void UnlockForAMoment(const v8::FunctionCallbackInfo<v8::Value>& args) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013442 ApiTestFuzzer::Fuzz();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013443 v8::Unlocker unlocker(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013444}
13445
13446
13447THREADED_TEST(LockUnlockLock) {
13448 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013449 v8::Locker locker(CcTest::isolate());
13450 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013451 LocalContext env;
13452 Local<v8::FunctionTemplate> fun_templ =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000013453 v8::FunctionTemplate::New(CcTest::isolate(), UnlockForAMoment);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013454 Local<Function> fun = fun_templ->GetFunction();
13455 env->Global()->Set(v8_str("unlock_for_a_moment"), fun);
13456 Local<Script> script = v8_compile("(function () {"
13457 " unlock_for_a_moment();"
13458 " return 42;"
13459 "})();");
13460 CHECK_EQ(42, script->Run()->Int32Value());
13461 }
13462 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013463 v8::Locker locker(CcTest::isolate());
13464 v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013465 LocalContext env;
13466 Local<v8::FunctionTemplate> fun_templ =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000013467 v8::FunctionTemplate::New(CcTest::isolate(), UnlockForAMoment);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013468 Local<Function> fun = fun_templ->GetFunction();
13469 env->Global()->Set(v8_str("unlock_for_a_moment"), fun);
13470 Local<Script> script = v8_compile("(function () {"
13471 " unlock_for_a_moment();"
13472 " return 42;"
13473 "})();");
13474 CHECK_EQ(42, script->Run()->Int32Value());
13475 }
13476}
13477
13478
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000013479static int GetGlobalObjectsCount() {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013480 CcTest::heap()->EnsureHeapIsIterable();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013481 int count = 0;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013482 i::HeapIterator it(CcTest::heap());
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000013483 for (i::HeapObject* object = it.next(); object != NULL; object = it.next())
13484 if (object->IsJSGlobalObject()) count++;
13485 return count;
13486}
13487
13488
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000013489static void CheckSurvivingGlobalObjectsCount(int expected) {
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +000013490 // We need to collect all garbage twice to be sure that everything
13491 // has been collected. This is because inline caches are cleared in
13492 // the first garbage collection but some of the maps have already
13493 // been marked at that point. Therefore some of the maps are not
13494 // collected until the second garbage collection.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013495 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
13496 CcTest::heap()->CollectAllGarbage(i::Heap::kMakeHeapIterableMask);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000013497 int count = GetGlobalObjectsCount();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013498#ifdef DEBUG
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013499 if (count != expected) CcTest::heap()->TracePathToGlobal();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013500#endif
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000013501 CHECK_EQ(expected, count);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013502}
13503
13504
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013505TEST(DontLeakGlobalObjects) {
13506 // Regression test for issues 1139850 and 1174891.
13507
machenbach@chromium.orgc8cbc432014-01-21 09:01:57 +000013508 i::FLAG_expose_gc = true;
kasperl@chromium.orgb9123622008-09-17 14:05:56 +000013509 v8::V8::Initialize();
ager@chromium.org9258b6b2008-09-11 09:11:10 +000013510
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013511 for (int i = 0; i < 5; i++) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013512 { v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013513 LocalContext context;
13514 }
svenpanne@chromium.orgc859c4f2012-10-15 11:51:39 +000013515 v8::V8::ContextDisposedNotification();
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000013516 CheckSurvivingGlobalObjectsCount(0);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013517
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013518 { v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013519 LocalContext context;
13520 v8_compile("Date")->Run();
13521 }
svenpanne@chromium.orgc859c4f2012-10-15 11:51:39 +000013522 v8::V8::ContextDisposedNotification();
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000013523 CheckSurvivingGlobalObjectsCount(0);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013524
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013525 { v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013526 LocalContext context;
13527 v8_compile("/aaa/")->Run();
13528 }
svenpanne@chromium.orgc859c4f2012-10-15 11:51:39 +000013529 v8::V8::ContextDisposedNotification();
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000013530 CheckSurvivingGlobalObjectsCount(0);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013531
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013532 { v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013533 const char* extension_list[] = { "v8/gc" };
13534 v8::ExtensionConfiguration extensions(1, extension_list);
13535 LocalContext context(&extensions);
13536 v8_compile("gc();")->Run();
13537 }
svenpanne@chromium.orgc859c4f2012-10-15 11:51:39 +000013538 v8::V8::ContextDisposedNotification();
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000013539 CheckSurvivingGlobalObjectsCount(0);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013540 }
13541}
13542
dslomov@chromium.org639bac02013-09-09 11:58:54 +000013543
13544TEST(CopyablePersistent) {
13545 LocalContext context;
13546 v8::Isolate* isolate = context->GetIsolate();
13547 i::GlobalHandles* globals =
13548 reinterpret_cast<i::Isolate*>(isolate)->global_handles();
13549 int initial_handles = globals->global_handles_count();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013550 typedef v8::Persistent<v8::Object, v8::CopyablePersistentTraits<v8::Object> >
13551 CopyableObject;
dslomov@chromium.org639bac02013-09-09 11:58:54 +000013552 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013553 CopyableObject handle1;
dslomov@chromium.org639bac02013-09-09 11:58:54 +000013554 {
13555 v8::HandleScope scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000013556 handle1.Reset(isolate, v8::Object::New(isolate));
dslomov@chromium.org639bac02013-09-09 11:58:54 +000013557 }
13558 CHECK_EQ(initial_handles + 1, globals->global_handles_count());
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013559 CopyableObject handle2;
dslomov@chromium.org639bac02013-09-09 11:58:54 +000013560 handle2 = handle1;
13561 CHECK(handle1 == handle2);
13562 CHECK_EQ(initial_handles + 2, globals->global_handles_count());
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013563 CopyableObject handle3(handle2);
dslomov@chromium.org639bac02013-09-09 11:58:54 +000013564 CHECK(handle1 == handle3);
13565 CHECK_EQ(initial_handles + 3, globals->global_handles_count());
13566 }
13567 // Verify autodispose
hpayer@chromium.orgc5d49712013-09-11 08:25:48 +000013568 CHECK_EQ(initial_handles, globals->global_handles_count());
dslomov@chromium.org639bac02013-09-09 11:58:54 +000013569}
13570
13571
13572static void WeakApiCallback(
13573 const v8::WeakCallbackData<v8::Object, Persistent<v8::Object> >& data) {
13574 Local<Value> value = data.GetValue()->Get(v8_str("key"));
13575 CHECK_EQ(231, static_cast<int32_t>(Local<v8::Integer>::Cast(value)->Value()));
13576 data.GetParameter()->Reset();
13577 delete data.GetParameter();
13578}
13579
13580
13581TEST(WeakCallbackApi) {
13582 LocalContext context;
13583 v8::Isolate* isolate = context->GetIsolate();
13584 i::GlobalHandles* globals =
13585 reinterpret_cast<i::Isolate*>(isolate)->global_handles();
13586 int initial_handles = globals->global_handles_count();
13587 {
13588 v8::HandleScope scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000013589 v8::Local<v8::Object> obj = v8::Object::New(isolate);
13590 obj->Set(v8_str("key"), v8::Integer::New(isolate, 231));
dslomov@chromium.org639bac02013-09-09 11:58:54 +000013591 v8::Persistent<v8::Object>* handle =
13592 new v8::Persistent<v8::Object>(isolate, obj);
13593 handle->SetWeak<v8::Object, v8::Persistent<v8::Object> >(handle,
13594 WeakApiCallback);
13595 }
13596 reinterpret_cast<i::Isolate*>(isolate)->heap()->
13597 CollectAllGarbage(i::Heap::kNoGCFlags);
13598 // Verify disposed.
13599 CHECK_EQ(initial_handles, globals->global_handles_count());
13600}
13601
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013602
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000013603v8::Persistent<v8::Object> some_object;
13604v8::Persistent<v8::Object> bad_handle;
13605
machenbach@chromium.orgddf38112013-12-04 09:42:52 +000013606void NewPersistentHandleCallback(
13607 const v8::WeakCallbackData<v8::Object, v8::Persistent<v8::Object> >& data) {
13608 v8::HandleScope scope(data.GetIsolate());
13609 bad_handle.Reset(data.GetIsolate(), some_object);
13610 data.GetParameter()->Reset();
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000013611}
13612
13613
13614THREADED_TEST(NewPersistentHandleFromWeakCallback) {
13615 LocalContext context;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000013616 v8::Isolate* isolate = context->GetIsolate();
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000013617
13618 v8::Persistent<v8::Object> handle1, handle2;
13619 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013620 v8::HandleScope scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000013621 some_object.Reset(isolate, v8::Object::New(isolate));
13622 handle1.Reset(isolate, v8::Object::New(isolate));
13623 handle2.Reset(isolate, v8::Object::New(isolate));
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000013624 }
13625 // Note: order is implementation dependent alas: currently
13626 // global handle nodes are processed by PostGarbageCollectionProcessing
13627 // in reverse allocation order, so if second allocated handle is deleted,
13628 // weak callback of the first handle would be able to 'reallocate' it.
machenbach@chromium.orgddf38112013-12-04 09:42:52 +000013629 handle1.SetWeak(&handle1, NewPersistentHandleCallback);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000013630 handle2.Reset();
machenbach@chromium.orgddf38112013-12-04 09:42:52 +000013631 CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000013632}
13633
13634
13635v8::Persistent<v8::Object> to_be_disposed;
13636
machenbach@chromium.orgddf38112013-12-04 09:42:52 +000013637void DisposeAndForceGcCallback(
13638 const v8::WeakCallbackData<v8::Object, v8::Persistent<v8::Object> >& data) {
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000013639 to_be_disposed.Reset();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013640 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
machenbach@chromium.orgddf38112013-12-04 09:42:52 +000013641 data.GetParameter()->Reset();
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000013642}
13643
13644
13645THREADED_TEST(DoNotUseDeletedNodesInSecondLevelGc) {
13646 LocalContext context;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000013647 v8::Isolate* isolate = context->GetIsolate();
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000013648
13649 v8::Persistent<v8::Object> handle1, handle2;
13650 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013651 v8::HandleScope scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000013652 handle1.Reset(isolate, v8::Object::New(isolate));
13653 handle2.Reset(isolate, v8::Object::New(isolate));
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000013654 }
machenbach@chromium.orgddf38112013-12-04 09:42:52 +000013655 handle1.SetWeak(&handle1, DisposeAndForceGcCallback);
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000013656 to_be_disposed.Reset(isolate, handle2);
machenbach@chromium.orgddf38112013-12-04 09:42:52 +000013657 CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000013658}
13659
machenbach@chromium.orgddf38112013-12-04 09:42:52 +000013660void DisposingCallback(
13661 const v8::WeakCallbackData<v8::Object, v8::Persistent<v8::Object> >& data) {
13662 data.GetParameter()->Reset();
ager@chromium.orgc4c92722009-11-18 14:12:51 +000013663}
13664
machenbach@chromium.orgddf38112013-12-04 09:42:52 +000013665void HandleCreatingCallback(
13666 const v8::WeakCallbackData<v8::Object, v8::Persistent<v8::Object> >& data) {
13667 v8::HandleScope scope(data.GetIsolate());
ulan@chromium.org0f13e742014-01-03 15:51:11 +000013668 v8::Persistent<v8::Object>(data.GetIsolate(),
13669 v8::Object::New(data.GetIsolate()));
machenbach@chromium.orgddf38112013-12-04 09:42:52 +000013670 data.GetParameter()->Reset();
ager@chromium.orgc4c92722009-11-18 14:12:51 +000013671}
13672
13673
13674THREADED_TEST(NoGlobalHandlesOrphaningDueToWeakCallback) {
13675 LocalContext context;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000013676 v8::Isolate* isolate = context->GetIsolate();
ager@chromium.orgc4c92722009-11-18 14:12:51 +000013677
13678 v8::Persistent<v8::Object> handle1, handle2, handle3;
13679 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000013680 v8::HandleScope scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000013681 handle3.Reset(isolate, v8::Object::New(isolate));
13682 handle2.Reset(isolate, v8::Object::New(isolate));
13683 handle1.Reset(isolate, v8::Object::New(isolate));
ager@chromium.orgc4c92722009-11-18 14:12:51 +000013684 }
machenbach@chromium.orgddf38112013-12-04 09:42:52 +000013685 handle2.SetWeak(&handle2, DisposingCallback);
13686 handle3.SetWeak(&handle3, HandleCreatingCallback);
13687 CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
ager@chromium.orgc4c92722009-11-18 14:12:51 +000013688}
13689
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000013690
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013691THREADED_TEST(CheckForCrossContextObjectLiterals) {
kasperl@chromium.orgb9123622008-09-17 14:05:56 +000013692 v8::V8::Initialize();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013693
13694 const int nof = 2;
13695 const char* sources[nof] = {
13696 "try { [ 2, 3, 4 ].forEach(5); } catch(e) { e.toString(); }",
13697 "Object()"
13698 };
13699
13700 for (int i = 0; i < nof; i++) {
13701 const char* source = sources[i];
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013702 { v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013703 LocalContext context;
13704 CompileRun(source);
13705 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013706 { v8::HandleScope scope(CcTest::isolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013707 LocalContext context;
13708 CompileRun(source);
13709 }
13710 }
13711}
13712
13713
ulan@chromium.org57ff8812013-05-10 08:16:55 +000013714static v8::Handle<Value> NestedScope(v8::Local<Context> env) {
machenbach@chromium.orgafbdadc2013-12-09 16:12:18 +000013715 v8::EscapableHandleScope inner(env->GetIsolate());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013716 env->Enter();
machenbach@chromium.orgafbdadc2013-12-09 16:12:18 +000013717 v8::Local<Value> three = v8_num(3);
13718 v8::Local<Value> value = inner.Escape(three);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013719 env->Exit();
13720 return value;
13721}
13722
13723
13724THREADED_TEST(NestedHandleScopeAndContexts) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000013725 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000013726 v8::HandleScope outer(isolate);
13727 v8::Local<Context> env = Context::New(isolate);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013728 env->Enter();
13729 v8::Handle<Value> value = NestedScope(env);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000013730 v8::Handle<String> str(value->ToString());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000013731 CHECK(!str.IsEmpty());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013732 env->Exit();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000013733}
13734
13735
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013736static bool MatchPointers(void* key1, void* key2) {
13737 return key1 == key2;
13738}
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013739
13740
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013741struct SymbolInfo {
13742 size_t id;
13743 size_t size;
13744 std::string name;
13745};
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013746
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013747
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013748class SetFunctionEntryHookTest {
13749 public:
13750 SetFunctionEntryHookTest() {
13751 CHECK(instance_ == NULL);
13752 instance_ = this;
13753 }
13754 ~SetFunctionEntryHookTest() {
13755 CHECK(instance_ == this);
13756 instance_ = NULL;
13757 }
13758 void Reset() {
13759 symbols_.clear();
13760 symbol_locations_.clear();
13761 invocations_.clear();
13762 }
13763 void RunTest();
13764 void OnJitEvent(const v8::JitCodeEvent* event);
13765 static void JitEvent(const v8::JitCodeEvent* event) {
13766 CHECK(instance_ != NULL);
13767 instance_->OnJitEvent(event);
13768 }
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013769
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013770 void OnEntryHook(uintptr_t function,
13771 uintptr_t return_addr_location);
13772 static void EntryHook(uintptr_t function,
13773 uintptr_t return_addr_location) {
13774 CHECK(instance_ != NULL);
13775 instance_->OnEntryHook(function, return_addr_location);
13776 }
ulan@chromium.orgdfe53072013-06-06 14:14:51 +000013777
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013778 static void RuntimeCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
13779 CHECK(instance_ != NULL);
13780 args.GetReturnValue().Set(v8_num(42));
13781 }
13782 void RunLoopInNewEnv(v8::Isolate* isolate);
13783
13784 // Records addr as location of symbol.
13785 void InsertSymbolAt(i::Address addr, SymbolInfo* symbol);
13786
13787 // Finds the symbol containing addr
13788 SymbolInfo* FindSymbolForAddr(i::Address addr);
13789 // Returns the number of invocations where the caller name contains
13790 // \p caller_name and the function name contains \p function_name.
13791 int CountInvocations(const char* caller_name,
13792 const char* function_name);
13793
13794 i::Handle<i::JSFunction> foo_func_;
13795 i::Handle<i::JSFunction> bar_func_;
13796
13797 typedef std::map<size_t, SymbolInfo> SymbolMap;
13798 typedef std::map<i::Address, SymbolInfo*> SymbolLocationMap;
13799 typedef std::map<std::pair<SymbolInfo*, SymbolInfo*>, int> InvocationMap;
13800 SymbolMap symbols_;
13801 SymbolLocationMap symbol_locations_;
13802 InvocationMap invocations_;
13803
13804 static SetFunctionEntryHookTest* instance_;
13805};
13806SetFunctionEntryHookTest* SetFunctionEntryHookTest::instance_ = NULL;
13807
13808
13809// Returns true if addr is in the range [start, start+len).
13810static bool Overlaps(i::Address start, size_t len, i::Address addr) {
13811 if (start <= addr && start + len > addr)
13812 return true;
13813
13814 return false;
13815}
13816
13817void SetFunctionEntryHookTest::InsertSymbolAt(i::Address addr,
13818 SymbolInfo* symbol) {
13819 // Insert the symbol at the new location.
13820 SymbolLocationMap::iterator it =
13821 symbol_locations_.insert(std::make_pair(addr, symbol)).first;
13822 // Now erase symbols to the left and right that overlap this one.
13823 while (it != symbol_locations_.begin()) {
13824 SymbolLocationMap::iterator left = it;
13825 --left;
13826 if (!Overlaps(left->first, left->second->size, addr))
13827 break;
13828 symbol_locations_.erase(left);
13829 }
13830
13831 // Now erase symbols to the left and right that overlap this one.
13832 while (true) {
13833 SymbolLocationMap::iterator right = it;
13834 ++right;
13835 if (right == symbol_locations_.end())
13836 break;
13837 if (!Overlaps(addr, symbol->size, right->first))
13838 break;
13839 symbol_locations_.erase(right);
ulan@chromium.orgdfe53072013-06-06 14:14:51 +000013840 }
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013841}
13842
13843
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013844void SetFunctionEntryHookTest::OnJitEvent(const v8::JitCodeEvent* event) {
13845 switch (event->type) {
13846 case v8::JitCodeEvent::CODE_ADDED: {
13847 CHECK(event->code_start != NULL);
13848 CHECK_NE(0, static_cast<int>(event->code_len));
13849 CHECK(event->name.str != NULL);
13850 size_t symbol_id = symbols_.size();
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013851
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013852 // Record the new symbol.
13853 SymbolInfo& info = symbols_[symbol_id];
13854 info.id = symbol_id;
13855 info.size = event->code_len;
13856 info.name.assign(event->name.str, event->name.str + event->name.len);
13857
13858 // And record it's location.
13859 InsertSymbolAt(reinterpret_cast<i::Address>(event->code_start), &info);
13860 }
13861 break;
13862
13863 case v8::JitCodeEvent::CODE_MOVED: {
13864 // We would like to never see code move that we haven't seen before,
13865 // but the code creation event does not happen until the line endings
13866 // have been calculated (this is so that we can report the line in the
13867 // script at which the function source is found, see
13868 // Compiler::RecordFunctionCompilation) and the line endings
13869 // calculations can cause a GC, which can move the newly created code
13870 // before its existence can be logged.
13871 SymbolLocationMap::iterator it(
13872 symbol_locations_.find(
13873 reinterpret_cast<i::Address>(event->code_start)));
13874 if (it != symbol_locations_.end()) {
13875 // Found a symbol at this location, move it.
13876 SymbolInfo* info = it->second;
13877 symbol_locations_.erase(it);
13878 InsertSymbolAt(reinterpret_cast<i::Address>(event->new_code_start),
13879 info);
13880 }
13881 }
13882 default:
13883 break;
13884 }
13885}
13886
13887void SetFunctionEntryHookTest::OnEntryHook(
13888 uintptr_t function, uintptr_t return_addr_location) {
13889 // Get the function's code object.
13890 i::Code* function_code = i::Code::GetCodeFromTargetAddress(
13891 reinterpret_cast<i::Address>(function));
13892 CHECK(function_code != NULL);
13893
13894 // Then try and look up the caller's code object.
13895 i::Address caller = *reinterpret_cast<i::Address*>(return_addr_location);
13896
13897 // Count the invocation.
13898 SymbolInfo* caller_symbol = FindSymbolForAddr(caller);
13899 SymbolInfo* function_symbol =
13900 FindSymbolForAddr(reinterpret_cast<i::Address>(function));
13901 ++invocations_[std::make_pair(caller_symbol, function_symbol)];
13902
13903 if (!bar_func_.is_null() && function_code == bar_func_->code()) {
13904 // Check that we have a symbol for the "bar" function at the right location.
13905 SymbolLocationMap::iterator it(
13906 symbol_locations_.find(function_code->instruction_start()));
13907 CHECK(it != symbol_locations_.end());
13908 }
13909
13910 if (!foo_func_.is_null() && function_code == foo_func_->code()) {
13911 // Check that we have a symbol for "foo" at the right location.
13912 SymbolLocationMap::iterator it(
13913 symbol_locations_.find(function_code->instruction_start()));
13914 CHECK(it != symbol_locations_.end());
13915 }
13916}
13917
13918
13919SymbolInfo* SetFunctionEntryHookTest::FindSymbolForAddr(i::Address addr) {
13920 SymbolLocationMap::iterator it(symbol_locations_.lower_bound(addr));
13921 // Do we have a direct hit on a symbol?
13922 if (it != symbol_locations_.end()) {
13923 if (it->first == addr)
13924 return it->second;
13925 }
13926
13927 // If not a direct hit, it'll have to be the previous symbol.
13928 if (it == symbol_locations_.begin())
13929 return NULL;
13930
13931 --it;
13932 size_t offs = addr - it->first;
13933 if (offs < it->second->size)
13934 return it->second;
13935
13936 return NULL;
13937}
13938
13939
13940int SetFunctionEntryHookTest::CountInvocations(
13941 const char* caller_name, const char* function_name) {
13942 InvocationMap::iterator it(invocations_.begin());
13943 int invocations = 0;
13944 for (; it != invocations_.end(); ++it) {
13945 SymbolInfo* caller = it->first.first;
13946 SymbolInfo* function = it->first.second;
13947
13948 // Filter out non-matching functions.
13949 if (function_name != NULL) {
13950 if (function->name.find(function_name) == std::string::npos)
13951 continue;
13952 }
13953
13954 // Filter out non-matching callers.
13955 if (caller_name != NULL) {
13956 if (caller == NULL)
13957 continue;
13958 if (caller->name.find(caller_name) == std::string::npos)
13959 continue;
13960 }
13961
13962 // It matches add the invocation count to the tally.
13963 invocations += it->second;
13964 }
13965
13966 return invocations;
13967}
13968
13969
13970void SetFunctionEntryHookTest::RunLoopInNewEnv(v8::Isolate* isolate) {
ulan@chromium.org57ff8812013-05-10 08:16:55 +000013971 v8::HandleScope outer(isolate);
13972 v8::Local<Context> env = Context::New(isolate);
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013973 env->Enter();
13974
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000013975 Local<ObjectTemplate> t = ObjectTemplate::New(isolate);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000013976 t->Set(v8_str("asdf"), v8::FunctionTemplate::New(isolate, RuntimeCallback));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013977 env->Global()->Set(v8_str("obj"), t->NewInstance());
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013978
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013979 const char* script =
13980 "function bar() {\n"
13981 " var sum = 0;\n"
13982 " for (i = 0; i < 100; ++i)\n"
13983 " sum = foo(i);\n"
13984 " return sum;\n"
13985 "}\n"
13986 "function foo(i) { return i * i; }\n"
13987 "// Invoke on the runtime function.\n"
13988 "obj.asdf()";
13989 CompileRun(script);
13990 bar_func_ = i::Handle<i::JSFunction>::cast(
13991 v8::Utils::OpenHandle(*env->Global()->Get(v8_str("bar"))));
13992 ASSERT(!bar_func_.is_null());
13993
13994 foo_func_ =
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013995 i::Handle<i::JSFunction>::cast(
13996 v8::Utils::OpenHandle(*env->Global()->Get(v8_str("foo"))));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000013997 ASSERT(!foo_func_.is_null());
verwaest@chromium.org753aee42012-07-17 16:15:42 +000013998
13999 v8::Handle<v8::Value> value = CompileRun("bar();");
14000 CHECK(value->IsNumber());
14001 CHECK_EQ(9801.0, v8::Number::Cast(*value)->Value());
14002
14003 // Test the optimized codegen path.
14004 value = CompileRun("%OptimizeFunctionOnNextCall(foo);"
14005 "bar();");
14006 CHECK(value->IsNumber());
14007 CHECK_EQ(9801.0, v8::Number::Cast(*value)->Value());
14008
14009 env->Exit();
14010}
14011
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000014012
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000014013void SetFunctionEntryHookTest::RunTest() {
14014 // Work in a new isolate throughout.
14015 v8::Isolate* isolate = v8::Isolate::New();
14016
14017 // Test setting the entry hook on the new isolate.
14018 CHECK(v8::V8::SetFunctionEntryHook(isolate, EntryHook));
14019
14020 // Replacing the hook, once set should fail.
14021 CHECK_EQ(false, v8::V8::SetFunctionEntryHook(isolate, EntryHook));
14022
14023 {
14024 v8::Isolate::Scope scope(isolate);
14025
14026 v8::V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault, JitEvent);
14027
14028 RunLoopInNewEnv(isolate);
14029
14030 // Check the exepected invocation counts.
14031 CHECK_EQ(2, CountInvocations(NULL, "bar"));
14032 CHECK_EQ(200, CountInvocations("bar", "foo"));
14033 CHECK_EQ(200, CountInvocations(NULL, "foo"));
14034
14035 // Verify that we have an entry hook on some specific stubs.
14036 CHECK_NE(0, CountInvocations(NULL, "CEntryStub"));
14037 CHECK_NE(0, CountInvocations(NULL, "JSEntryStub"));
14038 CHECK_NE(0, CountInvocations(NULL, "JSEntryTrampoline"));
14039 }
14040 isolate->Dispose();
14041
14042 Reset();
14043
14044 // Make sure a second isolate is unaffected by the previous entry hook.
14045 isolate = v8::Isolate::New();
14046 {
14047 v8::Isolate::Scope scope(isolate);
14048
14049 // Reset the entry count to zero and set the entry hook.
14050 RunLoopInNewEnv(isolate);
14051
14052 // We should record no invocations in this isolate.
14053 CHECK_EQ(0, static_cast<int>(invocations_.size()));
14054 }
14055 // Since the isolate has been used, we shouldn't be able to set an entry
14056 // hook anymore.
14057 CHECK_EQ(false, v8::V8::SetFunctionEntryHook(isolate, EntryHook));
14058
14059 isolate->Dispose();
14060}
14061
verwaest@chromium.org753aee42012-07-17 16:15:42 +000014062
14063TEST(SetFunctionEntryHook) {
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000014064 // FunctionEntryHook does not work well with experimental natives.
14065 // Experimental natives are compiled during snapshot deserialization.
14066 // This test breaks because InstallGetter (function from snapshot that
14067 // only gets called from experimental natives) is compiled with entry hooks.
verwaest@chromium.org753aee42012-07-17 16:15:42 +000014068 i::FLAG_allow_natives_syntax = true;
yangguo@chromium.orgfb377212012-11-16 14:43:43 +000014069 i::FLAG_use_inlining = false;
verwaest@chromium.org753aee42012-07-17 16:15:42 +000014070
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000014071 SetFunctionEntryHookTest test;
14072 test.RunTest();
verwaest@chromium.org753aee42012-07-17 16:15:42 +000014073}
14074
14075
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014076static i::HashMap* code_map = NULL;
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +000014077static i::HashMap* jitcode_line_info = NULL;
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014078static int saw_bar = 0;
14079static int move_events = 0;
14080
14081
14082static bool FunctionNameIs(const char* expected,
14083 const v8::JitCodeEvent* event) {
14084 // Log lines for functions are of the general form:
14085 // "LazyCompile:<type><function_name>", where the type is one of
14086 // "*", "~" or "".
14087 static const char kPreamble[] = "LazyCompile:";
14088 static size_t kPreambleLen = sizeof(kPreamble) - 1;
14089
14090 if (event->name.len < sizeof(kPreamble) - 1 ||
14091 strncmp(kPreamble, event->name.str, kPreambleLen) != 0) {
14092 return false;
14093 }
14094
14095 const char* tail = event->name.str + kPreambleLen;
14096 size_t tail_len = event->name.len - kPreambleLen;
14097 size_t expected_len = strlen(expected);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000014098 if (tail_len > 1 && (*tail == '*' || *tail == '~')) {
14099 --tail_len;
14100 ++tail;
14101 }
14102
14103 // Check for tails like 'bar :1'.
14104 if (tail_len > expected_len + 2 &&
14105 tail[expected_len] == ' ' &&
14106 tail[expected_len + 1] == ':' &&
14107 tail[expected_len + 2] &&
14108 !strncmp(tail, expected, expected_len)) {
14109 return true;
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014110 }
14111
14112 if (tail_len != expected_len)
14113 return false;
14114
14115 return strncmp(tail, expected, expected_len) == 0;
14116}
14117
14118
14119static void event_handler(const v8::JitCodeEvent* event) {
14120 CHECK(event != NULL);
14121 CHECK(code_map != NULL);
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +000014122 CHECK(jitcode_line_info != NULL);
14123
14124 class DummyJitCodeLineInfo {
14125 };
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014126
14127 switch (event->type) {
14128 case v8::JitCodeEvent::CODE_ADDED: {
14129 CHECK(event->code_start != NULL);
14130 CHECK_NE(0, static_cast<int>(event->code_len));
14131 CHECK(event->name.str != NULL);
14132 i::HashMap::Entry* entry =
14133 code_map->Lookup(event->code_start,
14134 i::ComputePointerHash(event->code_start),
14135 true);
14136 entry->value = reinterpret_cast<void*>(event->code_len);
14137
14138 if (FunctionNameIs("bar", event)) {
14139 ++saw_bar;
14140 }
14141 }
14142 break;
14143
14144 case v8::JitCodeEvent::CODE_MOVED: {
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014145 uint32_t hash = i::ComputePointerHash(event->code_start);
jkummerow@chromium.org78502a92012-09-06 13:50:42 +000014146 // We would like to never see code move that we haven't seen before,
14147 // but the code creation event does not happen until the line endings
14148 // have been calculated (this is so that we can report the line in the
14149 // script at which the function source is found, see
14150 // Compiler::RecordFunctionCompilation) and the line endings
14151 // calculations can cause a GC, which can move the newly created code
14152 // before its existence can be logged.
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014153 i::HashMap::Entry* entry =
14154 code_map->Lookup(event->code_start, hash, false);
jkummerow@chromium.org78502a92012-09-06 13:50:42 +000014155 if (entry != NULL) {
14156 ++move_events;
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014157
jkummerow@chromium.org78502a92012-09-06 13:50:42 +000014158 CHECK_EQ(reinterpret_cast<void*>(event->code_len), entry->value);
14159 code_map->Remove(event->code_start, hash);
14160
14161 entry = code_map->Lookup(event->new_code_start,
14162 i::ComputePointerHash(event->new_code_start),
14163 true);
14164 CHECK(entry != NULL);
14165 entry->value = reinterpret_cast<void*>(event->code_len);
14166 }
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014167 }
14168 break;
14169
14170 case v8::JitCodeEvent::CODE_REMOVED:
14171 // Object/code removal events are currently not dispatched from the GC.
14172 CHECK(false);
14173 break;
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +000014174
14175 // For CODE_START_LINE_INFO_RECORDING event, we will create one
14176 // DummyJitCodeLineInfo data structure pointed by event->user_dat. We
14177 // record it in jitcode_line_info.
14178 case v8::JitCodeEvent::CODE_START_LINE_INFO_RECORDING: {
14179 DummyJitCodeLineInfo* line_info = new DummyJitCodeLineInfo();
14180 v8::JitCodeEvent* temp_event = const_cast<v8::JitCodeEvent*>(event);
14181 temp_event->user_data = line_info;
14182 i::HashMap::Entry* entry =
14183 jitcode_line_info->Lookup(line_info,
14184 i::ComputePointerHash(line_info),
14185 true);
14186 entry->value = reinterpret_cast<void*>(line_info);
14187 }
14188 break;
14189 // For these two events, we will check whether the event->user_data
14190 // data structure is created before during CODE_START_LINE_INFO_RECORDING
14191 // event. And delete it in CODE_END_LINE_INFO_RECORDING event handling.
14192 case v8::JitCodeEvent::CODE_END_LINE_INFO_RECORDING: {
14193 CHECK(event->user_data != NULL);
14194 uint32_t hash = i::ComputePointerHash(event->user_data);
14195 i::HashMap::Entry* entry =
14196 jitcode_line_info->Lookup(event->user_data, hash, false);
14197 CHECK(entry != NULL);
14198 delete reinterpret_cast<DummyJitCodeLineInfo*>(event->user_data);
14199 }
14200 break;
14201
14202 case v8::JitCodeEvent::CODE_ADD_LINE_POS_INFO: {
14203 CHECK(event->user_data != NULL);
14204 uint32_t hash = i::ComputePointerHash(event->user_data);
14205 i::HashMap::Entry* entry =
14206 jitcode_line_info->Lookup(event->user_data, hash, false);
14207 CHECK(entry != NULL);
14208 }
14209 break;
14210
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014211 default:
14212 // Impossible event.
14213 CHECK(false);
14214 break;
14215 }
14216}
14217
14218
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014219UNINITIALIZED_TEST(SetJitCodeEventHandler) {
ulan@chromium.org6ba1fd02013-02-14 14:56:11 +000014220 i::FLAG_stress_compaction = true;
danno@chromium.orgf005df62013-04-30 16:36:45 +000014221 i::FLAG_incremental_marking = false;
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014222 const char* script =
14223 "function bar() {"
14224 " var sum = 0;"
14225 " for (i = 0; i < 100; ++i)"
14226 " sum = foo(i);"
14227 " return sum;"
14228 "}"
14229 "function foo(i) { return i * i; };"
14230 "bar();";
14231
14232 // Run this test in a new isolate to make sure we don't
14233 // have remnants of state from other code.
14234 v8::Isolate* isolate = v8::Isolate::New();
14235 isolate->Enter();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014236 i::Heap* heap = reinterpret_cast<i::Isolate*>(isolate)->heap();
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014237
14238 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000014239 v8::HandleScope scope(isolate);
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014240 i::HashMap code(MatchPointers);
14241 code_map = &code;
14242
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +000014243 i::HashMap lineinfo(MatchPointers);
14244 jitcode_line_info = &lineinfo;
14245
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014246 saw_bar = 0;
14247 move_events = 0;
14248
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014249 V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault, event_handler);
14250
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014251 // Generate new code objects sparsely distributed across several
14252 // different fragmented code-space pages.
14253 const int kIterations = 10;
14254 for (int i = 0; i < kIterations; ++i) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014255 LocalContext env(isolate);
ulan@chromium.org6ba1fd02013-02-14 14:56:11 +000014256 i::AlwaysAllocateScope always_allocate;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014257 SimulateFullSpace(heap->code_space());
ulan@chromium.org6ba1fd02013-02-14 14:56:11 +000014258 CompileRun(script);
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014259
ulan@chromium.org6ba1fd02013-02-14 14:56:11 +000014260 // Keep a strong reference to the code object in the handle scope.
14261 i::Handle<i::Code> bar_code(i::Handle<i::JSFunction>::cast(
14262 v8::Utils::OpenHandle(*env->Global()->Get(v8_str("bar"))))->code());
14263 i::Handle<i::Code> foo_code(i::Handle<i::JSFunction>::cast(
14264 v8::Utils::OpenHandle(*env->Global()->Get(v8_str("foo"))))->code());
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014265
14266 // Clear the compilation cache to get more wastage.
hpayer@chromium.orgc5d49712013-09-11 08:25:48 +000014267 reinterpret_cast<i::Isolate*>(isolate)->compilation_cache()->Clear();
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014268 }
14269
14270 // Force code movement.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014271 heap->CollectAllAvailableGarbage("TestSetJitCodeEventHandler");
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014272
ulan@chromium.org6ba1fd02013-02-14 14:56:11 +000014273 V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault, NULL);
14274
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014275 CHECK_LE(kIterations, saw_bar);
ulan@chromium.org6ba1fd02013-02-14 14:56:11 +000014276 CHECK_LT(0, move_events);
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014277
14278 code_map = NULL;
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +000014279 jitcode_line_info = NULL;
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014280 }
14281
14282 isolate->Exit();
14283 isolate->Dispose();
14284
14285 // Do this in a new isolate.
14286 isolate = v8::Isolate::New();
14287 isolate->Enter();
14288
14289 // Verify that we get callbacks for existing code objects when we
14290 // request enumeration of existing code.
14291 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000014292 v8::HandleScope scope(isolate);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014293 LocalContext env(isolate);
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014294 CompileRun(script);
14295
14296 // Now get code through initial iteration.
14297 i::HashMap code(MatchPointers);
14298 code_map = &code;
14299
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +000014300 i::HashMap lineinfo(MatchPointers);
14301 jitcode_line_info = &lineinfo;
14302
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014303 V8::SetJitCodeEventHandler(v8::kJitCodeEventEnumExisting, event_handler);
14304 V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault, NULL);
14305
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +000014306 jitcode_line_info = NULL;
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014307 // We expect that we got some events. Note that if we could get code removal
14308 // notifications, we could compare two collections, one created by listening
14309 // from the time of creation of an isolate, and the other by subscribing
14310 // with EnumExisting.
ulan@chromium.org6ba1fd02013-02-14 14:56:11 +000014311 CHECK_LT(0, code.occupancy());
14312
14313 code_map = NULL;
yangguo@chromium.org355cfd12012-08-29 15:32:24 +000014314 }
14315
14316 isolate->Exit();
14317 isolate->Dispose();
14318}
14319
14320
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000014321THREADED_TEST(ExternalAllocatedMemory) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014322 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000014323 v8::HandleScope outer(isolate);
14324 v8::Local<Context> env(Context::New(isolate));
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000014325 CHECK(!env.IsEmpty());
machenbach@chromium.org7ff76072013-11-21 09:47:43 +000014326 const int64_t kSize = 1024*1024;
14327 int64_t baseline = isolate->AdjustAmountOfExternalAllocatedMemory(0);
14328 CHECK_EQ(baseline + kSize,
14329 isolate->AdjustAmountOfExternalAllocatedMemory(kSize));
danno@chromium.orgf005df62013-04-30 16:36:45 +000014330 CHECK_EQ(baseline,
machenbach@chromium.org7ff76072013-11-21 09:47:43 +000014331 isolate->AdjustAmountOfExternalAllocatedMemory(-kSize));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000014332}
14333
14334
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014335// Regression test for issue 54, object templates with internal fields
14336// but no accessors or interceptors did not get their internal field
14337// count set on instances.
14338THREADED_TEST(Regress54) {
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014339 LocalContext context;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000014340 v8::Isolate* isolate = context->GetIsolate();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000014341 v8::HandleScope outer(isolate);
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014342 static v8::Persistent<v8::ObjectTemplate> templ;
14343 if (templ.IsEmpty()) {
machenbach@chromium.orgafbdadc2013-12-09 16:12:18 +000014344 v8::EscapableHandleScope inner(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000014345 v8::Local<v8::ObjectTemplate> local = v8::ObjectTemplate::New(isolate);
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014346 local->SetInternalFieldCount(1);
machenbach@chromium.orgafbdadc2013-12-09 16:12:18 +000014347 templ.Reset(isolate, inner.Escape(local));
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014348 }
rossberg@chromium.org79e79022013-06-03 15:43:46 +000014349 v8::Handle<v8::Object> result =
14350 v8::Local<v8::ObjectTemplate>::New(isolate, templ)->NewInstance();
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014351 CHECK_EQ(1, result->InternalFieldCount());
14352}
14353
14354
14355// If part of the threaded tests, this test makes ThreadingTest fail
14356// on mac.
14357TEST(CatchStackOverflow) {
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014358 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000014359 v8::HandleScope scope(context->GetIsolate());
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014360 v8::TryCatch try_catch;
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000014361 v8::Handle<v8::Script> script = v8::Script::Compile(v8::String::NewFromUtf8(
14362 context->GetIsolate(),
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014363 "function f() {"
14364 " return f();"
14365 "}"
14366 ""
14367 "f();"));
14368 v8::Handle<v8::Value> result = script->Run();
14369 CHECK(result.IsEmpty());
14370}
14371
14372
kasperl@chromium.org7be3c992009-03-12 07:19:55 +000014373static void CheckTryCatchSourceInfo(v8::Handle<v8::Script> script,
14374 const char* resource_name,
14375 int line_offset) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014376 v8::HandleScope scope(CcTest::isolate());
kasperl@chromium.org7be3c992009-03-12 07:19:55 +000014377 v8::TryCatch try_catch;
14378 v8::Handle<v8::Value> result = script->Run();
14379 CHECK(result.IsEmpty());
14380 CHECK(try_catch.HasCaught());
14381 v8::Handle<v8::Message> message = try_catch.Message();
14382 CHECK(!message.IsEmpty());
14383 CHECK_EQ(10 + line_offset, message->GetLineNumber());
14384 CHECK_EQ(91, message->GetStartPosition());
14385 CHECK_EQ(92, message->GetEndPosition());
14386 CHECK_EQ(2, message->GetStartColumn());
14387 CHECK_EQ(3, message->GetEndColumn());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000014388 v8::String::Utf8Value line(message->GetSourceLine());
kasperl@chromium.org7be3c992009-03-12 07:19:55 +000014389 CHECK_EQ(" throw 'nirk';", *line);
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000014390 v8::String::Utf8Value name(message->GetScriptResourceName());
kasperl@chromium.org7be3c992009-03-12 07:19:55 +000014391 CHECK_EQ(resource_name, *name);
14392}
14393
14394
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014395THREADED_TEST(TryCatchSourceInfo) {
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014396 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000014397 v8::HandleScope scope(context->GetIsolate());
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000014398 v8::Handle<v8::String> source = v8::String::NewFromUtf8(
14399 context->GetIsolate(),
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014400 "function Foo() {\n"
14401 " return Bar();\n"
14402 "}\n"
14403 "\n"
14404 "function Bar() {\n"
14405 " return Baz();\n"
14406 "}\n"
14407 "\n"
14408 "function Baz() {\n"
14409 " throw 'nirk';\n"
14410 "}\n"
14411 "\n"
14412 "Foo();\n");
kasperl@chromium.org7be3c992009-03-12 07:19:55 +000014413
14414 const char* resource_name;
14415 v8::Handle<v8::Script> script;
14416 resource_name = "test.js";
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000014417 script = v8::Script::Compile(
14418 source, v8::String::NewFromUtf8(context->GetIsolate(), resource_name));
kasperl@chromium.org7be3c992009-03-12 07:19:55 +000014419 CheckTryCatchSourceInfo(script, resource_name, 0);
14420
14421 resource_name = "test1.js";
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000014422 v8::ScriptOrigin origin1(
14423 v8::String::NewFromUtf8(context->GetIsolate(), resource_name));
kasperl@chromium.org7be3c992009-03-12 07:19:55 +000014424 script = v8::Script::Compile(source, &origin1);
14425 CheckTryCatchSourceInfo(script, resource_name, 0);
14426
14427 resource_name = "test2.js";
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000014428 v8::ScriptOrigin origin2(
14429 v8::String::NewFromUtf8(context->GetIsolate(), resource_name),
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014430 v8::Integer::New(context->GetIsolate(), 7));
kasperl@chromium.org7be3c992009-03-12 07:19:55 +000014431 script = v8::Script::Compile(source, &origin2);
14432 CheckTryCatchSourceInfo(script, resource_name, 7);
ager@chromium.org9258b6b2008-09-11 09:11:10 +000014433}
kasperl@chromium.orgb9123622008-09-17 14:05:56 +000014434
14435
14436THREADED_TEST(CompilationCache) {
kasperl@chromium.orgb9123622008-09-17 14:05:56 +000014437 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000014438 v8::HandleScope scope(context->GetIsolate());
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000014439 v8::Handle<v8::String> source0 =
14440 v8::String::NewFromUtf8(context->GetIsolate(), "1234");
14441 v8::Handle<v8::String> source1 =
14442 v8::String::NewFromUtf8(context->GetIsolate(), "1234");
14443 v8::Handle<v8::Script> script0 = v8::Script::Compile(
14444 source0, v8::String::NewFromUtf8(context->GetIsolate(), "test.js"));
14445 v8::Handle<v8::Script> script1 = v8::Script::Compile(
14446 source1, v8::String::NewFromUtf8(context->GetIsolate(), "test.js"));
kasperl@chromium.orgb9123622008-09-17 14:05:56 +000014447 v8::Handle<v8::Script> script2 =
14448 v8::Script::Compile(source0); // different origin
14449 CHECK_EQ(1234, script0->Run()->Int32Value());
14450 CHECK_EQ(1234, script1->Run()->Int32Value());
14451 CHECK_EQ(1234, script2->Run()->Int32Value());
14452}
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000014453
14454
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000014455static void FunctionNameCallback(
14456 const v8::FunctionCallbackInfo<v8::Value>& args) {
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000014457 ApiTestFuzzer::Fuzz();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000014458 args.GetReturnValue().Set(v8_num(42));
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000014459}
14460
14461
14462THREADED_TEST(CallbackFunctionName) {
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000014463 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000014464 v8::Isolate* isolate = context->GetIsolate();
14465 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000014466 Local<ObjectTemplate> t = ObjectTemplate::New(isolate);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000014467 t->Set(v8_str("asdf"),
14468 v8::FunctionTemplate::New(isolate, FunctionNameCallback));
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000014469 context->Global()->Set(v8_str("obj"), t->NewInstance());
14470 v8::Handle<v8::Value> value = CompileRun("obj.asdf.name");
14471 CHECK(value->IsString());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000014472 v8::String::Utf8Value name(value);
kasperl@chromium.org41044eb2008-10-06 08:24:46 +000014473 CHECK_EQ("asdf", *name);
14474}
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014475
14476
14477THREADED_TEST(DateAccess) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014478 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000014479 v8::HandleScope scope(context->GetIsolate());
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000014480 v8::Handle<v8::Value> date =
14481 v8::Date::New(context->GetIsolate(), 1224744689038.0);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014482 CHECK(date->IsDate());
danno@chromium.orgd3c42102013-08-01 16:58:23 +000014483 CHECK_EQ(1224744689038.0, date.As<v8::Date>()->ValueOf());
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014484}
14485
14486
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014487void CheckProperties(v8::Isolate* isolate,
14488 v8::Handle<v8::Value> val,
14489 int elmc,
14490 const char* elmv[]) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000014491 v8::Handle<v8::Object> obj = val.As<v8::Object>();
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014492 v8::Handle<v8::Array> props = obj->GetPropertyNames();
14493 CHECK_EQ(elmc, props->Length());
14494 for (int i = 0; i < elmc; i++) {
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014495 v8::String::Utf8Value elm(props->Get(v8::Integer::New(isolate, i)));
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014496 CHECK_EQ(elmv[i], *elm);
14497 }
14498}
14499
14500
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014501void CheckOwnProperties(v8::Isolate* isolate,
14502 v8::Handle<v8::Value> val,
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000014503 int elmc,
14504 const char* elmv[]) {
14505 v8::Handle<v8::Object> obj = val.As<v8::Object>();
14506 v8::Handle<v8::Array> props = obj->GetOwnPropertyNames();
14507 CHECK_EQ(elmc, props->Length());
14508 for (int i = 0; i < elmc; i++) {
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014509 v8::String::Utf8Value elm(props->Get(v8::Integer::New(isolate, i)));
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000014510 CHECK_EQ(elmv[i], *elm);
14511 }
14512}
14513
14514
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014515THREADED_TEST(PropertyEnumeration) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014516 LocalContext context;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014517 v8::Isolate* isolate = context->GetIsolate();
14518 v8::HandleScope scope(isolate);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000014519 v8::Handle<v8::Value> obj = v8::Script::Compile(v8::String::NewFromUtf8(
14520 context->GetIsolate(),
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014521 "var result = [];"
14522 "result[0] = {};"
14523 "result[1] = {a: 1, b: 2};"
14524 "result[2] = [1, 2, 3];"
14525 "var proto = {x: 1, y: 2, z: 3};"
14526 "var x = { __proto__: proto, w: 0, z: 1 };"
14527 "result[3] = x;"
14528 "result;"))->Run();
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000014529 v8::Handle<v8::Array> elms = obj.As<v8::Array>();
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014530 CHECK_EQ(4, elms->Length());
14531 int elmc0 = 0;
14532 const char** elmv0 = NULL;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014533 CheckProperties(
14534 isolate, elms->Get(v8::Integer::New(isolate, 0)), elmc0, elmv0);
14535 CheckOwnProperties(
14536 isolate, elms->Get(v8::Integer::New(isolate, 0)), elmc0, elmv0);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014537 int elmc1 = 2;
14538 const char* elmv1[] = {"a", "b"};
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014539 CheckProperties(
14540 isolate, elms->Get(v8::Integer::New(isolate, 1)), elmc1, elmv1);
14541 CheckOwnProperties(
14542 isolate, elms->Get(v8::Integer::New(isolate, 1)), elmc1, elmv1);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014543 int elmc2 = 3;
14544 const char* elmv2[] = {"0", "1", "2"};
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014545 CheckProperties(
14546 isolate, elms->Get(v8::Integer::New(isolate, 2)), elmc2, elmv2);
14547 CheckOwnProperties(
14548 isolate, elms->Get(v8::Integer::New(isolate, 2)), elmc2, elmv2);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014549 int elmc3 = 4;
14550 const char* elmv3[] = {"w", "z", "x", "y"};
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014551 CheckProperties(
14552 isolate, elms->Get(v8::Integer::New(isolate, 3)), elmc3, elmv3);
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000014553 int elmc4 = 2;
14554 const char* elmv4[] = {"w", "z"};
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014555 CheckOwnProperties(
14556 isolate, elms->Get(v8::Integer::New(isolate, 3)), elmc4, elmv4);
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000014557}
ager@chromium.org870a0b62008-11-04 11:43:05 +000014558
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000014559
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000014560THREADED_TEST(PropertyEnumeration2) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000014561 LocalContext context;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014562 v8::Isolate* isolate = context->GetIsolate();
14563 v8::HandleScope scope(isolate);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000014564 v8::Handle<v8::Value> obj = v8::Script::Compile(v8::String::NewFromUtf8(
14565 context->GetIsolate(),
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000014566 "var result = [];"
14567 "result[0] = {};"
14568 "result[1] = {a: 1, b: 2};"
14569 "result[2] = [1, 2, 3];"
14570 "var proto = {x: 1, y: 2, z: 3};"
14571 "var x = { __proto__: proto, w: 0, z: 1 };"
14572 "result[3] = x;"
14573 "result;"))->Run();
14574 v8::Handle<v8::Array> elms = obj.As<v8::Array>();
14575 CHECK_EQ(4, elms->Length());
14576 int elmc0 = 0;
14577 const char** elmv0 = NULL;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014578 CheckProperties(isolate,
14579 elms->Get(v8::Integer::New(isolate, 0)), elmc0, elmv0);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000014580
ulan@chromium.org0f13e742014-01-03 15:51:11 +000014581 v8::Handle<v8::Value> val = elms->Get(v8::Integer::New(isolate, 0));
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000014582 v8::Handle<v8::Array> props = val.As<v8::Object>()->GetPropertyNames();
14583 CHECK_EQ(0, props->Length());
14584 for (uint32_t i = 0; i < props->Length(); i++) {
14585 printf("p[%d]\n", i);
14586 }
14587}
ager@chromium.org870a0b62008-11-04 11:43:05 +000014588
ager@chromium.org870a0b62008-11-04 11:43:05 +000014589static bool NamedSetAccessBlocker(Local<v8::Object> obj,
14590 Local<Value> name,
14591 v8::AccessType type,
14592 Local<Value> data) {
14593 return type != v8::ACCESS_SET;
14594}
14595
14596
14597static bool IndexedSetAccessBlocker(Local<v8::Object> obj,
14598 uint32_t key,
14599 v8::AccessType type,
14600 Local<Value> data) {
14601 return type != v8::ACCESS_SET;
14602}
14603
14604
14605THREADED_TEST(DisableAccessChecksWhileConfiguring) {
ager@chromium.org870a0b62008-11-04 11:43:05 +000014606 LocalContext context;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000014607 v8::Isolate* isolate = context->GetIsolate();
14608 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000014609 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org870a0b62008-11-04 11:43:05 +000014610 templ->SetAccessCheckCallbacks(NamedSetAccessBlocker,
14611 IndexedSetAccessBlocker);
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000014612 templ->Set(v8_str("x"), v8::True(isolate));
ager@chromium.org870a0b62008-11-04 11:43:05 +000014613 Local<v8::Object> instance = templ->NewInstance();
14614 context->Global()->Set(v8_str("obj"), instance);
14615 Local<Value> value = CompileRun("obj.x");
14616 CHECK(value->BooleanValue());
14617}
ager@chromium.orga74f0da2008-12-03 16:05:52 +000014618
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000014619
ager@chromium.org32912102009-01-16 10:38:43 +000014620static bool NamedGetAccessBlocker(Local<v8::Object> obj,
14621 Local<Value> name,
14622 v8::AccessType type,
14623 Local<Value> data) {
14624 return false;
14625}
14626
14627
14628static bool IndexedGetAccessBlocker(Local<v8::Object> obj,
14629 uint32_t key,
14630 v8::AccessType type,
14631 Local<Value> data) {
14632 return false;
14633}
14634
14635
14636
14637THREADED_TEST(AccessChecksReenabledCorrectly) {
ager@chromium.org32912102009-01-16 10:38:43 +000014638 LocalContext context;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000014639 v8::Isolate* isolate = context->GetIsolate();
14640 v8::HandleScope scope(isolate);
14641 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org32912102009-01-16 10:38:43 +000014642 templ->SetAccessCheckCallbacks(NamedGetAccessBlocker,
14643 IndexedGetAccessBlocker);
14644 templ->Set(v8_str("a"), v8_str("a"));
14645 // Add more than 8 (see kMaxFastProperties) properties
14646 // so that the constructor will force copying map.
14647 // Cannot sprintf, gcc complains unsafety.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000014648 char buf[4];
ager@chromium.org32912102009-01-16 10:38:43 +000014649 for (char i = '0'; i <= '9' ; i++) {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000014650 buf[0] = i;
ager@chromium.org32912102009-01-16 10:38:43 +000014651 for (char j = '0'; j <= '9'; j++) {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000014652 buf[1] = j;
ager@chromium.org32912102009-01-16 10:38:43 +000014653 for (char k = '0'; k <= '9'; k++) {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000014654 buf[2] = k;
14655 buf[3] = 0;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000014656 templ->Set(v8_str(buf), v8::Number::New(isolate, k));
ager@chromium.org32912102009-01-16 10:38:43 +000014657 }
14658 }
14659 }
14660
14661 Local<v8::Object> instance_1 = templ->NewInstance();
14662 context->Global()->Set(v8_str("obj_1"), instance_1);
14663
14664 Local<Value> value_1 = CompileRun("obj_1.a");
14665 CHECK(value_1->IsUndefined());
14666
14667 Local<v8::Object> instance_2 = templ->NewInstance();
14668 context->Global()->Set(v8_str("obj_2"), instance_2);
14669
14670 Local<Value> value_2 = CompileRun("obj_2.a");
14671 CHECK(value_2->IsUndefined());
14672}
ager@chromium.orga74f0da2008-12-03 16:05:52 +000014673
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000014674
ager@chromium.org8bb60582008-12-11 12:02:20 +000014675// This tests that access check information remains on the global
14676// object template when creating contexts.
14677THREADED_TEST(AccessControlRepeatedContextCreation) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014678 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000014679 v8::HandleScope handle_scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000014680 v8::Handle<v8::ObjectTemplate> global_template =
14681 v8::ObjectTemplate::New(isolate);
ager@chromium.org8bb60582008-12-11 12:02:20 +000014682 global_template->SetAccessCheckCallbacks(NamedSetAccessBlocker,
14683 IndexedSetAccessBlocker);
14684 i::Handle<i::ObjectTemplateInfo> internal_template =
14685 v8::Utils::OpenHandle(*global_template);
14686 CHECK(!internal_template->constructor()->IsUndefined());
14687 i::Handle<i::FunctionTemplateInfo> constructor(
14688 i::FunctionTemplateInfo::cast(internal_template->constructor()));
14689 CHECK(!constructor->access_check_info()->IsUndefined());
ulan@chromium.org57ff8812013-05-10 08:16:55 +000014690 v8::Local<Context> context0(Context::New(isolate, NULL, global_template));
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000014691 CHECK(!context0.IsEmpty());
ager@chromium.org8bb60582008-12-11 12:02:20 +000014692 CHECK(!constructor->access_check_info()->IsUndefined());
14693}
14694
14695
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000014696THREADED_TEST(TurnOnAccessCheck) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014697 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000014698 v8::HandleScope handle_scope(isolate);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000014699
14700 // Create an environment with access check to the global object disabled by
14701 // default.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000014702 v8::Handle<v8::ObjectTemplate> global_template =
14703 v8::ObjectTemplate::New(isolate);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000014704 global_template->SetAccessCheckCallbacks(NamedGetAccessBlocker,
14705 IndexedGetAccessBlocker,
14706 v8::Handle<v8::Value>(),
14707 false);
ulan@chromium.org57ff8812013-05-10 08:16:55 +000014708 v8::Local<Context> context = Context::New(isolate, NULL, global_template);
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000014709 Context::Scope context_scope(context);
14710
14711 // Set up a property and a number of functions.
14712 context->Global()->Set(v8_str("a"), v8_num(1));
14713 CompileRun("function f1() {return a;}"
14714 "function f2() {return a;}"
14715 "function g1() {return h();}"
14716 "function g2() {return h();}"
14717 "function h() {return 1;}");
14718 Local<Function> f1 =
14719 Local<Function>::Cast(context->Global()->Get(v8_str("f1")));
14720 Local<Function> f2 =
14721 Local<Function>::Cast(context->Global()->Get(v8_str("f2")));
14722 Local<Function> g1 =
14723 Local<Function>::Cast(context->Global()->Get(v8_str("g1")));
14724 Local<Function> g2 =
14725 Local<Function>::Cast(context->Global()->Get(v8_str("g2")));
14726 Local<Function> h =
14727 Local<Function>::Cast(context->Global()->Get(v8_str("h")));
14728
14729 // Get the global object.
14730 v8::Handle<v8::Object> global = context->Global();
14731
14732 // Call f1 one time and f2 a number of times. This will ensure that f1 still
14733 // uses the runtime system to retreive property a whereas f2 uses global load
14734 // inline cache.
14735 CHECK(f1->Call(global, 0, NULL)->Equals(v8_num(1)));
14736 for (int i = 0; i < 4; i++) {
14737 CHECK(f2->Call(global, 0, NULL)->Equals(v8_num(1)));
14738 }
14739
14740 // Same for g1 and g2.
14741 CHECK(g1->Call(global, 0, NULL)->Equals(v8_num(1)));
14742 for (int i = 0; i < 4; i++) {
14743 CHECK(g2->Call(global, 0, NULL)->Equals(v8_num(1)));
14744 }
14745
14746 // Detach the global and turn on access check.
jkummerow@chromium.org113035e2013-12-13 15:13:40 +000014747 Local<Object> hidden_global = Local<Object>::Cast(
14748 context->Global()->GetPrototype());
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000014749 context->DetachGlobal();
jkummerow@chromium.org113035e2013-12-13 15:13:40 +000014750 hidden_global->TurnOnAccessCheck();
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000014751
14752 // Failing access check to property get results in undefined.
14753 CHECK(f1->Call(global, 0, NULL)->IsUndefined());
14754 CHECK(f2->Call(global, 0, NULL)->IsUndefined());
14755
14756 // Failing access check to function call results in exception.
14757 CHECK(g1->Call(global, 0, NULL).IsEmpty());
14758 CHECK(g2->Call(global, 0, NULL).IsEmpty());
14759
14760 // No failing access check when just returning a constant.
14761 CHECK(h->Call(global, 0, NULL)->Equals(v8_num(1)));
14762}
14763
14764
jkummerow@chromium.orgf7a58842012-02-21 10:08:21 +000014765static const char* kPropertyA = "a";
14766static const char* kPropertyH = "h";
kasperl@chromium.orga5551262010-12-07 12:49:48 +000014767
14768static bool NamedGetAccessBlockAandH(Local<v8::Object> obj,
14769 Local<Value> name,
14770 v8::AccessType type,
14771 Local<Value> data) {
jkummerow@chromium.orgf7a58842012-02-21 10:08:21 +000014772 if (!name->IsString()) return false;
14773 i::Handle<i::String> name_handle =
14774 v8::Utils::OpenHandle(String::Cast(*name));
jkummerow@chromium.org59297c72013-01-09 16:32:23 +000014775 return !name_handle->IsUtf8EqualTo(i::CStrVector(kPropertyA))
14776 && !name_handle->IsUtf8EqualTo(i::CStrVector(kPropertyH));
kasperl@chromium.orga5551262010-12-07 12:49:48 +000014777}
14778
14779
jkummerow@chromium.orgf7a58842012-02-21 10:08:21 +000014780THREADED_TEST(TurnOnAccessCheckAndRecompile) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000014781 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000014782 v8::HandleScope handle_scope(isolate);
kasperl@chromium.orga5551262010-12-07 12:49:48 +000014783
14784 // Create an environment with access check to the global object disabled by
14785 // default. When the registered access checker will block access to properties
jkummerow@chromium.orgf7a58842012-02-21 10:08:21 +000014786 // a and h.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000014787 v8::Handle<v8::ObjectTemplate> global_template =
14788 v8::ObjectTemplate::New(isolate);
kasperl@chromium.orga5551262010-12-07 12:49:48 +000014789 global_template->SetAccessCheckCallbacks(NamedGetAccessBlockAandH,
14790 IndexedGetAccessBlocker,
14791 v8::Handle<v8::Value>(),
14792 false);
ulan@chromium.org57ff8812013-05-10 08:16:55 +000014793 v8::Local<Context> context = Context::New(isolate, NULL, global_template);
kasperl@chromium.orga5551262010-12-07 12:49:48 +000014794 Context::Scope context_scope(context);
14795
14796 // Set up a property and a number of functions.
14797 context->Global()->Set(v8_str("a"), v8_num(1));
14798 static const char* source = "function f1() {return a;}"
14799 "function f2() {return a;}"
14800 "function g1() {return h();}"
14801 "function g2() {return h();}"
14802 "function h() {return 1;}";
14803
14804 CompileRun(source);
14805 Local<Function> f1;
14806 Local<Function> f2;
14807 Local<Function> g1;
14808 Local<Function> g2;
14809 Local<Function> h;
14810 f1 = Local<Function>::Cast(context->Global()->Get(v8_str("f1")));
14811 f2 = Local<Function>::Cast(context->Global()->Get(v8_str("f2")));
14812 g1 = Local<Function>::Cast(context->Global()->Get(v8_str("g1")));
14813 g2 = Local<Function>::Cast(context->Global()->Get(v8_str("g2")));
14814 h = Local<Function>::Cast(context->Global()->Get(v8_str("h")));
14815
14816 // Get the global object.
14817 v8::Handle<v8::Object> global = context->Global();
14818
14819 // Call f1 one time and f2 a number of times. This will ensure that f1 still
14820 // uses the runtime system to retreive property a whereas f2 uses global load
14821 // inline cache.
14822 CHECK(f1->Call(global, 0, NULL)->Equals(v8_num(1)));
14823 for (int i = 0; i < 4; i++) {
14824 CHECK(f2->Call(global, 0, NULL)->Equals(v8_num(1)));
14825 }
14826
14827 // Same for g1 and g2.
14828 CHECK(g1->Call(global, 0, NULL)->Equals(v8_num(1)));
14829 for (int i = 0; i < 4; i++) {
14830 CHECK(g2->Call(global, 0, NULL)->Equals(v8_num(1)));
14831 }
14832
14833 // Detach the global and turn on access check now blocking access to property
14834 // a and function h.
jkummerow@chromium.org113035e2013-12-13 15:13:40 +000014835 Local<Object> hidden_global = Local<Object>::Cast(
14836 context->Global()->GetPrototype());
kasperl@chromium.orga5551262010-12-07 12:49:48 +000014837 context->DetachGlobal();
jkummerow@chromium.org113035e2013-12-13 15:13:40 +000014838 hidden_global->TurnOnAccessCheck();
kasperl@chromium.orga5551262010-12-07 12:49:48 +000014839
14840 // Failing access check to property get results in undefined.
14841 CHECK(f1->Call(global, 0, NULL)->IsUndefined());
14842 CHECK(f2->Call(global, 0, NULL)->IsUndefined());
14843
14844 // Failing access check to function call results in exception.
14845 CHECK(g1->Call(global, 0, NULL).IsEmpty());
14846 CHECK(g2->Call(global, 0, NULL).IsEmpty());
14847
14848 // No failing access check when just returning a constant.
14849 CHECK(h->Call(global, 0, NULL)->Equals(v8_num(1)));
14850
14851 // Now compile the source again. And get the newly compiled functions, except
14852 // for h for which access is blocked.
14853 CompileRun(source);
jkummerow@chromium.org113035e2013-12-13 15:13:40 +000014854 f1 = Local<Function>::Cast(hidden_global->Get(v8_str("f1")));
14855 f2 = Local<Function>::Cast(hidden_global->Get(v8_str("f2")));
14856 g1 = Local<Function>::Cast(hidden_global->Get(v8_str("g1")));
14857 g2 = Local<Function>::Cast(hidden_global->Get(v8_str("g2")));
14858 CHECK(hidden_global->Get(v8_str("h"))->IsUndefined());
kasperl@chromium.orga5551262010-12-07 12:49:48 +000014859
14860 // Failing access check to property get results in undefined.
14861 CHECK(f1->Call(global, 0, NULL)->IsUndefined());
14862 CHECK(f2->Call(global, 0, NULL)->IsUndefined());
14863
14864 // Failing access check to function call results in exception.
14865 CHECK(g1->Call(global, 0, NULL).IsEmpty());
14866 CHECK(g2->Call(global, 0, NULL).IsEmpty());
14867}
14868
14869
ager@chromium.orga74f0da2008-12-03 16:05:52 +000014870// This test verifies that pre-compilation (aka preparsing) can be called
14871// without initializing the whole VM. Thus we cannot run this test in a
14872// multi-threaded setup.
14873TEST(PreCompile) {
14874 // TODO(155): This test would break without the initialization of V8. This is
14875 // a workaround for now to make this test not fail.
14876 v8::V8::Initialize();
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +000014877 v8::Isolate* isolate = CcTest::isolate();
machenbach@chromium.org4ddd2f12014-01-14 08:13:44 +000014878 HandleScope handle_scope(isolate);
kmillikin@chromium.org9155e252010-05-26 13:27:57 +000014879 const char* script = "function foo(a) { return a+1; }";
machenbach@chromium.org4ddd2f12014-01-14 08:13:44 +000014880 v8::ScriptData* sd = v8::ScriptData::PreCompile(v8::String::NewFromUtf8(
14881 isolate, script, v8::String::kNormalString, i::StrLength(script)));
ager@chromium.orga74f0da2008-12-03 16:05:52 +000014882 CHECK_NE(sd->Length(), 0);
14883 CHECK_NE(sd->Data(), NULL);
fschneider@chromium.org0c20e672010-01-14 15:28:53 +000014884 CHECK(!sd->HasError());
14885 delete sd;
14886}
14887
14888
14889TEST(PreCompileWithError) {
14890 v8::V8::Initialize();
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +000014891 v8::Isolate* isolate = CcTest::isolate();
machenbach@chromium.org4ddd2f12014-01-14 08:13:44 +000014892 HandleScope handle_scope(isolate);
kmillikin@chromium.org9155e252010-05-26 13:27:57 +000014893 const char* script = "function foo(a) { return 1 * * 2; }";
machenbach@chromium.org4ddd2f12014-01-14 08:13:44 +000014894 v8::ScriptData* sd = v8::ScriptData::PreCompile(v8::String::NewFromUtf8(
14895 isolate, script, v8::String::kNormalString, i::StrLength(script)));
fschneider@chromium.org0c20e672010-01-14 15:28:53 +000014896 CHECK(sd->HasError());
14897 delete sd;
14898}
14899
14900
14901TEST(Regress31661) {
14902 v8::V8::Initialize();
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +000014903 v8::Isolate* isolate = CcTest::isolate();
machenbach@chromium.org4ddd2f12014-01-14 08:13:44 +000014904 HandleScope handle_scope(isolate);
kmillikin@chromium.org9155e252010-05-26 13:27:57 +000014905 const char* script = " The Definintive Guide";
machenbach@chromium.org4ddd2f12014-01-14 08:13:44 +000014906 v8::ScriptData* sd = v8::ScriptData::PreCompile(v8::String::NewFromUtf8(
14907 isolate, script, v8::String::kNormalString, i::StrLength(script)));
fschneider@chromium.org0c20e672010-01-14 15:28:53 +000014908 CHECK(sd->HasError());
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000014909 delete sd;
ager@chromium.orga74f0da2008-12-03 16:05:52 +000014910}
14911
14912
kmillikin@chromium.org9155e252010-05-26 13:27:57 +000014913// Tests that ScriptData can be serialized and deserialized.
14914TEST(PreCompileSerialization) {
14915 v8::V8::Initialize();
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +000014916 v8::Isolate* isolate = CcTest::isolate();
machenbach@chromium.org4ddd2f12014-01-14 08:13:44 +000014917 HandleScope handle_scope(isolate);
kmillikin@chromium.org9155e252010-05-26 13:27:57 +000014918 const char* script = "function foo(a) { return a+1; }";
machenbach@chromium.org4ddd2f12014-01-14 08:13:44 +000014919 v8::ScriptData* sd = v8::ScriptData::PreCompile(v8::String::NewFromUtf8(
14920 isolate, script, v8::String::kNormalString, i::StrLength(script)));
kmillikin@chromium.org9155e252010-05-26 13:27:57 +000014921
14922 // Serialize.
14923 int serialized_data_length = sd->Length();
14924 char* serialized_data = i::NewArray<char>(serialized_data_length);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +000014925 i::OS::MemCopy(serialized_data, sd->Data(), serialized_data_length);
kmillikin@chromium.org9155e252010-05-26 13:27:57 +000014926
14927 // Deserialize.
14928 v8::ScriptData* deserialized_sd =
14929 v8::ScriptData::New(serialized_data, serialized_data_length);
14930
14931 // Verify that the original is the same as the deserialized.
14932 CHECK_EQ(sd->Length(), deserialized_sd->Length());
14933 CHECK_EQ(0, memcmp(sd->Data(), deserialized_sd->Data(), sd->Length()));
14934 CHECK_EQ(sd->HasError(), deserialized_sd->HasError());
14935
14936 delete sd;
14937 delete deserialized_sd;
14938}
14939
14940
14941// Attempts to deserialize bad data.
14942TEST(PreCompileDeserializationError) {
14943 v8::V8::Initialize();
14944 const char* data = "DONT CARE";
14945 int invalid_size = 3;
14946 v8::ScriptData* sd = v8::ScriptData::New(data, invalid_size);
14947
14948 CHECK_EQ(0, sd->Length());
14949
14950 delete sd;
14951}
14952
14953
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014954// Attempts to deserialize bad data.
14955TEST(PreCompileInvalidPreparseDataError) {
14956 v8::V8::Initialize();
jkummerow@chromium.orgfb7a7c42013-10-02 11:41:02 +000014957 v8::Isolate* isolate = CcTest::isolate();
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014958 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000014959 v8::HandleScope scope(context->GetIsolate());
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014960
14961 const char* script = "function foo(){ return 5;}\n"
14962 "function bar(){ return 6 + 7;} foo();";
machenbach@chromium.org4ddd2f12014-01-14 08:13:44 +000014963 v8::ScriptData* sd = v8::ScriptData::PreCompile(v8::String::NewFromUtf8(
14964 isolate, script, v8::String::kNormalString, i::StrLength(script)));
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014965 CHECK(!sd->HasError());
14966 // ScriptDataImpl private implementation details
ager@chromium.orgbeb25712010-11-29 08:02:25 +000014967 const int kHeaderSize = i::PreparseDataConstants::kHeaderSize;
ager@chromium.org5b2fbee2010-09-08 06:38:15 +000014968 const int kFunctionEntrySize = i::FunctionEntry::kSize;
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014969 const int kFunctionEntryStartOffset = 0;
14970 const int kFunctionEntryEndOffset = 1;
14971 unsigned* sd_data =
14972 reinterpret_cast<unsigned*>(const_cast<char*>(sd->Data()));
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014973
14974 // Overwrite function bar's end position with 0.
14975 sd_data[kHeaderSize + 1 * kFunctionEntrySize + kFunctionEntryEndOffset] = 0;
14976 v8::TryCatch try_catch;
14977
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000014978 Local<String> source = String::NewFromUtf8(isolate, script);
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014979 Local<Script> compiled_script = Script::New(source, NULL, sd);
14980 CHECK(try_catch.HasCaught());
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000014981 String::Utf8Value exception_value(try_catch.Message()->Get());
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014982 CHECK_EQ("Uncaught SyntaxError: Invalid preparser data for function bar",
14983 *exception_value);
14984
14985 try_catch.Reset();
lrn@chromium.orgd4e9e222011-08-03 12:01:58 +000014986
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014987 // Overwrite function bar's start position with 200. The function entry
lrn@chromium.orgd4e9e222011-08-03 12:01:58 +000014988 // will not be found when searching for it by position and we should fall
14989 // back on eager compilation.
machenbach@chromium.org4ddd2f12014-01-14 08:13:44 +000014990 sd = v8::ScriptData::PreCompile(v8::String::NewFromUtf8(
14991 isolate, script, v8::String::kNormalString, i::StrLength(script)));
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +000014992 sd_data = reinterpret_cast<unsigned*>(const_cast<char*>(sd->Data()));
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014993 sd_data[kHeaderSize + 1 * kFunctionEntrySize + kFunctionEntryStartOffset] =
14994 200;
14995 compiled_script = Script::New(source, NULL, sd);
lrn@chromium.orgd4e9e222011-08-03 12:01:58 +000014996 CHECK(!try_catch.HasCaught());
erik.corry@gmail.com4a2e25e2010-07-07 12:22:46 +000014997
14998 delete sd;
14999}
15000
15001
ager@chromium.orga74f0da2008-12-03 16:05:52 +000015002// This tests that we do not allow dictionary load/call inline caches
15003// to use functions that have not yet been compiled. The potential
15004// problem of loading a function that has not yet been compiled can
15005// arise because we share code between contexts via the compilation
15006// cache.
15007THREADED_TEST(DictionaryICLoadedFunction) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015008 v8::HandleScope scope(CcTest::isolate());
ager@chromium.orga74f0da2008-12-03 16:05:52 +000015009 // Test LoadIC.
15010 for (int i = 0; i < 2; i++) {
15011 LocalContext context;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000015012 context->Global()->Set(v8_str("tmp"), v8::True(CcTest::isolate()));
ager@chromium.orga74f0da2008-12-03 16:05:52 +000015013 context->Global()->Delete(v8_str("tmp"));
15014 CompileRun("for (var j = 0; j < 10; j++) new RegExp('');");
15015 }
15016 // Test CallIC.
15017 for (int i = 0; i < 2; i++) {
15018 LocalContext context;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000015019 context->Global()->Set(v8_str("tmp"), v8::True(CcTest::isolate()));
ager@chromium.orga74f0da2008-12-03 16:05:52 +000015020 context->Global()->Delete(v8_str("tmp"));
15021 CompileRun("for (var j = 0; j < 10; j++) RegExp('')");
15022 }
15023}
ager@chromium.orgddb913d2009-01-27 10:01:48 +000015024
15025
15026// Test that cross-context new calls use the context of the callee to
15027// create the new JavaScript object.
15028THREADED_TEST(CrossContextNew) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015029 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000015030 v8::HandleScope scope(isolate);
15031 v8::Local<Context> context0 = Context::New(isolate);
15032 v8::Local<Context> context1 = Context::New(isolate);
ager@chromium.orgddb913d2009-01-27 10:01:48 +000015033
15034 // Allow cross-domain access.
15035 Local<String> token = v8_str("<security token>");
15036 context0->SetSecurityToken(token);
15037 context1->SetSecurityToken(token);
15038
15039 // Set an 'x' property on the Object prototype and define a
15040 // constructor function in context0.
15041 context0->Enter();
15042 CompileRun("Object.prototype.x = 42; function C() {};");
15043 context0->Exit();
15044
15045 // Call the constructor function from context0 and check that the
15046 // result has the 'x' property.
15047 context1->Enter();
15048 context1->Global()->Set(v8_str("other"), context0->Global());
15049 Local<Value> value = CompileRun("var instance = new other.C(); instance.x");
15050 CHECK(value->IsInt32());
15051 CHECK_EQ(42, value->Int32Value());
15052 context1->Exit();
ager@chromium.orgddb913d2009-01-27 10:01:48 +000015053}
ager@chromium.org381abbb2009-02-25 13:23:22 +000015054
15055
ager@chromium.org3b45ab52009-03-19 22:21:34 +000015056// Verify that we can clone an object
15057TEST(ObjectClone) {
ager@chromium.org3b45ab52009-03-19 22:21:34 +000015058 LocalContext env;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015059 v8::Isolate* isolate = env->GetIsolate();
15060 v8::HandleScope scope(isolate);
ager@chromium.org3b45ab52009-03-19 22:21:34 +000015061
15062 const char* sample =
15063 "var rv = {};" \
15064 "rv.alpha = 'hello';" \
15065 "rv.beta = 123;" \
15066 "rv;";
15067
15068 // Create an object, verify basics.
15069 Local<Value> val = CompileRun(sample);
15070 CHECK(val->IsObject());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000015071 Local<v8::Object> obj = val.As<v8::Object>();
ager@chromium.org3b45ab52009-03-19 22:21:34 +000015072 obj->Set(v8_str("gamma"), v8_str("cloneme"));
15073
15074 CHECK_EQ(v8_str("hello"), obj->Get(v8_str("alpha")));
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015075 CHECK_EQ(v8::Integer::New(isolate, 123), obj->Get(v8_str("beta")));
ager@chromium.org3b45ab52009-03-19 22:21:34 +000015076 CHECK_EQ(v8_str("cloneme"), obj->Get(v8_str("gamma")));
15077
15078 // Clone it.
15079 Local<v8::Object> clone = obj->Clone();
15080 CHECK_EQ(v8_str("hello"), clone->Get(v8_str("alpha")));
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015081 CHECK_EQ(v8::Integer::New(isolate, 123), clone->Get(v8_str("beta")));
ager@chromium.org3b45ab52009-03-19 22:21:34 +000015082 CHECK_EQ(v8_str("cloneme"), clone->Get(v8_str("gamma")));
15083
15084 // Set a property on the clone, verify each object.
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015085 clone->Set(v8_str("beta"), v8::Integer::New(isolate, 456));
15086 CHECK_EQ(v8::Integer::New(isolate, 123), obj->Get(v8_str("beta")));
15087 CHECK_EQ(v8::Integer::New(isolate, 456), clone->Get(v8_str("beta")));
ager@chromium.org3b45ab52009-03-19 22:21:34 +000015088}
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015089
15090
ager@chromium.org5ec48922009-05-05 07:25:34 +000015091class AsciiVectorResource : public v8::String::ExternalAsciiStringResource {
15092 public:
15093 explicit AsciiVectorResource(i::Vector<const char> vector)
15094 : data_(vector) {}
15095 virtual ~AsciiVectorResource() {}
15096 virtual size_t length() const { return data_.length(); }
15097 virtual const char* data() const { return data_.start(); }
15098 private:
15099 i::Vector<const char> data_;
15100};
15101
15102
15103class UC16VectorResource : public v8::String::ExternalStringResource {
15104 public:
15105 explicit UC16VectorResource(i::Vector<const i::uc16> vector)
15106 : data_(vector) {}
15107 virtual ~UC16VectorResource() {}
15108 virtual size_t length() const { return data_.length(); }
15109 virtual const i::uc16* data() const { return data_.start(); }
15110 private:
15111 i::Vector<const i::uc16> data_;
15112};
15113
15114
15115static void MorphAString(i::String* string,
15116 AsciiVectorResource* ascii_resource,
15117 UC16VectorResource* uc16_resource) {
15118 CHECK(i::StringShape(string).IsExternal());
ulan@chromium.org8e8d8822012-11-23 14:36:46 +000015119 if (string->IsOneByteRepresentation()) {
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +000015120 // Check old map is not internalized or long.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015121 CHECK(string->map() == CcTest::heap()->external_ascii_string_map());
ager@chromium.org5ec48922009-05-05 07:25:34 +000015122 // Morph external string to be TwoByte string.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015123 string->set_map(CcTest::heap()->external_string_map());
ager@chromium.org5ec48922009-05-05 07:25:34 +000015124 i::ExternalTwoByteString* morphed =
15125 i::ExternalTwoByteString::cast(string);
15126 morphed->set_resource(uc16_resource);
15127 } else {
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +000015128 // Check old map is not internalized or long.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015129 CHECK(string->map() == CcTest::heap()->external_string_map());
ager@chromium.org5ec48922009-05-05 07:25:34 +000015130 // Morph external string to be ASCII string.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015131 string->set_map(CcTest::heap()->external_ascii_string_map());
ager@chromium.org5ec48922009-05-05 07:25:34 +000015132 i::ExternalAsciiString* morphed =
15133 i::ExternalAsciiString::cast(string);
15134 morphed->set_resource(ascii_resource);
15135 }
15136}
15137
15138
15139// Test that we can still flatten a string if the components it is built up
15140// from have been turned into 16 bit strings in the mean time.
15141THREADED_TEST(MorphCompositeStringTest) {
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +000015142 char utf_buffer[129];
ager@chromium.org5ec48922009-05-05 07:25:34 +000015143 const char* c_string = "Now is the time for all good men"
15144 " to come to the aid of the party";
15145 uint16_t* two_byte_string = AsciiToTwoByteString(c_string);
15146 {
ager@chromium.org5ec48922009-05-05 07:25:34 +000015147 LocalContext env;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015148 i::Factory* factory = CcTest::i_isolate()->factory();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015149 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org5ec48922009-05-05 07:25:34 +000015150 AsciiVectorResource ascii_resource(
ager@chromium.orgc4c92722009-11-18 14:12:51 +000015151 i::Vector<const char>(c_string, i::StrLength(c_string)));
ager@chromium.org5ec48922009-05-05 07:25:34 +000015152 UC16VectorResource uc16_resource(
ager@chromium.orgc4c92722009-11-18 14:12:51 +000015153 i::Vector<const uint16_t>(two_byte_string,
15154 i::StrLength(c_string)));
ager@chromium.org5ec48922009-05-05 07:25:34 +000015155
15156 Local<String> lhs(v8::Utils::ToLocal(
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000015157 factory->NewExternalStringFromAscii(&ascii_resource)));
ager@chromium.org5ec48922009-05-05 07:25:34 +000015158 Local<String> rhs(v8::Utils::ToLocal(
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000015159 factory->NewExternalStringFromAscii(&ascii_resource)));
ager@chromium.org5ec48922009-05-05 07:25:34 +000015160
15161 env->Global()->Set(v8_str("lhs"), lhs);
15162 env->Global()->Set(v8_str("rhs"), rhs);
15163
15164 CompileRun(
15165 "var cons = lhs + rhs;"
15166 "var slice = lhs.substring(1, lhs.length - 1);"
15167 "var slice_on_cons = (lhs + rhs).substring(1, lhs.length *2 - 1);");
15168
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015169 CHECK(lhs->IsOneByte());
15170 CHECK(rhs->IsOneByte());
rossberg@chromium.org2c067b12012-03-19 11:01:52 +000015171
ager@chromium.org5ec48922009-05-05 07:25:34 +000015172 MorphAString(*v8::Utils::OpenHandle(*lhs), &ascii_resource, &uc16_resource);
15173 MorphAString(*v8::Utils::OpenHandle(*rhs), &ascii_resource, &uc16_resource);
15174
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +000015175 // This should UTF-8 without flattening, since everything is ASCII.
15176 Handle<String> cons = v8_compile("cons")->Run().As<String>();
15177 CHECK_EQ(128, cons->Utf8Length());
15178 int nchars = -1;
15179 CHECK_EQ(129, cons->WriteUtf8(utf_buffer, -1, &nchars));
15180 CHECK_EQ(128, nchars);
15181 CHECK_EQ(0, strcmp(
15182 utf_buffer,
15183 "Now is the time for all good men to come to the aid of the party"
15184 "Now is the time for all good men to come to the aid of the party"));
15185
ager@chromium.org5ec48922009-05-05 07:25:34 +000015186 // Now do some stuff to make sure the strings are flattened, etc.
15187 CompileRun(
15188 "/[^a-z]/.test(cons);"
15189 "/[^a-z]/.test(slice);"
15190 "/[^a-z]/.test(slice_on_cons);");
15191 const char* expected_cons =
15192 "Now is the time for all good men to come to the aid of the party"
15193 "Now is the time for all good men to come to the aid of the party";
15194 const char* expected_slice =
15195 "ow is the time for all good men to come to the aid of the part";
15196 const char* expected_slice_on_cons =
15197 "ow is the time for all good men to come to the aid of the party"
15198 "Now is the time for all good men to come to the aid of the part";
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015199 CHECK_EQ(String::NewFromUtf8(env->GetIsolate(), expected_cons),
ager@chromium.org5ec48922009-05-05 07:25:34 +000015200 env->Global()->Get(v8_str("cons")));
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015201 CHECK_EQ(String::NewFromUtf8(env->GetIsolate(), expected_slice),
ager@chromium.org5ec48922009-05-05 07:25:34 +000015202 env->Global()->Get(v8_str("slice")));
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015203 CHECK_EQ(String::NewFromUtf8(env->GetIsolate(), expected_slice_on_cons),
ager@chromium.org5ec48922009-05-05 07:25:34 +000015204 env->Global()->Get(v8_str("slice_on_cons")));
15205 }
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000015206 i::DeleteArray(two_byte_string);
ager@chromium.org5ec48922009-05-05 07:25:34 +000015207}
15208
15209
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000015210TEST(CompileExternalTwoByteSource) {
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000015211 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015212 v8::HandleScope scope(context->GetIsolate());
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000015213
15214 // This is a very short list of sources, which currently is to check for a
15215 // regression caused by r2703.
15216 const char* ascii_sources[] = {
15217 "0.5",
15218 "-0.5", // This mainly testes PushBack in the Scanner.
15219 "--0.5", // This mainly testes PushBack in the Scanner.
15220 NULL
15221 };
15222
15223 // Compile the sources as external two byte strings.
15224 for (int i = 0; ascii_sources[i] != NULL; i++) {
15225 uint16_t* two_byte_string = AsciiToTwoByteString(ascii_sources[i]);
machenbach@chromium.org57a54ac2014-01-31 14:01:53 +000015226 TestResource* uc16_resource = new TestResource(two_byte_string);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000015227 v8::Local<v8::String> source =
machenbach@chromium.org57a54ac2014-01-31 14:01:53 +000015228 v8::String::NewExternal(context->GetIsolate(), uc16_resource);
sgjesse@chromium.orgc81c8942009-08-21 10:54:26 +000015229 v8::Script::Compile(source);
15230 }
15231}
15232
15233
mstarzinger@chromium.orgb4968be2013-10-16 09:00:56 +000015234#ifndef V8_INTERPRETED_REGEXP
15235
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +000015236struct RegExpInterruptionData {
15237 int loop_count;
15238 UC16VectorResource* string_resource;
15239 v8::Persistent<v8::String> string;
15240} regexp_interruption_data;
15241
15242
15243class RegExpInterruptionThread : public i::Thread {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015244 public:
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +000015245 explicit RegExpInterruptionThread(v8::Isolate* isolate)
15246 : Thread("TimeoutThread"), isolate_(isolate) {}
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000015247
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +000015248 virtual void Run() {
15249 for (regexp_interruption_data.loop_count = 0;
15250 regexp_interruption_data.loop_count < 7;
15251 regexp_interruption_data.loop_count++) {
15252 i::OS::Sleep(50); // Wait a bit before requesting GC.
15253 reinterpret_cast<i::Isolate*>(isolate_)->stack_guard()->RequestGC();
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015254 }
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +000015255 i::OS::Sleep(50); // Wait a bit before terminating.
15256 v8::V8::TerminateExecution(isolate_);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015257 }
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015258
jkummerow@chromium.orge297f592011-06-08 10:05:15 +000015259 private:
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +000015260 v8::Isolate* isolate_;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015261};
15262
15263
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +000015264void RunBeforeGC(v8::GCType type, v8::GCCallbackFlags flags) {
15265 if (regexp_interruption_data.loop_count != 2) return;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015266 v8::HandleScope scope(CcTest::isolate());
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +000015267 v8::Local<v8::String> string = v8::Local<v8::String>::New(
15268 CcTest::isolate(), regexp_interruption_data.string);
15269 string->MakeExternal(regexp_interruption_data.string_resource);
15270}
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015271
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015272
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +000015273// Test that RegExp execution can be interrupted. Specifically, we test
15274// * interrupting with GC
15275// * turn the subject string from one-byte internal to two-byte external string
15276// * force termination
15277TEST(RegExpInterruption) {
15278 v8::HandleScope scope(CcTest::isolate());
15279 LocalContext env;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015280
mstarzinger@chromium.orga2e1a402013-10-15 08:25:05 +000015281 RegExpInterruptionThread timeout_thread(CcTest::isolate());
15282
15283 v8::V8::AddGCPrologueCallback(RunBeforeGC);
15284 static const char* ascii_content = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
15285 i::uc16* uc16_content = AsciiToTwoByteString(ascii_content);
15286 v8::Local<v8::String> string = v8_str(ascii_content);
15287
15288 CcTest::global()->Set(v8_str("a"), string);
15289 regexp_interruption_data.string.Reset(CcTest::isolate(), string);
15290 regexp_interruption_data.string_resource = new UC16VectorResource(
15291 i::Vector<const i::uc16>(uc16_content, i::StrLength(ascii_content)));
15292
15293 v8::TryCatch try_catch;
15294 timeout_thread.Start();
15295
15296 CompileRun("/((a*)*)*b/.exec(a)");
15297 CHECK(try_catch.HasTerminated());
15298
15299 timeout_thread.Join();
15300
15301 delete regexp_interruption_data.string_resource;
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015302 regexp_interruption_data.string.Reset();
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015303}
15304
mstarzinger@chromium.orgb4968be2013-10-16 09:00:56 +000015305#endif // V8_INTERPRETED_REGEXP
15306
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015307
mmassi@chromium.org7028c052012-06-13 11:51:58 +000015308// Test that we cannot set a property on the global object if there
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015309// is a read-only property in the prototype chain.
15310TEST(ReadOnlyPropertyInGlobalProto) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +000015311 i::FLAG_es5_readonly = true;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015312 v8::Isolate* isolate = CcTest::isolate();
15313 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000015314 v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015315 LocalContext context(0, templ);
15316 v8::Handle<v8::Object> global = context->Global();
15317 v8::Handle<v8::Object> global_proto =
15318 v8::Handle<v8::Object>::Cast(global->Get(v8_str("__proto__")));
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015319 global_proto->Set(v8_str("x"), v8::Integer::New(isolate, 0), v8::ReadOnly);
15320 global_proto->Set(v8_str("y"), v8::Integer::New(isolate, 0), v8::ReadOnly);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015321 // Check without 'eval' or 'with'.
15322 v8::Handle<v8::Value> res =
15323 CompileRun("function f() { x = 42; return x; }; f()");
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015324 CHECK_EQ(v8::Integer::New(isolate, 0), res);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015325 // Check with 'eval'.
mmassi@chromium.org7028c052012-06-13 11:51:58 +000015326 res = CompileRun("function f() { eval('1'); y = 43; return y; }; f()");
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015327 CHECK_EQ(v8::Integer::New(isolate, 0), res);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015328 // Check with 'with'.
mmassi@chromium.org7028c052012-06-13 11:51:58 +000015329 res = CompileRun("function f() { with (this) { y = 44 }; return y; }; f()");
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015330 CHECK_EQ(v8::Integer::New(isolate, 0), res);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000015331}
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015332
15333static int force_set_set_count = 0;
15334static int force_set_get_count = 0;
15335bool pass_on_get = false;
15336
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015337static void ForceSetGetter(v8::Local<v8::String> name,
15338 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015339 force_set_get_count++;
15340 if (pass_on_get) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015341 return;
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015342 }
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015343 info.GetReturnValue().Set(3);
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015344}
15345
15346static void ForceSetSetter(v8::Local<v8::String> name,
15347 v8::Local<v8::Value> value,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015348 const v8::PropertyCallbackInfo<void>& info) {
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015349 force_set_set_count++;
15350}
15351
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015352static void ForceSetInterceptSetter(
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015353 v8::Local<v8::String> name,
15354 v8::Local<v8::Value> value,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015355 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015356 force_set_set_count++;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015357 info.GetReturnValue().SetUndefined();
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015358}
15359
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000015360
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015361TEST(ForceSet) {
15362 force_set_get_count = 0;
15363 force_set_set_count = 0;
15364 pass_on_get = false;
15365
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015366 v8::Isolate* isolate = CcTest::isolate();
15367 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000015368 v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015369 v8::Handle<v8::String> access_property =
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015370 v8::String::NewFromUtf8(isolate, "a");
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015371 templ->SetAccessor(access_property, ForceSetGetter, ForceSetSetter);
15372 LocalContext context(NULL, templ);
15373 v8::Handle<v8::Object> global = context->Global();
15374
15375 // Ordinary properties
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015376 v8::Handle<v8::String> simple_property =
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015377 v8::String::NewFromUtf8(isolate, "p");
15378 global->Set(simple_property, v8::Int32::New(isolate, 4), v8::ReadOnly);
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015379 CHECK_EQ(4, global->Get(simple_property)->Int32Value());
15380 // This should fail because the property is read-only
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015381 global->Set(simple_property, v8::Int32::New(isolate, 5));
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015382 CHECK_EQ(4, global->Get(simple_property)->Int32Value());
15383 // This should succeed even though the property is read-only
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015384 global->ForceSet(simple_property, v8::Int32::New(isolate, 6));
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015385 CHECK_EQ(6, global->Get(simple_property)->Int32Value());
15386
15387 // Accessors
15388 CHECK_EQ(0, force_set_set_count);
15389 CHECK_EQ(0, force_set_get_count);
15390 CHECK_EQ(3, global->Get(access_property)->Int32Value());
15391 // CHECK_EQ the property shouldn't override it, just call the setter
15392 // which in this case does nothing.
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015393 global->Set(access_property, v8::Int32::New(isolate, 7));
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015394 CHECK_EQ(3, global->Get(access_property)->Int32Value());
15395 CHECK_EQ(1, force_set_set_count);
15396 CHECK_EQ(2, force_set_get_count);
15397 // Forcing the property to be set should override the accessor without
15398 // calling it
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015399 global->ForceSet(access_property, v8::Int32::New(isolate, 8));
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015400 CHECK_EQ(8, global->Get(access_property)->Int32Value());
15401 CHECK_EQ(1, force_set_set_count);
15402 CHECK_EQ(2, force_set_get_count);
15403}
15404
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000015405
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015406TEST(ForceSetWithInterceptor) {
15407 force_set_get_count = 0;
15408 force_set_set_count = 0;
15409 pass_on_get = false;
15410
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015411 v8::Isolate* isolate = CcTest::isolate();
15412 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000015413 v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015414 templ->SetNamedPropertyHandler(ForceSetGetter, ForceSetInterceptSetter);
15415 LocalContext context(NULL, templ);
15416 v8::Handle<v8::Object> global = context->Global();
15417
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015418 v8::Handle<v8::String> some_property =
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015419 v8::String::NewFromUtf8(isolate, "a");
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015420 CHECK_EQ(0, force_set_set_count);
15421 CHECK_EQ(0, force_set_get_count);
15422 CHECK_EQ(3, global->Get(some_property)->Int32Value());
15423 // Setting the property shouldn't override it, just call the setter
15424 // which in this case does nothing.
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015425 global->Set(some_property, v8::Int32::New(isolate, 7));
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015426 CHECK_EQ(3, global->Get(some_property)->Int32Value());
15427 CHECK_EQ(1, force_set_set_count);
15428 CHECK_EQ(2, force_set_get_count);
15429 // Getting the property when the interceptor returns an empty handle
15430 // should yield undefined, since the property isn't present on the
15431 // object itself yet.
15432 pass_on_get = true;
15433 CHECK(global->Get(some_property)->IsUndefined());
15434 CHECK_EQ(1, force_set_set_count);
15435 CHECK_EQ(3, force_set_get_count);
15436 // Forcing the property to be set should cause the value to be
15437 // set locally without calling the interceptor.
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015438 global->ForceSet(some_property, v8::Int32::New(isolate, 8));
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015439 CHECK_EQ(8, global->Get(some_property)->Int32Value());
15440 CHECK_EQ(1, force_set_set_count);
15441 CHECK_EQ(4, force_set_get_count);
15442 // Reenabling the interceptor should cause it to take precedence over
15443 // the property
15444 pass_on_get = false;
15445 CHECK_EQ(3, global->Get(some_property)->Int32Value());
15446 CHECK_EQ(1, force_set_set_count);
15447 CHECK_EQ(5, force_set_get_count);
15448 // The interceptor should also work for other properties
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015449 CHECK_EQ(3, global->Get(v8::String::NewFromUtf8(isolate, "b"))
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015450 ->Int32Value());
ager@chromium.org65dad4b2009-04-23 08:48:43 +000015451 CHECK_EQ(1, force_set_set_count);
15452 CHECK_EQ(6, force_set_get_count);
15453}
ager@chromium.org1bf0cd02009-05-20 11:34:19 +000015454
15455
ager@chromium.orge2902be2009-06-08 12:21:35 +000015456THREADED_TEST(ForceDelete) {
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015457 v8::Isolate* isolate = CcTest::isolate();
15458 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000015459 v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
ager@chromium.orge2902be2009-06-08 12:21:35 +000015460 LocalContext context(NULL, templ);
15461 v8::Handle<v8::Object> global = context->Global();
15462
15463 // Ordinary properties
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015464 v8::Handle<v8::String> simple_property =
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015465 v8::String::NewFromUtf8(isolate, "p");
15466 global->Set(simple_property, v8::Int32::New(isolate, 4), v8::DontDelete);
ager@chromium.orge2902be2009-06-08 12:21:35 +000015467 CHECK_EQ(4, global->Get(simple_property)->Int32Value());
15468 // This should fail because the property is dont-delete.
15469 CHECK(!global->Delete(simple_property));
15470 CHECK_EQ(4, global->Get(simple_property)->Int32Value());
15471 // This should succeed even though the property is dont-delete.
15472 CHECK(global->ForceDelete(simple_property));
15473 CHECK(global->Get(simple_property)->IsUndefined());
15474}
15475
15476
15477static int force_delete_interceptor_count = 0;
15478static bool pass_on_delete = false;
15479
15480
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015481static void ForceDeleteDeleter(
ager@chromium.orge2902be2009-06-08 12:21:35 +000015482 v8::Local<v8::String> name,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015483 const v8::PropertyCallbackInfo<v8::Boolean>& info) {
ager@chromium.orge2902be2009-06-08 12:21:35 +000015484 force_delete_interceptor_count++;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015485 if (pass_on_delete) return;
15486 info.GetReturnValue().Set(true);
ager@chromium.orge2902be2009-06-08 12:21:35 +000015487}
15488
15489
15490THREADED_TEST(ForceDeleteWithInterceptor) {
15491 force_delete_interceptor_count = 0;
15492 pass_on_delete = false;
15493
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015494 v8::Isolate* isolate = CcTest::isolate();
15495 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000015496 v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
ager@chromium.orge2902be2009-06-08 12:21:35 +000015497 templ->SetNamedPropertyHandler(0, 0, 0, ForceDeleteDeleter);
15498 LocalContext context(NULL, templ);
15499 v8::Handle<v8::Object> global = context->Global();
15500
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015501 v8::Handle<v8::String> some_property =
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015502 v8::String::NewFromUtf8(isolate, "a");
15503 global->Set(some_property, v8::Integer::New(isolate, 42), v8::DontDelete);
ager@chromium.orge2902be2009-06-08 12:21:35 +000015504
15505 // Deleting a property should get intercepted and nothing should
15506 // happen.
15507 CHECK_EQ(0, force_delete_interceptor_count);
15508 CHECK(global->Delete(some_property));
15509 CHECK_EQ(1, force_delete_interceptor_count);
15510 CHECK_EQ(42, global->Get(some_property)->Int32Value());
15511 // Deleting the property when the interceptor returns an empty
15512 // handle should not delete the property since it is DontDelete.
15513 pass_on_delete = true;
15514 CHECK(!global->Delete(some_property));
15515 CHECK_EQ(2, force_delete_interceptor_count);
15516 CHECK_EQ(42, global->Get(some_property)->Int32Value());
15517 // Forcing the property to be deleted should delete the value
15518 // without calling the interceptor.
15519 CHECK(global->ForceDelete(some_property));
15520 CHECK(global->Get(some_property)->IsUndefined());
15521 CHECK_EQ(2, force_delete_interceptor_count);
15522}
15523
15524
kasperl@chromium.org68ac0092009-07-09 06:00:35 +000015525// Make sure that forcing a delete invalidates any IC stubs, so we
15526// don't read the hole value.
15527THREADED_TEST(ForceDeleteIC) {
kasperl@chromium.org68ac0092009-07-09 06:00:35 +000015528 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015529 v8::HandleScope scope(context->GetIsolate());
kasperl@chromium.org68ac0092009-07-09 06:00:35 +000015530 // Create a DontDelete variable on the global object.
15531 CompileRun("this.__proto__ = { foo: 'horse' };"
15532 "var foo = 'fish';"
15533 "function f() { return foo.length; }");
15534 // Initialize the IC for foo in f.
15535 CompileRun("for (var i = 0; i < 4; i++) f();");
15536 // Make sure the value of foo is correct before the deletion.
15537 CHECK_EQ(4, CompileRun("f()")->Int32Value());
15538 // Force the deletion of foo.
15539 CHECK(context->Global()->ForceDelete(v8_str("foo")));
15540 // Make sure the value for foo is read from the prototype, and that
15541 // we don't get in trouble with reading the deleted cell value
15542 // sentinel.
15543 CHECK_EQ(5, CompileRun("f()")->Int32Value());
15544}
15545
15546
mstarzinger@chromium.org88d326b2012-04-23 12:57:22 +000015547TEST(InlinedFunctionAcrossContexts) {
15548 i::FLAG_allow_natives_syntax = true;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015549 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000015550 v8::HandleScope outer_scope(isolate);
15551 v8::Local<v8::Context> ctx1 = v8::Context::New(isolate);
15552 v8::Local<v8::Context> ctx2 = v8::Context::New(isolate);
mstarzinger@chromium.org88d326b2012-04-23 12:57:22 +000015553 ctx1->Enter();
15554
15555 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015556 v8::HandleScope inner_scope(CcTest::isolate());
mstarzinger@chromium.org88d326b2012-04-23 12:57:22 +000015557 CompileRun("var G = 42; function foo() { return G; }");
15558 v8::Local<v8::Value> foo = ctx1->Global()->Get(v8_str("foo"));
15559 ctx2->Enter();
15560 ctx2->Global()->Set(v8_str("o"), foo);
15561 v8::Local<v8::Value> res = CompileRun(
15562 "function f() { return o(); }"
15563 "for (var i = 0; i < 10; ++i) f();"
15564 "%OptimizeFunctionOnNextCall(f);"
15565 "f();");
15566 CHECK_EQ(42, res->Int32Value());
15567 ctx2->Exit();
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015568 v8::Handle<v8::String> G_property =
15569 v8::String::NewFromUtf8(CcTest::isolate(), "G");
mstarzinger@chromium.org88d326b2012-04-23 12:57:22 +000015570 CHECK(ctx1->Global()->ForceDelete(G_property));
15571 ctx2->Enter();
15572 ExpectString(
15573 "(function() {"
15574 " try {"
15575 " return f();"
15576 " } catch(e) {"
15577 " return e.toString();"
15578 " }"
15579 " })()",
15580 "ReferenceError: G is not defined");
15581 ctx2->Exit();
15582 ctx1->Exit();
mstarzinger@chromium.org88d326b2012-04-23 12:57:22 +000015583 }
mstarzinger@chromium.org88d326b2012-04-23 12:57:22 +000015584}
15585
15586
ulan@chromium.org57ff8812013-05-10 08:16:55 +000015587static v8::Local<Context> calling_context0;
15588static v8::Local<Context> calling_context1;
15589static v8::Local<Context> calling_context2;
ager@chromium.org1bf0cd02009-05-20 11:34:19 +000015590
15591
15592// Check that the call to the callback is initiated in
15593// calling_context2, the directly calling context is calling_context1
15594// and the callback itself is in calling_context0.
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015595static void GetCallingContextCallback(
15596 const v8::FunctionCallbackInfo<v8::Value>& args) {
ager@chromium.org1bf0cd02009-05-20 11:34:19 +000015597 ApiTestFuzzer::Fuzz();
mvstanton@chromium.org40ce96b2013-04-09 09:52:22 +000015598 CHECK(args.GetIsolate()->GetCurrentContext() == calling_context0);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015599 CHECK(args.GetIsolate()->GetCallingContext() == calling_context1);
15600 CHECK(args.GetIsolate()->GetEnteredContext() == calling_context2);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015601 args.GetReturnValue().Set(42);
15602}
15603
15604
15605THREADED_TEST(GetCurrentContextWhenNotInContext) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015606 i::Isolate* isolate = CcTest::i_isolate();
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000015607 CHECK(isolate != NULL);
15608 CHECK(isolate->context() == NULL);
15609 v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
15610 v8::HandleScope scope(v8_isolate);
15611 // The following should not crash, but return an empty handle.
15612 v8::Local<v8::Context> current = v8_isolate->GetCurrentContext();
15613 CHECK(current.IsEmpty());
ager@chromium.org1bf0cd02009-05-20 11:34:19 +000015614}
15615
15616
15617THREADED_TEST(GetCallingContext) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015618 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000015619 v8::HandleScope scope(isolate);
ager@chromium.org1bf0cd02009-05-20 11:34:19 +000015620
ulan@chromium.org57ff8812013-05-10 08:16:55 +000015621 Local<Context> calling_context0(Context::New(isolate));
15622 Local<Context> calling_context1(Context::New(isolate));
15623 Local<Context> calling_context2(Context::New(isolate));
15624 ::calling_context0 = calling_context0;
15625 ::calling_context1 = calling_context1;
15626 ::calling_context2 = calling_context2;
ager@chromium.org1bf0cd02009-05-20 11:34:19 +000015627
15628 // Allow cross-domain access.
15629 Local<String> token = v8_str("<security token>");
15630 calling_context0->SetSecurityToken(token);
15631 calling_context1->SetSecurityToken(token);
15632 calling_context2->SetSecurityToken(token);
15633
15634 // Create an object with a C++ callback in context0.
15635 calling_context0->Enter();
15636 Local<v8::FunctionTemplate> callback_templ =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000015637 v8::FunctionTemplate::New(isolate, GetCallingContextCallback);
ager@chromium.org1bf0cd02009-05-20 11:34:19 +000015638 calling_context0->Global()->Set(v8_str("callback"),
15639 callback_templ->GetFunction());
15640 calling_context0->Exit();
15641
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000015642 // Expose context0 in context1 and set up a function that calls the
ager@chromium.org1bf0cd02009-05-20 11:34:19 +000015643 // callback function.
15644 calling_context1->Enter();
15645 calling_context1->Global()->Set(v8_str("context0"),
15646 calling_context0->Global());
15647 CompileRun("function f() { context0.callback() }");
15648 calling_context1->Exit();
15649
15650 // Expose context1 in context2 and call the callback function in
15651 // context0 indirectly through f in context1.
15652 calling_context2->Enter();
15653 calling_context2->Global()->Set(v8_str("context1"),
15654 calling_context1->Global());
15655 CompileRun("context1.f()");
15656 calling_context2->Exit();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000015657 ::calling_context0.Clear();
15658 ::calling_context1.Clear();
15659 ::calling_context2.Clear();
ager@chromium.org1bf0cd02009-05-20 11:34:19 +000015660}
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000015661
15662
15663// Check that a variable declaration with no explicit initialization
erik.corry@gmail.comed49e962012-04-17 11:57:53 +000015664// value does shadow an existing property in the prototype chain.
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000015665THREADED_TEST(InitGlobalVarInProtoChain) {
mstarzinger@chromium.org88d326b2012-04-23 12:57:22 +000015666 i::FLAG_es52_globals = true;
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000015667 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015668 v8::HandleScope scope(context->GetIsolate());
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000015669 // Introduce a variable in the prototype chain.
15670 CompileRun("__proto__.x = 42");
erik.corry@gmail.comed49e962012-04-17 11:57:53 +000015671 v8::Handle<v8::Value> result = CompileRun("var x = 43; x");
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000015672 CHECK(!result->IsUndefined());
erik.corry@gmail.comed49e962012-04-17 11:57:53 +000015673 CHECK_EQ(43, result->Int32Value());
kasperl@chromium.org2abc4502009-07-02 07:00:29 +000015674}
kasperl@chromium.org68ac0092009-07-09 06:00:35 +000015675
15676
15677// Regression test for issue 398.
15678// If a function is added to an object, creating a constant function
15679// field, and the result is cloned, replacing the constant function on the
15680// original should not affect the clone.
15681// See http://code.google.com/p/v8/issues/detail?id=398
15682THREADED_TEST(ReplaceConstantFunction) {
kasperl@chromium.org68ac0092009-07-09 06:00:35 +000015683 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000015684 v8::Isolate* isolate = context->GetIsolate();
15685 v8::HandleScope scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015686 v8::Handle<v8::Object> obj = v8::Object::New(isolate);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000015687 v8::Handle<v8::FunctionTemplate> func_templ =
15688 v8::FunctionTemplate::New(isolate);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015689 v8::Handle<v8::String> foo_string =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000015690 v8::String::NewFromUtf8(isolate, "foo");
kasperl@chromium.org68ac0092009-07-09 06:00:35 +000015691 obj->Set(foo_string, func_templ->GetFunction());
15692 v8::Handle<v8::Object> obj_clone = obj->Clone();
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000015693 obj_clone->Set(foo_string,
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000015694 v8::String::NewFromUtf8(isolate, "Hello"));
kasperl@chromium.org68ac0092009-07-09 06:00:35 +000015695 CHECK(!obj->Get(foo_string)->IsUndefined());
15696}
kasperl@chromium.orge959c182009-07-27 08:59:04 +000015697
15698
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015699static void CheckElementValue(i::Isolate* isolate,
15700 int expected,
15701 i::Handle<i::Object> obj,
15702 int offset) {
15703 i::Object* element = obj->GetElement(isolate, offset)->ToObjectChecked();
15704 CHECK_EQ(expected, i::Smi::cast(element)->value());
15705}
15706
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015707
15708THREADED_TEST(PixelArray) {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015709 LocalContext context;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015710 i::Isolate* isolate = CcTest::i_isolate();
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015711 i::Factory* factory = isolate->factory();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000015712 v8::HandleScope scope(context->GetIsolate());
ager@chromium.orgc4c92722009-11-18 14:12:51 +000015713 const int kElementCount = 260;
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015714 uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(kElementCount));
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000015715 i::Handle<i::ExternalUint8ClampedArray> pixels =
15716 i::Handle<i::ExternalUint8ClampedArray>::cast(
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000015717 factory->NewExternalArray(kElementCount,
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000015718 v8::kExternalUint8ClampedArray,
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000015719 pixel_data));
15720 // Force GC to trigger verification.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015721 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015722 for (int i = 0; i < kElementCount; i++) {
ager@chromium.orgc4c92722009-11-18 14:12:51 +000015723 pixels->set(i, i % 256);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015724 }
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000015725 // Force GC to trigger verification.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000015726 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015727 for (int i = 0; i < kElementCount; i++) {
kmillikin@chromium.org7c2628c2011-08-10 11:27:35 +000015728 CHECK_EQ(i % 256, pixels->get_scalar(i));
ager@chromium.orgc4c92722009-11-18 14:12:51 +000015729 CHECK_EQ(i % 256, pixel_data[i]);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015730 }
15731
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015732 v8::Handle<v8::Object> obj = v8::Object::New(context->GetIsolate());
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015733 i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
15734 // Set the elements to be the pixels.
15735 // jsobj->set_elements(*pixels);
15736 obj->SetIndexedPropertiesToPixelData(pixel_data, kElementCount);
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015737 CheckElementValue(isolate, 1, jsobj, 1);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000015738 obj->Set(v8_str("field"), v8::Int32::New(CcTest::isolate(), 1503));
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015739 context->Global()->Set(v8_str("pixels"), obj);
15740 v8::Handle<v8::Value> result = CompileRun("pixels.field");
15741 CHECK_EQ(1503, result->Int32Value());
15742 result = CompileRun("pixels[1]");
15743 CHECK_EQ(1, result->Int32Value());
sgjesse@chromium.org9eceac12009-09-30 07:18:41 +000015744
15745 result = CompileRun("var sum = 0;"
15746 "for (var i = 0; i < 8; i++) {"
15747 " sum += pixels[i] = pixels[i] = -i;"
15748 "}"
15749 "sum;");
15750 CHECK_EQ(-28, result->Int32Value());
15751
15752 result = CompileRun("var sum = 0;"
15753 "for (var i = 0; i < 8; i++) {"
15754 " sum += pixels[i] = pixels[i] = 0;"
15755 "}"
15756 "sum;");
15757 CHECK_EQ(0, result->Int32Value());
15758
15759 result = CompileRun("var sum = 0;"
15760 "for (var i = 0; i < 8; i++) {"
15761 " sum += pixels[i] = pixels[i] = 255;"
15762 "}"
15763 "sum;");
15764 CHECK_EQ(8 * 255, result->Int32Value());
15765
15766 result = CompileRun("var sum = 0;"
15767 "for (var i = 0; i < 8; i++) {"
15768 " sum += pixels[i] = pixels[i] = 256 + i;"
15769 "}"
15770 "sum;");
15771 CHECK_EQ(2076, result->Int32Value());
15772
15773 result = CompileRun("var sum = 0;"
15774 "for (var i = 0; i < 8; i++) {"
15775 " sum += pixels[i] = pixels[i] = i;"
15776 "}"
15777 "sum;");
15778 CHECK_EQ(28, result->Int32Value());
15779
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015780 result = CompileRun("var sum = 0;"
15781 "for (var i = 0; i < 8; i++) {"
15782 " sum += pixels[i];"
15783 "}"
15784 "sum;");
15785 CHECK_EQ(28, result->Int32Value());
15786
ulan@chromium.org09d7ab52013-02-25 15:50:35 +000015787 i::Handle<i::Smi> value(i::Smi::FromInt(2),
15788 reinterpret_cast<i::Isolate*>(context->GetIsolate()));
jkummerow@chromium.org486075a2011-09-07 12:44:28 +000015789 i::Handle<i::Object> no_failure;
yangguo@chromium.orgab30bb82012-02-24 14:41:46 +000015790 no_failure =
15791 i::JSObject::SetElement(jsobj, 1, value, NONE, i::kNonStrictMode);
jkummerow@chromium.org486075a2011-09-07 12:44:28 +000015792 ASSERT(!no_failure.is_null());
15793 i::USE(no_failure);
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015794 CheckElementValue(isolate, 2, jsobj, 1);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015795 *value.location() = i::Smi::FromInt(256);
yangguo@chromium.orgab30bb82012-02-24 14:41:46 +000015796 no_failure =
15797 i::JSObject::SetElement(jsobj, 1, value, NONE, i::kNonStrictMode);
jkummerow@chromium.org486075a2011-09-07 12:44:28 +000015798 ASSERT(!no_failure.is_null());
15799 i::USE(no_failure);
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015800 CheckElementValue(isolate, 255, jsobj, 1);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015801 *value.location() = i::Smi::FromInt(-1);
yangguo@chromium.orgab30bb82012-02-24 14:41:46 +000015802 no_failure =
15803 i::JSObject::SetElement(jsobj, 1, value, NONE, i::kNonStrictMode);
jkummerow@chromium.org486075a2011-09-07 12:44:28 +000015804 ASSERT(!no_failure.is_null());
15805 i::USE(no_failure);
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015806 CheckElementValue(isolate, 0, jsobj, 1);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015807
15808 result = CompileRun("for (var i = 0; i < 8; i++) {"
15809 " pixels[i] = (i * 65) - 109;"
15810 "}"
15811 "pixels[1] + pixels[6];");
15812 CHECK_EQ(255, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015813 CheckElementValue(isolate, 0, jsobj, 0);
15814 CheckElementValue(isolate, 0, jsobj, 1);
15815 CheckElementValue(isolate, 21, jsobj, 2);
15816 CheckElementValue(isolate, 86, jsobj, 3);
15817 CheckElementValue(isolate, 151, jsobj, 4);
15818 CheckElementValue(isolate, 216, jsobj, 5);
15819 CheckElementValue(isolate, 255, jsobj, 6);
15820 CheckElementValue(isolate, 255, jsobj, 7);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015821 result = CompileRun("var sum = 0;"
15822 "for (var i = 0; i < 8; i++) {"
15823 " sum += pixels[i];"
15824 "}"
15825 "sum;");
15826 CHECK_EQ(984, result->Int32Value());
15827
15828 result = CompileRun("for (var i = 0; i < 8; i++) {"
15829 " pixels[i] = (i * 1.1);"
15830 "}"
15831 "pixels[1] + pixels[6];");
15832 CHECK_EQ(8, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015833 CheckElementValue(isolate, 0, jsobj, 0);
15834 CheckElementValue(isolate, 1, jsobj, 1);
15835 CheckElementValue(isolate, 2, jsobj, 2);
15836 CheckElementValue(isolate, 3, jsobj, 3);
15837 CheckElementValue(isolate, 4, jsobj, 4);
15838 CheckElementValue(isolate, 6, jsobj, 5);
15839 CheckElementValue(isolate, 7, jsobj, 6);
15840 CheckElementValue(isolate, 8, jsobj, 7);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015841
15842 result = CompileRun("for (var i = 0; i < 8; i++) {"
15843 " pixels[7] = undefined;"
15844 "}"
15845 "pixels[7];");
15846 CHECK_EQ(0, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015847 CheckElementValue(isolate, 0, jsobj, 7);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015848
15849 result = CompileRun("for (var i = 0; i < 8; i++) {"
15850 " pixels[6] = '2.3';"
15851 "}"
15852 "pixels[6];");
15853 CHECK_EQ(2, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015854 CheckElementValue(isolate, 2, jsobj, 6);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015855
15856 result = CompileRun("for (var i = 0; i < 8; i++) {"
15857 " pixels[5] = NaN;"
15858 "}"
15859 "pixels[5];");
15860 CHECK_EQ(0, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015861 CheckElementValue(isolate, 0, jsobj, 5);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015862
15863 result = CompileRun("for (var i = 0; i < 8; i++) {"
15864 " pixels[8] = Infinity;"
15865 "}"
15866 "pixels[8];");
15867 CHECK_EQ(255, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015868 CheckElementValue(isolate, 255, jsobj, 8);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015869
15870 result = CompileRun("for (var i = 0; i < 8; i++) {"
15871 " pixels[9] = -Infinity;"
15872 "}"
15873 "pixels[9];");
15874 CHECK_EQ(0, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000015875 CheckElementValue(isolate, 0, jsobj, 9);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000015876
15877 result = CompileRun("pixels[3] = 33;"
15878 "delete pixels[3];"
15879 "pixels[3];");
15880 CHECK_EQ(33, result->Int32Value());
15881
15882 result = CompileRun("pixels[0] = 10; pixels[1] = 11;"
15883 "pixels[2] = 12; pixels[3] = 13;"
15884 "pixels.__defineGetter__('2',"
15885 "function() { return 120; });"
15886 "pixels[2];");
15887 CHECK_EQ(12, result->Int32Value());
15888
15889 result = CompileRun("var js_array = new Array(40);"
15890 "js_array[0] = 77;"
15891 "js_array;");
15892 CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
15893
15894 result = CompileRun("pixels[1] = 23;"
15895 "pixels.__proto__ = [];"
15896 "js_array.__proto__ = pixels;"
15897 "js_array.concat(pixels);");
15898 CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
15899 CHECK_EQ(23, v8::Object::Cast(*result)->Get(v8_str("1"))->Int32Value());
15900
sgjesse@chromium.org9eceac12009-09-30 07:18:41 +000015901 result = CompileRun("pixels[1] = 23;");
15902 CHECK_EQ(23, result->Int32Value());
15903
ager@chromium.orgc4c92722009-11-18 14:12:51 +000015904 // Test for index greater than 255. Regression test for:
15905 // http://code.google.com/p/chromium/issues/detail?id=26337.
15906 result = CompileRun("pixels[256] = 255;");
15907 CHECK_EQ(255, result->Int32Value());
15908 result = CompileRun("var i = 0;"
15909 "for (var j = 0; j < 8; j++) { i = pixels[256]; }"
15910 "i");
15911 CHECK_EQ(255, result->Int32Value());
15912
ricow@chromium.org83aa5492011-02-07 12:42:56 +000015913 // Make sure that pixel array ICs recognize when a non-pixel array
15914 // is passed to it.
15915 result = CompileRun("function pa_load(p) {"
15916 " var sum = 0;"
15917 " for (var j = 0; j < 256; j++) { sum += p[j]; }"
15918 " return sum;"
15919 "}"
15920 "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
15921 "for (var i = 0; i < 10; ++i) { pa_load(pixels); }"
15922 "just_ints = new Object();"
15923 "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
15924 "for (var i = 0; i < 10; ++i) {"
15925 " result = pa_load(just_ints);"
15926 "}"
15927 "result");
15928 CHECK_EQ(32640, result->Int32Value());
15929
15930 // Make sure that pixel array ICs recognize out-of-bound accesses.
15931 result = CompileRun("function pa_load(p, start) {"
15932 " var sum = 0;"
15933 " for (var j = start; j < 256; j++) { sum += p[j]; }"
15934 " return sum;"
15935 "}"
15936 "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
15937 "for (var i = 0; i < 10; ++i) { pa_load(pixels,0); }"
15938 "for (var i = 0; i < 10; ++i) {"
15939 " result = pa_load(pixels,-10);"
15940 "}"
15941 "result");
15942 CHECK_EQ(0, result->Int32Value());
15943
15944 // Make sure that generic ICs properly handles a pixel array.
15945 result = CompileRun("function pa_load(p) {"
15946 " var sum = 0;"
15947 " for (var j = 0; j < 256; j++) { sum += p[j]; }"
15948 " return sum;"
15949 "}"
15950 "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
15951 "just_ints = new Object();"
15952 "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
15953 "for (var i = 0; i < 10; ++i) { pa_load(just_ints); }"
15954 "for (var i = 0; i < 10; ++i) {"
15955 " result = pa_load(pixels);"
15956 "}"
15957 "result");
15958 CHECK_EQ(32640, result->Int32Value());
15959
15960 // Make sure that generic load ICs recognize out-of-bound accesses in
15961 // pixel arrays.
15962 result = CompileRun("function pa_load(p, start) {"
15963 " var sum = 0;"
15964 " for (var j = start; j < 256; j++) { sum += p[j]; }"
15965 " return sum;"
15966 "}"
15967 "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
15968 "just_ints = new Object();"
15969 "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
15970 "for (var i = 0; i < 10; ++i) { pa_load(just_ints,0); }"
15971 "for (var i = 0; i < 10; ++i) { pa_load(pixels,0); }"
15972 "for (var i = 0; i < 10; ++i) {"
15973 " result = pa_load(pixels,-10);"
15974 "}"
15975 "result");
15976 CHECK_EQ(0, result->Int32Value());
15977
15978 // Make sure that generic ICs properly handles other types than pixel
15979 // arrays (that the inlined fast pixel array test leaves the right information
15980 // in the right registers).
15981 result = CompileRun("function pa_load(p) {"
15982 " var sum = 0;"
15983 " for (var j = 0; j < 256; j++) { sum += p[j]; }"
15984 " return sum;"
15985 "}"
15986 "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
15987 "just_ints = new Object();"
15988 "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
15989 "for (var i = 0; i < 10; ++i) { pa_load(just_ints); }"
15990 "for (var i = 0; i < 10; ++i) { pa_load(pixels); }"
15991 "sparse_array = new Object();"
15992 "for (var i = 0; i < 256; ++i) { sparse_array[i] = i; }"
15993 "sparse_array[1000000] = 3;"
15994 "for (var i = 0; i < 10; ++i) {"
15995 " result = pa_load(sparse_array);"
15996 "}"
15997 "result");
15998 CHECK_EQ(32640, result->Int32Value());
15999
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +000016000 // Make sure that pixel array store ICs clamp values correctly.
16001 result = CompileRun("function pa_store(p) {"
16002 " for (var j = 0; j < 256; j++) { p[j] = j * 2; }"
16003 "}"
16004 "pa_store(pixels);"
16005 "var sum = 0;"
16006 "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
16007 "sum");
16008 CHECK_EQ(48896, result->Int32Value());
16009
16010 // Make sure that pixel array stores correctly handle accesses outside
16011 // of the pixel array..
16012 result = CompileRun("function pa_store(p,start) {"
16013 " for (var j = 0; j < 256; j++) {"
16014 " p[j+start] = j * 2;"
16015 " }"
16016 "}"
16017 "pa_store(pixels,0);"
16018 "pa_store(pixels,-128);"
16019 "var sum = 0;"
16020 "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
16021 "sum");
16022 CHECK_EQ(65280, result->Int32Value());
16023
16024 // Make sure that the generic store stub correctly handle accesses outside
16025 // of the pixel array..
16026 result = CompileRun("function pa_store(p,start) {"
16027 " for (var j = 0; j < 256; j++) {"
16028 " p[j+start] = j * 2;"
16029 " }"
16030 "}"
16031 "pa_store(pixels,0);"
16032 "just_ints = new Object();"
16033 "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
16034 "pa_store(just_ints, 0);"
16035 "pa_store(pixels,-128);"
16036 "var sum = 0;"
16037 "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
16038 "sum");
16039 CHECK_EQ(65280, result->Int32Value());
16040
16041 // Make sure that the generic keyed store stub clamps pixel array values
16042 // correctly.
16043 result = CompileRun("function pa_store(p) {"
16044 " for (var j = 0; j < 256; j++) { p[j] = j * 2; }"
16045 "}"
16046 "pa_store(pixels);"
16047 "just_ints = new Object();"
16048 "pa_store(just_ints);"
16049 "pa_store(pixels);"
16050 "var sum = 0;"
16051 "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
16052 "sum");
16053 CHECK_EQ(48896, result->Int32Value());
16054
16055 // Make sure that pixel array loads are optimized by crankshaft.
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000016056 result = CompileRun("function pa_load(p) {"
16057 " var sum = 0;"
16058 " for (var i=0; i<256; ++i) {"
16059 " sum += p[i];"
16060 " }"
16061 " return sum; "
16062 "}"
16063 "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000016064 "for (var i = 0; i < 5000; ++i) {"
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000016065 " result = pa_load(pixels);"
16066 "}"
16067 "result");
16068 CHECK_EQ(32640, result->Int32Value());
16069
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000016070 // Make sure that pixel array stores are optimized by crankshaft.
16071 result = CompileRun("function pa_init(p) {"
16072 "for (var i = 0; i < 256; ++i) { p[i] = i; }"
16073 "}"
16074 "function pa_load(p) {"
16075 " var sum = 0;"
16076 " for (var i=0; i<256; ++i) {"
16077 " sum += p[i];"
16078 " }"
16079 " return sum; "
16080 "}"
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000016081 "for (var i = 0; i < 5000; ++i) {"
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000016082 " pa_init(pixels);"
16083 "}"
16084 "result = pa_load(pixels);"
16085 "result");
16086 CHECK_EQ(32640, result->Int32Value());
16087
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000016088 free(pixel_data);
16089}
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000016090
ager@chromium.org96c75b52009-08-26 09:13:16 +000016091
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016092THREADED_TEST(PixelArrayInfo) {
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016093 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016094 v8::HandleScope scope(context->GetIsolate());
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016095 for (int size = 0; size < 100; size += 10) {
16096 uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(size));
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016097 v8::Handle<v8::Object> obj = v8::Object::New(context->GetIsolate());
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016098 obj->SetIndexedPropertiesToPixelData(pixel_data, size);
16099 CHECK(obj->HasIndexedPropertiesInPixelData());
16100 CHECK_EQ(pixel_data, obj->GetIndexedPropertiesPixelData());
16101 CHECK_EQ(size, obj->GetIndexedPropertiesPixelDataLength());
16102 free(pixel_data);
16103 }
16104}
16105
16106
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000016107static void NotHandledIndexedPropertyGetter(
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000016108 uint32_t index,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000016109 const v8::PropertyCallbackInfo<v8::Value>& info) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000016110 ApiTestFuzzer::Fuzz();
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000016111}
16112
16113
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000016114static void NotHandledIndexedPropertySetter(
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000016115 uint32_t index,
16116 Local<Value> value,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000016117 const v8::PropertyCallbackInfo<v8::Value>& info) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000016118 ApiTestFuzzer::Fuzz();
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000016119}
16120
16121
16122THREADED_TEST(PixelArrayWithInterceptor) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000016123 LocalContext context;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000016124 i::Factory* factory = CcTest::i_isolate()->factory();
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000016125 v8::Isolate* isolate = context->GetIsolate();
16126 v8::HandleScope scope(isolate);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000016127 const int kElementCount = 260;
16128 uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(kElementCount));
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016129 i::Handle<i::ExternalUint8ClampedArray> pixels =
16130 i::Handle<i::ExternalUint8ClampedArray>::cast(
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000016131 factory->NewExternalArray(kElementCount,
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016132 v8::kExternalUint8ClampedArray,
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000016133 pixel_data));
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000016134 for (int i = 0; i < kElementCount; i++) {
16135 pixels->set(i, i % 256);
16136 }
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000016137 v8::Handle<v8::ObjectTemplate> templ =
16138 v8::ObjectTemplate::New(context->GetIsolate());
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +000016139 templ->SetIndexedPropertyHandler(NotHandledIndexedPropertyGetter,
16140 NotHandledIndexedPropertySetter);
16141 v8::Handle<v8::Object> obj = templ->NewInstance();
16142 obj->SetIndexedPropertiesToPixelData(pixel_data, kElementCount);
16143 context->Global()->Set(v8_str("pixels"), obj);
16144 v8::Handle<v8::Value> result = CompileRun("pixels[1]");
16145 CHECK_EQ(1, result->Int32Value());
16146 result = CompileRun("var sum = 0;"
16147 "for (var i = 0; i < 8; i++) {"
16148 " sum += pixels[i] = pixels[i] = -i;"
16149 "}"
16150 "sum;");
16151 CHECK_EQ(-28, result->Int32Value());
16152 result = CompileRun("pixels.hasOwnProperty('1')");
16153 CHECK(result->BooleanValue());
16154 free(pixel_data);
16155}
16156
16157
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016158static int ExternalArrayElementSize(v8::ExternalArrayType array_type) {
16159 switch (array_type) {
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016160 case v8::kExternalInt8Array:
16161 case v8::kExternalUint8Array:
16162 case v8::kExternalUint8ClampedArray:
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016163 return 1;
16164 break;
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016165 case v8::kExternalInt16Array:
16166 case v8::kExternalUint16Array:
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016167 return 2;
16168 break;
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016169 case v8::kExternalInt32Array:
16170 case v8::kExternalUint32Array:
16171 case v8::kExternalFloat32Array:
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016172 return 4;
16173 break;
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016174 case v8::kExternalFloat64Array:
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +000016175 return 8;
16176 break;
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016177 default:
16178 UNREACHABLE();
16179 return -1;
16180 }
16181 UNREACHABLE();
16182 return -1;
16183}
16184
16185
ager@chromium.org3811b432009-10-28 14:53:37 +000016186template <class ExternalArrayClass, class ElementType>
danno@chromium.orgf005df62013-04-30 16:36:45 +000016187static void ObjectWithExternalArrayTestHelper(
16188 Handle<Context> context,
16189 v8::Handle<Object> obj,
16190 int element_count,
16191 v8::ExternalArrayType array_type,
16192 int64_t low, int64_t high) {
ager@chromium.org3811b432009-10-28 14:53:37 +000016193 i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000016194 i::Isolate* isolate = jsobj->GetIsolate();
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016195 obj->Set(v8_str("field"),
16196 v8::Int32::New(reinterpret_cast<v8::Isolate*>(isolate), 1503));
ager@chromium.org3811b432009-10-28 14:53:37 +000016197 context->Global()->Set(v8_str("ext_array"), obj);
16198 v8::Handle<v8::Value> result = CompileRun("ext_array.field");
16199 CHECK_EQ(1503, result->Int32Value());
16200 result = CompileRun("ext_array[1]");
16201 CHECK_EQ(1, result->Int32Value());
16202
ager@chromium.org3811b432009-10-28 14:53:37 +000016203 // Check assigned smis
16204 result = CompileRun("for (var i = 0; i < 8; i++) {"
16205 " ext_array[i] = i;"
16206 "}"
16207 "var sum = 0;"
16208 "for (var i = 0; i < 8; i++) {"
16209 " sum += ext_array[i];"
16210 "}"
16211 "sum;");
machenbach@chromium.org5c88bc32014-01-17 08:10:36 +000016212
ager@chromium.org3811b432009-10-28 14:53:37 +000016213 CHECK_EQ(28, result->Int32Value());
machenbach@chromium.org5c88bc32014-01-17 08:10:36 +000016214 // Check pass through of assigned smis
16215 result = CompileRun("var sum = 0;"
16216 "for (var i = 0; i < 8; i++) {"
16217 " sum += ext_array[i] = ext_array[i] = -i;"
16218 "}"
16219 "sum;");
16220 CHECK_EQ(-28, result->Int32Value());
16221
ager@chromium.org3811b432009-10-28 14:53:37 +000016222
16223 // Check assigned smis in reverse order
16224 result = CompileRun("for (var i = 8; --i >= 0; ) {"
16225 " ext_array[i] = i;"
16226 "}"
16227 "var sum = 0;"
16228 "for (var i = 0; i < 8; i++) {"
16229 " sum += ext_array[i];"
16230 "}"
16231 "sum;");
16232 CHECK_EQ(28, result->Int32Value());
16233
16234 // Check pass through of assigned HeapNumbers
16235 result = CompileRun("var sum = 0;"
16236 "for (var i = 0; i < 16; i+=2) {"
16237 " sum += ext_array[i] = ext_array[i] = (-i * 0.5);"
16238 "}"
16239 "sum;");
16240 CHECK_EQ(-28, result->Int32Value());
16241
16242 // Check assigned HeapNumbers
16243 result = CompileRun("for (var i = 0; i < 16; i+=2) {"
16244 " ext_array[i] = (i * 0.5);"
16245 "}"
16246 "var sum = 0;"
16247 "for (var i = 0; i < 16; i+=2) {"
16248 " sum += ext_array[i];"
16249 "}"
16250 "sum;");
16251 CHECK_EQ(28, result->Int32Value());
16252
16253 // Check assigned HeapNumbers in reverse order
16254 result = CompileRun("for (var i = 14; i >= 0; i-=2) {"
16255 " ext_array[i] = (i * 0.5);"
16256 "}"
16257 "var sum = 0;"
16258 "for (var i = 0; i < 16; i+=2) {"
16259 " sum += ext_array[i];"
16260 "}"
16261 "sum;");
16262 CHECK_EQ(28, result->Int32Value());
16263
16264 i::ScopedVector<char> test_buf(1024);
16265
16266 // Check legal boundary conditions.
16267 // The repeated loads and stores ensure the ICs are exercised.
16268 const char* boundary_program =
16269 "var res = 0;"
16270 "for (var i = 0; i < 16; i++) {"
16271 " ext_array[i] = %lld;"
16272 " if (i > 8) {"
16273 " res = ext_array[i];"
16274 " }"
16275 "}"
16276 "res;";
16277 i::OS::SNPrintF(test_buf,
16278 boundary_program,
16279 low);
16280 result = CompileRun(test_buf.start());
16281 CHECK_EQ(low, result->IntegerValue());
16282
16283 i::OS::SNPrintF(test_buf,
16284 boundary_program,
16285 high);
16286 result = CompileRun(test_buf.start());
16287 CHECK_EQ(high, result->IntegerValue());
16288
16289 // Check misprediction of type in IC.
16290 result = CompileRun("var tmp_array = ext_array;"
16291 "var sum = 0;"
16292 "for (var i = 0; i < 8; i++) {"
16293 " tmp_array[i] = i;"
16294 " sum += tmp_array[i];"
16295 " if (i == 4) {"
16296 " tmp_array = {};"
16297 " }"
16298 "}"
16299 "sum;");
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000016300 // Force GC to trigger verification.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000016301 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org3811b432009-10-28 14:53:37 +000016302 CHECK_EQ(28, result->Int32Value());
16303
16304 // Make sure out-of-range loads do not throw.
16305 i::OS::SNPrintF(test_buf,
16306 "var caught_exception = false;"
16307 "try {"
16308 " ext_array[%d];"
16309 "} catch (e) {"
16310 " caught_exception = true;"
16311 "}"
16312 "caught_exception;",
danno@chromium.orgf005df62013-04-30 16:36:45 +000016313 element_count);
ager@chromium.org3811b432009-10-28 14:53:37 +000016314 result = CompileRun(test_buf.start());
16315 CHECK_EQ(false, result->BooleanValue());
16316
16317 // Make sure out-of-range stores do not throw.
16318 i::OS::SNPrintF(test_buf,
16319 "var caught_exception = false;"
16320 "try {"
16321 " ext_array[%d] = 1;"
16322 "} catch (e) {"
16323 " caught_exception = true;"
16324 "}"
16325 "caught_exception;",
danno@chromium.orgf005df62013-04-30 16:36:45 +000016326 element_count);
ager@chromium.org3811b432009-10-28 14:53:37 +000016327 result = CompileRun(test_buf.start());
16328 CHECK_EQ(false, result->BooleanValue());
16329
16330 // Check other boundary conditions, values and operations.
16331 result = CompileRun("for (var i = 0; i < 8; i++) {"
16332 " ext_array[7] = undefined;"
16333 "}"
16334 "ext_array[7];");
16335 CHECK_EQ(0, result->Int32Value());
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016336 if (array_type == v8::kExternalFloat64Array ||
16337 array_type == v8::kExternalFloat32Array) {
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000016338 CHECK_EQ(static_cast<int>(i::OS::nan_value()),
16339 static_cast<int>(
16340 jsobj->GetElement(isolate, 7)->ToObjectChecked()->Number()));
yangguo@chromium.org56454712012-02-16 15:33:53 +000016341 } else {
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000016342 CheckElementValue(isolate, 0, jsobj, 7);
yangguo@chromium.org56454712012-02-16 15:33:53 +000016343 }
ager@chromium.org3811b432009-10-28 14:53:37 +000016344
16345 result = CompileRun("for (var i = 0; i < 8; i++) {"
16346 " ext_array[6] = '2.3';"
16347 "}"
16348 "ext_array[6];");
16349 CHECK_EQ(2, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000016350 CHECK_EQ(2,
16351 static_cast<int>(
16352 jsobj->GetElement(isolate, 6)->ToObjectChecked()->Number()));
ager@chromium.org3811b432009-10-28 14:53:37 +000016353
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016354 if (array_type != v8::kExternalFloat32Array &&
16355 array_type != v8::kExternalFloat64Array) {
ager@chromium.org3811b432009-10-28 14:53:37 +000016356 // Though the specification doesn't state it, be explicit about
16357 // converting NaNs and +/-Infinity to zero.
16358 result = CompileRun("for (var i = 0; i < 8; i++) {"
16359 " ext_array[i] = 5;"
16360 "}"
16361 "for (var i = 0; i < 8; i++) {"
16362 " ext_array[i] = NaN;"
16363 "}"
16364 "ext_array[5];");
16365 CHECK_EQ(0, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000016366 CheckElementValue(isolate, 0, jsobj, 5);
ager@chromium.org3811b432009-10-28 14:53:37 +000016367
16368 result = CompileRun("for (var i = 0; i < 8; i++) {"
16369 " ext_array[i] = 5;"
16370 "}"
16371 "for (var i = 0; i < 8; i++) {"
16372 " ext_array[i] = Infinity;"
16373 "}"
16374 "ext_array[5];");
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000016375 int expected_value =
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016376 (array_type == v8::kExternalUint8ClampedArray) ? 255 : 0;
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000016377 CHECK_EQ(expected_value, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000016378 CheckElementValue(isolate, expected_value, jsobj, 5);
ager@chromium.org3811b432009-10-28 14:53:37 +000016379
16380 result = CompileRun("for (var i = 0; i < 8; i++) {"
16381 " ext_array[i] = 5;"
16382 "}"
16383 "for (var i = 0; i < 8; i++) {"
16384 " ext_array[i] = -Infinity;"
16385 "}"
16386 "ext_array[5];");
16387 CHECK_EQ(0, result->Int32Value());
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000016388 CheckElementValue(isolate, 0, jsobj, 5);
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +000016389
16390 // Check truncation behavior of integral arrays.
16391 const char* unsigned_data =
16392 "var source_data = [0.6, 10.6];"
16393 "var expected_results = [0, 10];";
16394 const char* signed_data =
16395 "var source_data = [0.6, 10.6, -0.6, -10.6];"
16396 "var expected_results = [0, 10, 0, -10];";
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000016397 const char* pixel_data =
16398 "var source_data = [0.6, 10.6];"
16399 "var expected_results = [1, 11];";
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +000016400 bool is_unsigned =
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016401 (array_type == v8::kExternalUint8Array ||
16402 array_type == v8::kExternalUint16Array ||
16403 array_type == v8::kExternalUint32Array);
16404 bool is_pixel_data = array_type == v8::kExternalUint8ClampedArray;
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +000016405
16406 i::OS::SNPrintF(test_buf,
16407 "%s"
16408 "var all_passed = true;"
16409 "for (var i = 0; i < source_data.length; i++) {"
16410 " for (var j = 0; j < 8; j++) {"
16411 " ext_array[j] = source_data[i];"
16412 " }"
16413 " all_passed = all_passed &&"
16414 " (ext_array[5] == expected_results[i]);"
16415 "}"
16416 "all_passed;",
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000016417 (is_unsigned ?
16418 unsigned_data :
16419 (is_pixel_data ? pixel_data : signed_data)));
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +000016420 result = CompileRun(test_buf.start());
16421 CHECK_EQ(true, result->BooleanValue());
ager@chromium.org3811b432009-10-28 14:53:37 +000016422 }
16423
danno@chromium.orgf005df62013-04-30 16:36:45 +000016424 i::Handle<ExternalArrayClass> array(
16425 ExternalArrayClass::cast(jsobj->elements()));
16426 for (int i = 0; i < element_count; i++) {
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000016427 array->set(i, static_cast<ElementType>(i));
16428 }
danno@chromium.orgf005df62013-04-30 16:36:45 +000016429
karlklose@chromium.org44bc7082011-04-11 12:33:05 +000016430 // Test complex assignments
16431 result = CompileRun("function ee_op_test_complex_func(sum) {"
16432 " for (var i = 0; i < 40; ++i) {"
16433 " sum += (ext_array[i] += 1);"
16434 " sum += (ext_array[i] -= 1);"
16435 " } "
16436 " return sum;"
16437 "}"
16438 "sum=0;"
16439 "for (var i=0;i<10000;++i) {"
16440 " sum=ee_op_test_complex_func(sum);"
16441 "}"
16442 "sum;");
16443 CHECK_EQ(16000000, result->Int32Value());
16444
16445 // Test count operations
16446 result = CompileRun("function ee_op_test_count_func(sum) {"
16447 " for (var i = 0; i < 40; ++i) {"
16448 " sum += (++ext_array[i]);"
16449 " sum += (--ext_array[i]);"
16450 " } "
16451 " return sum;"
16452 "}"
16453 "sum=0;"
16454 "for (var i=0;i<10000;++i) {"
16455 " sum=ee_op_test_count_func(sum);"
16456 "}"
16457 "sum;");
16458 CHECK_EQ(16000000, result->Int32Value());
16459
ager@chromium.org3811b432009-10-28 14:53:37 +000016460 result = CompileRun("ext_array[3] = 33;"
16461 "delete ext_array[3];"
16462 "ext_array[3];");
16463 CHECK_EQ(33, result->Int32Value());
16464
16465 result = CompileRun("ext_array[0] = 10; ext_array[1] = 11;"
16466 "ext_array[2] = 12; ext_array[3] = 13;"
16467 "ext_array.__defineGetter__('2',"
16468 "function() { return 120; });"
16469 "ext_array[2];");
16470 CHECK_EQ(12, result->Int32Value());
16471
16472 result = CompileRun("var js_array = new Array(40);"
16473 "js_array[0] = 77;"
16474 "js_array;");
16475 CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
16476
16477 result = CompileRun("ext_array[1] = 23;"
16478 "ext_array.__proto__ = [];"
16479 "js_array.__proto__ = ext_array;"
16480 "js_array.concat(ext_array);");
16481 CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
16482 CHECK_EQ(23, v8::Object::Cast(*result)->Get(v8_str("1"))->Int32Value());
16483
16484 result = CompileRun("ext_array[1] = 23;");
16485 CHECK_EQ(23, result->Int32Value());
danno@chromium.orgf005df62013-04-30 16:36:45 +000016486}
16487
16488
machenbach@chromium.org5c88bc32014-01-17 08:10:36 +000016489template <class FixedTypedArrayClass,
16490 i::ElementsKind elements_kind,
16491 class ElementType>
16492static void FixedTypedArrayTestHelper(
16493 v8::ExternalArrayType array_type,
16494 ElementType low,
16495 ElementType high) {
16496 i::FLAG_allow_natives_syntax = true;
16497 LocalContext context;
16498 i::Isolate* isolate = CcTest::i_isolate();
16499 i::Factory* factory = isolate->factory();
16500 v8::HandleScope scope(context->GetIsolate());
16501 const int kElementCount = 260;
16502 i::Handle<FixedTypedArrayClass> fixed_array =
16503 i::Handle<FixedTypedArrayClass>::cast(
16504 factory->NewFixedTypedArray(kElementCount, array_type));
16505 CHECK_EQ(FixedTypedArrayClass::kInstanceType,
16506 fixed_array->map()->instance_type());
16507 CHECK_EQ(kElementCount, fixed_array->length());
16508 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
16509 for (int i = 0; i < kElementCount; i++) {
16510 fixed_array->set(i, static_cast<ElementType>(i));
16511 }
16512 // Force GC to trigger verification.
16513 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
16514 for (int i = 0; i < kElementCount; i++) {
16515 CHECK_EQ(static_cast<int64_t>(static_cast<ElementType>(i)),
16516 static_cast<int64_t>(fixed_array->get_scalar(i)));
16517 }
16518 v8::Handle<v8::Object> obj = v8::Object::New(CcTest::isolate());
16519 i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
16520 i::Handle<i::Map> fixed_array_map =
16521 isolate->factory()->GetElementsTransitionMap(jsobj, elements_kind);
16522 jsobj->set_map(*fixed_array_map);
16523 jsobj->set_elements(*fixed_array);
16524
16525 ObjectWithExternalArrayTestHelper<FixedTypedArrayClass, ElementType>(
16526 context.local(), obj, kElementCount, array_type,
16527 static_cast<int64_t>(low),
16528 static_cast<int64_t>(high));
16529}
16530
16531
16532THREADED_TEST(FixedUint8Array) {
16533 FixedTypedArrayTestHelper<i::FixedUint8Array, i::UINT8_ELEMENTS, uint8_t>(
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016534 v8::kExternalUint8Array,
machenbach@chromium.org5c88bc32014-01-17 08:10:36 +000016535 0x0, 0xFF);
16536}
16537
16538
16539THREADED_TEST(FixedUint8ClampedArray) {
16540 FixedTypedArrayTestHelper<i::FixedUint8ClampedArray,
16541 i::UINT8_CLAMPED_ELEMENTS, uint8_t>(
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016542 v8::kExternalUint8ClampedArray,
machenbach@chromium.org5c88bc32014-01-17 08:10:36 +000016543 0x0, 0xFF);
16544}
16545
16546
16547THREADED_TEST(FixedInt8Array) {
16548 FixedTypedArrayTestHelper<i::FixedInt8Array, i::INT8_ELEMENTS, int8_t>(
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016549 v8::kExternalInt8Array,
machenbach@chromium.org5c88bc32014-01-17 08:10:36 +000016550 -0x80, 0x7F);
16551}
16552
16553
16554THREADED_TEST(FixedUint16Array) {
16555 FixedTypedArrayTestHelper<i::FixedUint16Array, i::UINT16_ELEMENTS, uint16_t>(
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016556 v8::kExternalUint16Array,
machenbach@chromium.org5c88bc32014-01-17 08:10:36 +000016557 0x0, 0xFFFF);
16558}
16559
16560
16561THREADED_TEST(FixedInt16Array) {
16562 FixedTypedArrayTestHelper<i::FixedInt16Array, i::INT16_ELEMENTS, int16_t>(
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016563 v8::kExternalInt16Array,
machenbach@chromium.org5c88bc32014-01-17 08:10:36 +000016564 -0x8000, 0x7FFF);
16565}
16566
16567
16568THREADED_TEST(FixedUint32Array) {
16569 FixedTypedArrayTestHelper<i::FixedUint32Array, i::UINT32_ELEMENTS, uint32_t>(
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016570 v8::kExternalUint32Array,
machenbach@chromium.org5c88bc32014-01-17 08:10:36 +000016571 0x0, UINT_MAX);
16572}
16573
16574
16575THREADED_TEST(FixedInt32Array) {
16576 FixedTypedArrayTestHelper<i::FixedInt32Array, i::INT32_ELEMENTS, int32_t>(
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016577 v8::kExternalInt32Array,
machenbach@chromium.org5c88bc32014-01-17 08:10:36 +000016578 INT_MIN, INT_MAX);
16579}
16580
16581
16582THREADED_TEST(FixedFloat32Array) {
16583 FixedTypedArrayTestHelper<i::FixedFloat32Array, i::FLOAT32_ELEMENTS, float>(
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016584 v8::kExternalFloat32Array,
machenbach@chromium.org5c88bc32014-01-17 08:10:36 +000016585 -500, 500);
16586}
16587
16588
16589THREADED_TEST(FixedFloat64Array) {
16590 FixedTypedArrayTestHelper<i::FixedFloat64Array, i::FLOAT64_ELEMENTS, float>(
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016591 v8::kExternalFloat64Array,
machenbach@chromium.org5c88bc32014-01-17 08:10:36 +000016592 -500, 500);
16593}
16594
16595
danno@chromium.orgf005df62013-04-30 16:36:45 +000016596template <class ExternalArrayClass, class ElementType>
16597static void ExternalArrayTestHelper(v8::ExternalArrayType array_type,
16598 int64_t low,
16599 int64_t high) {
16600 LocalContext context;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000016601 i::Isolate* isolate = CcTest::i_isolate();
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000016602 i::Factory* factory = isolate->factory();
danno@chromium.orgf005df62013-04-30 16:36:45 +000016603 v8::HandleScope scope(context->GetIsolate());
16604 const int kElementCount = 40;
16605 int element_size = ExternalArrayElementSize(array_type);
16606 ElementType* array_data =
16607 static_cast<ElementType*>(malloc(kElementCount * element_size));
16608 i::Handle<ExternalArrayClass> array =
16609 i::Handle<ExternalArrayClass>::cast(
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000016610 factory->NewExternalArray(kElementCount, array_type, array_data));
danno@chromium.orgf005df62013-04-30 16:36:45 +000016611 // Force GC to trigger verification.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000016612 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
danno@chromium.orgf005df62013-04-30 16:36:45 +000016613 for (int i = 0; i < kElementCount; i++) {
16614 array->set(i, static_cast<ElementType>(i));
16615 }
16616 // Force GC to trigger verification.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000016617 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
danno@chromium.orgf005df62013-04-30 16:36:45 +000016618 for (int i = 0; i < kElementCount; i++) {
16619 CHECK_EQ(static_cast<int64_t>(i),
16620 static_cast<int64_t>(array->get_scalar(i)));
16621 CHECK_EQ(static_cast<int64_t>(i), static_cast<int64_t>(array_data[i]));
16622 }
16623
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016624 v8::Handle<v8::Object> obj = v8::Object::New(context->GetIsolate());
danno@chromium.orgf005df62013-04-30 16:36:45 +000016625 i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
16626 // Set the elements to be the external array.
16627 obj->SetIndexedPropertiesToExternalArrayData(array_data,
16628 array_type,
16629 kElementCount);
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +000016630 CHECK_EQ(1,
16631 static_cast<int>(
16632 jsobj->GetElement(isolate, 1)->ToObjectChecked()->Number()));
danno@chromium.orgf005df62013-04-30 16:36:45 +000016633
16634 ObjectWithExternalArrayTestHelper<ExternalArrayClass, ElementType>(
16635 context.local(), obj, kElementCount, array_type, low, high);
16636
16637 v8::Handle<v8::Value> result;
ager@chromium.org3811b432009-10-28 14:53:37 +000016638
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +000016639 // Test more complex manipulations which cause eax to contain values
16640 // that won't be completely overwritten by loads from the arrays.
16641 // This catches bugs in the instructions used for the KeyedLoadIC
16642 // for byte and word types.
16643 {
16644 const int kXSize = 300;
16645 const int kYSize = 300;
16646 const int kLargeElementCount = kXSize * kYSize * 4;
16647 ElementType* large_array_data =
16648 static_cast<ElementType*>(malloc(kLargeElementCount * element_size));
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016649 v8::Handle<v8::Object> large_obj = v8::Object::New(context->GetIsolate());
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +000016650 // Set the elements to be the external array.
16651 large_obj->SetIndexedPropertiesToExternalArrayData(large_array_data,
16652 array_type,
16653 kLargeElementCount);
16654 context->Global()->Set(v8_str("large_array"), large_obj);
16655 // Initialize contents of a few rows.
16656 for (int x = 0; x < 300; x++) {
16657 int row = 0;
16658 int offset = row * 300 * 4;
16659 large_array_data[offset + 4 * x + 0] = (ElementType) 127;
16660 large_array_data[offset + 4 * x + 1] = (ElementType) 0;
16661 large_array_data[offset + 4 * x + 2] = (ElementType) 0;
16662 large_array_data[offset + 4 * x + 3] = (ElementType) 127;
16663 row = 150;
16664 offset = row * 300 * 4;
16665 large_array_data[offset + 4 * x + 0] = (ElementType) 127;
16666 large_array_data[offset + 4 * x + 1] = (ElementType) 0;
16667 large_array_data[offset + 4 * x + 2] = (ElementType) 0;
16668 large_array_data[offset + 4 * x + 3] = (ElementType) 127;
16669 row = 298;
16670 offset = row * 300 * 4;
16671 large_array_data[offset + 4 * x + 0] = (ElementType) 127;
16672 large_array_data[offset + 4 * x + 1] = (ElementType) 0;
16673 large_array_data[offset + 4 * x + 2] = (ElementType) 0;
16674 large_array_data[offset + 4 * x + 3] = (ElementType) 127;
16675 }
16676 // The goal of the code below is to make "offset" large enough
16677 // that the computation of the index (which goes into eax) has
16678 // high bits set which will not be overwritten by a byte or short
16679 // load.
16680 result = CompileRun("var failed = false;"
16681 "var offset = 0;"
16682 "for (var i = 0; i < 300; i++) {"
16683 " if (large_array[4 * i] != 127 ||"
16684 " large_array[4 * i + 1] != 0 ||"
16685 " large_array[4 * i + 2] != 0 ||"
16686 " large_array[4 * i + 3] != 127) {"
16687 " failed = true;"
16688 " }"
16689 "}"
16690 "offset = 150 * 300 * 4;"
16691 "for (var i = 0; i < 300; i++) {"
16692 " if (large_array[offset + 4 * i] != 127 ||"
16693 " large_array[offset + 4 * i + 1] != 0 ||"
16694 " large_array[offset + 4 * i + 2] != 0 ||"
16695 " large_array[offset + 4 * i + 3] != 127) {"
16696 " failed = true;"
16697 " }"
16698 "}"
16699 "offset = 298 * 300 * 4;"
16700 "for (var i = 0; i < 300; i++) {"
16701 " if (large_array[offset + 4 * i] != 127 ||"
16702 " large_array[offset + 4 * i + 1] != 0 ||"
16703 " large_array[offset + 4 * i + 2] != 0 ||"
16704 " large_array[offset + 4 * i + 3] != 127) {"
16705 " failed = true;"
16706 " }"
16707 "}"
16708 "!failed;");
16709 CHECK_EQ(true, result->BooleanValue());
16710 free(large_array_data);
16711 }
16712
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000016713 // The "" property descriptor is overloaded to store information about
16714 // the external array. Ensure that setting and accessing the "" property
16715 // works (it should overwrite the information cached about the external
16716 // array in the DescriptorArray) in various situations.
16717 result = CompileRun("ext_array[''] = 23; ext_array['']");
16718 CHECK_EQ(23, result->Int32Value());
16719
16720 // Property "" set after the external array is associated with the object.
16721 {
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016722 v8::Handle<v8::Object> obj2 = v8::Object::New(context->GetIsolate());
16723 obj2->Set(v8_str("ee_test_field"),
16724 v8::Int32::New(context->GetIsolate(), 256));
16725 obj2->Set(v8_str(""), v8::Int32::New(context->GetIsolate(), 1503));
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000016726 // Set the elements to be the external array.
16727 obj2->SetIndexedPropertiesToExternalArrayData(array_data,
16728 array_type,
16729 kElementCount);
16730 context->Global()->Set(v8_str("ext_array"), obj2);
16731 result = CompileRun("ext_array['']");
16732 CHECK_EQ(1503, result->Int32Value());
16733 }
16734
16735 // Property "" set after the external array is associated with the object.
16736 {
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016737 v8::Handle<v8::Object> obj2 = v8::Object::New(context->GetIsolate());
16738 obj2->Set(v8_str("ee_test_field_2"),
16739 v8::Int32::New(context->GetIsolate(), 256));
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000016740 // Set the elements to be the external array.
16741 obj2->SetIndexedPropertiesToExternalArrayData(array_data,
16742 array_type,
16743 kElementCount);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016744 obj2->Set(v8_str(""), v8::Int32::New(context->GetIsolate(), 1503));
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000016745 context->Global()->Set(v8_str("ext_array"), obj2);
16746 result = CompileRun("ext_array['']");
16747 CHECK_EQ(1503, result->Int32Value());
16748 }
16749
16750 // Should reuse the map from previous test.
16751 {
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016752 v8::Handle<v8::Object> obj2 = v8::Object::New(context->GetIsolate());
16753 obj2->Set(v8_str("ee_test_field_2"),
16754 v8::Int32::New(context->GetIsolate(), 256));
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000016755 // Set the elements to be the external array. Should re-use the map
16756 // from previous test.
16757 obj2->SetIndexedPropertiesToExternalArrayData(array_data,
16758 array_type,
16759 kElementCount);
16760 context->Global()->Set(v8_str("ext_array"), obj2);
16761 result = CompileRun("ext_array['']");
16762 }
16763
16764 // Property "" is a constant function that shouldn't not be interfered with
16765 // when an external array is set.
16766 {
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016767 v8::Handle<v8::Object> obj2 = v8::Object::New(context->GetIsolate());
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000016768 // Start
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016769 obj2->Set(v8_str("ee_test_field3"),
16770 v8::Int32::New(context->GetIsolate(), 256));
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000016771
16772 // Add a constant function to an object.
16773 context->Global()->Set(v8_str("ext_array"), obj2);
16774 result = CompileRun("ext_array[''] = function() {return 1503;};"
16775 "ext_array['']();");
16776
16777 // Add an external array transition to the same map that
16778 // has the constant transition.
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016779 v8::Handle<v8::Object> obj3 = v8::Object::New(context->GetIsolate());
16780 obj3->Set(v8_str("ee_test_field3"),
16781 v8::Int32::New(context->GetIsolate(), 256));
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000016782 obj3->SetIndexedPropertiesToExternalArrayData(array_data,
16783 array_type,
16784 kElementCount);
16785 context->Global()->Set(v8_str("ext_array"), obj3);
16786 }
16787
16788 // If a external array transition is in the map, it should get clobbered
16789 // by a constant function.
16790 {
16791 // Add an external array transition.
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016792 v8::Handle<v8::Object> obj3 = v8::Object::New(context->GetIsolate());
16793 obj3->Set(v8_str("ee_test_field4"),
16794 v8::Int32::New(context->GetIsolate(), 256));
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000016795 obj3->SetIndexedPropertiesToExternalArrayData(array_data,
16796 array_type,
16797 kElementCount);
16798
16799 // Add a constant function to the same map that just got an external array
16800 // transition.
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016801 v8::Handle<v8::Object> obj2 = v8::Object::New(context->GetIsolate());
16802 obj2->Set(v8_str("ee_test_field4"),
16803 v8::Int32::New(context->GetIsolate(), 256));
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000016804 context->Global()->Set(v8_str("ext_array"), obj2);
16805 result = CompileRun("ext_array[''] = function() {return 1503;};"
16806 "ext_array['']();");
16807 }
16808
ager@chromium.org3811b432009-10-28 14:53:37 +000016809 free(array_data);
16810}
16811
16812
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016813THREADED_TEST(ExternalInt8Array) {
16814 ExternalArrayTestHelper<i::ExternalInt8Array, int8_t>(
16815 v8::kExternalInt8Array,
ager@chromium.org3811b432009-10-28 14:53:37 +000016816 -128,
16817 127);
16818}
16819
16820
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016821THREADED_TEST(ExternalUint8Array) {
16822 ExternalArrayTestHelper<i::ExternalUint8Array, uint8_t>(
16823 v8::kExternalUint8Array,
ager@chromium.org3811b432009-10-28 14:53:37 +000016824 0,
16825 255);
16826}
16827
16828
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016829THREADED_TEST(ExternalUint8ClampedArray) {
16830 ExternalArrayTestHelper<i::ExternalUint8ClampedArray, uint8_t>(
16831 v8::kExternalUint8ClampedArray,
danno@chromium.org4d3fe4e2011-03-10 10:14:28 +000016832 0,
16833 255);
16834}
16835
16836
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016837THREADED_TEST(ExternalInt16Array) {
16838 ExternalArrayTestHelper<i::ExternalInt16Array, int16_t>(
16839 v8::kExternalInt16Array,
ager@chromium.org3811b432009-10-28 14:53:37 +000016840 -32768,
16841 32767);
16842}
16843
16844
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016845THREADED_TEST(ExternalUint16Array) {
16846 ExternalArrayTestHelper<i::ExternalUint16Array, uint16_t>(
16847 v8::kExternalUint16Array,
ager@chromium.org3811b432009-10-28 14:53:37 +000016848 0,
16849 65535);
16850}
16851
16852
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016853THREADED_TEST(ExternalInt32Array) {
16854 ExternalArrayTestHelper<i::ExternalInt32Array, int32_t>(
16855 v8::kExternalInt32Array,
ager@chromium.org3811b432009-10-28 14:53:37 +000016856 INT_MIN, // -2147483648
16857 INT_MAX); // 2147483647
16858}
16859
16860
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016861THREADED_TEST(ExternalUint32Array) {
16862 ExternalArrayTestHelper<i::ExternalUint32Array, uint32_t>(
16863 v8::kExternalUint32Array,
ager@chromium.org3811b432009-10-28 14:53:37 +000016864 0,
16865 UINT_MAX); // 4294967295
16866}
16867
16868
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016869THREADED_TEST(ExternalFloat32Array) {
16870 ExternalArrayTestHelper<i::ExternalFloat32Array, float>(
16871 v8::kExternalFloat32Array,
ager@chromium.org3811b432009-10-28 14:53:37 +000016872 -500,
16873 500);
16874}
16875
16876
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016877THREADED_TEST(ExternalFloat64Array) {
16878 ExternalArrayTestHelper<i::ExternalFloat64Array, double>(
16879 v8::kExternalFloat64Array,
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +000016880 -500,
16881 500);
16882}
16883
16884
ager@chromium.org3811b432009-10-28 14:53:37 +000016885THREADED_TEST(ExternalArrays) {
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016886 TestExternalInt8Array();
16887 TestExternalUint8Array();
16888 TestExternalInt16Array();
16889 TestExternalUint16Array();
16890 TestExternalInt32Array();
16891 TestExternalUint32Array();
16892 TestExternalFloat32Array();
ager@chromium.org3811b432009-10-28 14:53:37 +000016893}
16894
16895
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016896void ExternalArrayInfoTestHelper(v8::ExternalArrayType array_type) {
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016897 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000016898 v8::HandleScope scope(context->GetIsolate());
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016899 for (int size = 0; size < 100; size += 10) {
16900 int element_size = ExternalArrayElementSize(array_type);
16901 void* external_data = malloc(size * element_size);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016902 v8::Handle<v8::Object> obj = v8::Object::New(context->GetIsolate());
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016903 obj->SetIndexedPropertiesToExternalArrayData(
16904 external_data, array_type, size);
16905 CHECK(obj->HasIndexedPropertiesInExternalArrayData());
16906 CHECK_EQ(external_data, obj->GetIndexedPropertiesExternalArrayData());
16907 CHECK_EQ(array_type, obj->GetIndexedPropertiesExternalArrayDataType());
16908 CHECK_EQ(size, obj->GetIndexedPropertiesExternalArrayDataLength());
16909 free(external_data);
16910 }
16911}
16912
16913
16914THREADED_TEST(ExternalArrayInfo) {
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016915 ExternalArrayInfoTestHelper(v8::kExternalInt8Array);
16916 ExternalArrayInfoTestHelper(v8::kExternalUint8Array);
16917 ExternalArrayInfoTestHelper(v8::kExternalInt16Array);
16918 ExternalArrayInfoTestHelper(v8::kExternalUint16Array);
16919 ExternalArrayInfoTestHelper(v8::kExternalInt32Array);
16920 ExternalArrayInfoTestHelper(v8::kExternalUint32Array);
16921 ExternalArrayInfoTestHelper(v8::kExternalFloat32Array);
16922 ExternalArrayInfoTestHelper(v8::kExternalFloat64Array);
16923 ExternalArrayInfoTestHelper(v8::kExternalUint8ClampedArray);
whesse@chromium.org2c186ca2010-06-16 11:32:39 +000016924}
16925
16926
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016927void ExtArrayLimitsHelper(v8::Isolate* isolate,
16928 v8::ExternalArrayType array_type,
16929 int size) {
16930 v8::Handle<v8::Object> obj = v8::Object::New(isolate);
danno@chromium.org412fa512012-09-14 13:28:26 +000016931 v8::V8::SetFatalErrorHandler(StoringErrorCallback);
16932 last_location = last_message = NULL;
16933 obj->SetIndexedPropertiesToExternalArrayData(NULL, array_type, size);
16934 CHECK(!obj->HasIndexedPropertiesInExternalArrayData());
16935 CHECK_NE(NULL, last_location);
16936 CHECK_NE(NULL, last_message);
16937}
16938
16939
16940TEST(ExternalArrayLimits) {
danno@chromium.org412fa512012-09-14 13:28:26 +000016941 LocalContext context;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000016942 v8::Isolate* isolate = context->GetIsolate();
16943 v8::HandleScope scope(isolate);
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000016944 ExtArrayLimitsHelper(isolate, v8::kExternalInt8Array, 0x40000000);
16945 ExtArrayLimitsHelper(isolate, v8::kExternalInt8Array, 0xffffffff);
16946 ExtArrayLimitsHelper(isolate, v8::kExternalUint8Array, 0x40000000);
16947 ExtArrayLimitsHelper(isolate, v8::kExternalUint8Array, 0xffffffff);
16948 ExtArrayLimitsHelper(isolate, v8::kExternalInt16Array, 0x40000000);
16949 ExtArrayLimitsHelper(isolate, v8::kExternalInt16Array, 0xffffffff);
16950 ExtArrayLimitsHelper(isolate, v8::kExternalUint16Array, 0x40000000);
16951 ExtArrayLimitsHelper(isolate, v8::kExternalUint16Array, 0xffffffff);
16952 ExtArrayLimitsHelper(isolate, v8::kExternalInt32Array, 0x40000000);
16953 ExtArrayLimitsHelper(isolate, v8::kExternalInt32Array, 0xffffffff);
16954 ExtArrayLimitsHelper(isolate, v8::kExternalUint32Array, 0x40000000);
16955 ExtArrayLimitsHelper(isolate, v8::kExternalUint32Array, 0xffffffff);
16956 ExtArrayLimitsHelper(isolate, v8::kExternalFloat32Array, 0x40000000);
16957 ExtArrayLimitsHelper(isolate, v8::kExternalFloat32Array, 0xffffffff);
16958 ExtArrayLimitsHelper(isolate, v8::kExternalFloat64Array, 0x40000000);
16959 ExtArrayLimitsHelper(isolate, v8::kExternalFloat64Array, 0xffffffff);
16960 ExtArrayLimitsHelper(isolate, v8::kExternalUint8ClampedArray, 0x40000000);
16961 ExtArrayLimitsHelper(isolate, v8::kExternalUint8ClampedArray, 0xffffffff);
danno@chromium.org412fa512012-09-14 13:28:26 +000016962}
16963
16964
danno@chromium.orgf005df62013-04-30 16:36:45 +000016965template <typename ElementType, typename TypedArray,
16966 class ExternalArrayClass>
16967void TypedArrayTestHelper(v8::ExternalArrayType array_type,
16968 int64_t low, int64_t high) {
16969 const int kElementCount = 50;
danno@chromium.orgf005df62013-04-30 16:36:45 +000016970
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +000016971 i::ScopedVector<ElementType> backing_store(kElementCount+2);
16972
danno@chromium.orgf005df62013-04-30 16:36:45 +000016973 LocalContext env;
16974 v8::Isolate* isolate = env->GetIsolate();
16975 v8::HandleScope handle_scope(isolate);
16976
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000016977 Local<v8::ArrayBuffer> ab =
16978 v8::ArrayBuffer::New(isolate, backing_store.start(),
16979 (kElementCount + 2) * sizeof(ElementType));
danno@chromium.orgf005df62013-04-30 16:36:45 +000016980 Local<TypedArray> ta =
16981 TypedArray::New(ab, 2*sizeof(ElementType), kElementCount);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000016982 CheckInternalFieldsAreZero<v8::ArrayBufferView>(ta);
danno@chromium.orgf005df62013-04-30 16:36:45 +000016983 CHECK_EQ(kElementCount, static_cast<int>(ta->Length()));
16984 CHECK_EQ(2*sizeof(ElementType), static_cast<int>(ta->ByteOffset()));
16985 CHECK_EQ(kElementCount*sizeof(ElementType),
16986 static_cast<int>(ta->ByteLength()));
16987 CHECK_EQ(ab, ta->Buffer());
16988
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +000016989 ElementType* data = backing_store.start() + 2;
danno@chromium.orgf005df62013-04-30 16:36:45 +000016990 for (int i = 0; i < kElementCount; i++) {
16991 data[i] = static_cast<ElementType>(i);
16992 }
16993
16994 ObjectWithExternalArrayTestHelper<ExternalArrayClass, ElementType>(
16995 env.local(), ta, kElementCount, array_type, low, high);
16996}
16997
16998
16999THREADED_TEST(Uint8Array) {
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000017000 TypedArrayTestHelper<uint8_t, v8::Uint8Array, i::ExternalUint8Array>(
17001 v8::kExternalUint8Array, 0, 0xFF);
danno@chromium.orgf005df62013-04-30 16:36:45 +000017002}
17003
17004
17005THREADED_TEST(Int8Array) {
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000017006 TypedArrayTestHelper<int8_t, v8::Int8Array, i::ExternalInt8Array>(
17007 v8::kExternalInt8Array, -0x80, 0x7F);
danno@chromium.orgf005df62013-04-30 16:36:45 +000017008}
17009
17010
17011THREADED_TEST(Uint16Array) {
17012 TypedArrayTestHelper<uint16_t,
17013 v8::Uint16Array,
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000017014 i::ExternalUint16Array>(
17015 v8::kExternalUint16Array, 0, 0xFFFF);
danno@chromium.orgf005df62013-04-30 16:36:45 +000017016}
17017
17018
17019THREADED_TEST(Int16Array) {
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000017020 TypedArrayTestHelper<int16_t, v8::Int16Array, i::ExternalInt16Array>(
17021 v8::kExternalInt16Array, -0x8000, 0x7FFF);
danno@chromium.orgf005df62013-04-30 16:36:45 +000017022}
17023
17024
17025THREADED_TEST(Uint32Array) {
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000017026 TypedArrayTestHelper<uint32_t, v8::Uint32Array, i::ExternalUint32Array>(
17027 v8::kExternalUint32Array, 0, UINT_MAX);
danno@chromium.orgf005df62013-04-30 16:36:45 +000017028}
17029
17030
17031THREADED_TEST(Int32Array) {
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000017032 TypedArrayTestHelper<int32_t, v8::Int32Array, i::ExternalInt32Array>(
17033 v8::kExternalInt32Array, INT_MIN, INT_MAX);
danno@chromium.orgf005df62013-04-30 16:36:45 +000017034}
17035
17036
17037THREADED_TEST(Float32Array) {
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000017038 TypedArrayTestHelper<float, v8::Float32Array, i::ExternalFloat32Array>(
17039 v8::kExternalFloat32Array, -500, 500);
danno@chromium.orgf005df62013-04-30 16:36:45 +000017040}
17041
17042
17043THREADED_TEST(Float64Array) {
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000017044 TypedArrayTestHelper<double, v8::Float64Array, i::ExternalFloat64Array>(
17045 v8::kExternalFloat64Array, -500, 500);
danno@chromium.orgf005df62013-04-30 16:36:45 +000017046}
17047
17048
ulan@chromium.org57ff8812013-05-10 08:16:55 +000017049THREADED_TEST(Uint8ClampedArray) {
machenbach@chromium.orgaf4fba32014-01-27 01:05:32 +000017050 TypedArrayTestHelper<uint8_t,
17051 v8::Uint8ClampedArray, i::ExternalUint8ClampedArray>(
17052 v8::kExternalUint8ClampedArray, 0, 0xFF);
ulan@chromium.org57ff8812013-05-10 08:16:55 +000017053}
17054
17055
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000017056THREADED_TEST(DataView) {
17057 const int kSize = 50;
17058
17059 i::ScopedVector<uint8_t> backing_store(kSize+2);
17060
17061 LocalContext env;
17062 v8::Isolate* isolate = env->GetIsolate();
17063 v8::HandleScope handle_scope(isolate);
17064
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000017065 Local<v8::ArrayBuffer> ab =
17066 v8::ArrayBuffer::New(isolate, backing_store.start(), 2 + kSize);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000017067 Local<v8::DataView> dv =
17068 v8::DataView::New(ab, 2, kSize);
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000017069 CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000017070 CHECK_EQ(2, static_cast<int>(dv->ByteOffset()));
17071 CHECK_EQ(kSize, static_cast<int>(dv->ByteLength()));
17072 CHECK_EQ(ab, dv->Buffer());
17073}
17074
17075
17076#define IS_ARRAY_BUFFER_VIEW_TEST(View) \
17077 THREADED_TEST(Is##View) { \
ulan@chromium.org57ff8812013-05-10 08:16:55 +000017078 LocalContext env; \
17079 v8::Isolate* isolate = env->GetIsolate(); \
17080 v8::HandleScope handle_scope(isolate); \
17081 \
17082 Handle<Value> result = CompileRun( \
17083 "var ab = new ArrayBuffer(128);" \
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000017084 "new " #View "(ab)"); \
17085 CHECK(result->IsArrayBufferView()); \
17086 CHECK(result->Is##View()); \
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000017087 CheckInternalFieldsAreZero<v8::ArrayBufferView>(result.As<v8::View>()); \
ulan@chromium.org57ff8812013-05-10 08:16:55 +000017088 }
17089
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000017090IS_ARRAY_BUFFER_VIEW_TEST(Uint8Array)
17091IS_ARRAY_BUFFER_VIEW_TEST(Int8Array)
17092IS_ARRAY_BUFFER_VIEW_TEST(Uint16Array)
17093IS_ARRAY_BUFFER_VIEW_TEST(Int16Array)
17094IS_ARRAY_BUFFER_VIEW_TEST(Uint32Array)
17095IS_ARRAY_BUFFER_VIEW_TEST(Int32Array)
17096IS_ARRAY_BUFFER_VIEW_TEST(Float32Array)
17097IS_ARRAY_BUFFER_VIEW_TEST(Float64Array)
17098IS_ARRAY_BUFFER_VIEW_TEST(Uint8ClampedArray)
17099IS_ARRAY_BUFFER_VIEW_TEST(DataView)
ulan@chromium.org57ff8812013-05-10 08:16:55 +000017100
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000017101#undef IS_ARRAY_BUFFER_VIEW_TEST
ulan@chromium.org57ff8812013-05-10 08:16:55 +000017102
17103
17104
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000017105THREADED_TEST(ScriptContextDependence) {
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000017106 LocalContext c1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017107 v8::HandleScope scope(c1->GetIsolate());
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000017108 const char *source = "foo";
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000017109 v8::Handle<v8::Script> dep =
17110 v8::Script::Compile(v8::String::NewFromUtf8(c1->GetIsolate(), source));
17111 v8::Handle<v8::Script> indep =
17112 v8::Script::New(v8::String::NewFromUtf8(c1->GetIsolate(), source));
17113 c1->Global()->Set(v8::String::NewFromUtf8(c1->GetIsolate(), "foo"),
ulan@chromium.org0f13e742014-01-03 15:51:11 +000017114 v8::Integer::New(c1->GetIsolate(), 100));
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000017115 CHECK_EQ(dep->Run()->Int32Value(), 100);
17116 CHECK_EQ(indep->Run()->Int32Value(), 100);
17117 LocalContext c2;
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000017118 c2->Global()->Set(v8::String::NewFromUtf8(c2->GetIsolate(), "foo"),
ulan@chromium.org0f13e742014-01-03 15:51:11 +000017119 v8::Integer::New(c2->GetIsolate(), 101));
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000017120 CHECK_EQ(dep->Run()->Int32Value(), 100);
17121 CHECK_EQ(indep->Run()->Int32Value(), 101);
17122}
17123
ager@chromium.org96c75b52009-08-26 09:13:16 +000017124
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000017125THREADED_TEST(StackTrace) {
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000017126 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017127 v8::HandleScope scope(context->GetIsolate());
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000017128 v8::TryCatch try_catch;
17129 const char *source = "function foo() { FAIL.FAIL; }; foo();";
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000017130 v8::Handle<v8::String> src =
17131 v8::String::NewFromUtf8(context->GetIsolate(), source);
17132 v8::Handle<v8::String> origin =
17133 v8::String::NewFromUtf8(context->GetIsolate(), "stack-trace-test");
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000017134 v8::Script::New(src, origin)->Run();
17135 CHECK(try_catch.HasCaught());
17136 v8::String::Utf8Value stack(try_catch.StackTrace());
17137 CHECK(strstr(*stack, "at foo (stack-trace-test") != NULL);
17138}
ager@chromium.org96c75b52009-08-26 09:13:16 +000017139
17140
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017141// Checks that a StackFrame has certain expected values.
17142void checkStackFrame(const char* expected_script_name,
17143 const char* expected_func_name, int expected_line_number,
17144 int expected_column, bool is_eval, bool is_constructor,
17145 v8::Handle<v8::StackFrame> frame) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017146 v8::HandleScope scope(CcTest::isolate());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017147 v8::String::Utf8Value func_name(frame->GetFunctionName());
17148 v8::String::Utf8Value script_name(frame->GetScriptName());
17149 if (*script_name == NULL) {
17150 // The situation where there is no associated script, like for evals.
17151 CHECK(expected_script_name == NULL);
17152 } else {
17153 CHECK(strstr(*script_name, expected_script_name) != NULL);
17154 }
17155 CHECK(strstr(*func_name, expected_func_name) != NULL);
17156 CHECK_EQ(expected_line_number, frame->GetLineNumber());
17157 CHECK_EQ(expected_column, frame->GetColumn());
17158 CHECK_EQ(is_eval, frame->IsEval());
17159 CHECK_EQ(is_constructor, frame->IsConstructor());
17160}
17161
17162
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000017163void AnalyzeStackInNativeCode(const v8::FunctionCallbackInfo<v8::Value>& args) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017164 v8::HandleScope scope(args.GetIsolate());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017165 const char* origin = "capture-stack-trace-test";
17166 const int kOverviewTest = 1;
17167 const int kDetailedTest = 2;
17168
17169 ASSERT(args.Length() == 1);
17170
17171 int testGroup = args[0]->Int32Value();
17172 if (testGroup == kOverviewTest) {
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000017173 v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
17174 args.GetIsolate(), 10, v8::StackTrace::kOverview);
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017175 CHECK_EQ(4, stackTrace->GetFrameCount());
17176 checkStackFrame(origin, "bar", 2, 10, false, false,
17177 stackTrace->GetFrame(0));
17178 checkStackFrame(origin, "foo", 6, 3, false, false,
17179 stackTrace->GetFrame(1));
whesse@chromium.org030d38e2011-07-13 13:23:34 +000017180 // This is the source string inside the eval which has the call to foo.
17181 checkStackFrame(NULL, "", 1, 5, false, false,
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017182 stackTrace->GetFrame(2));
whesse@chromium.org030d38e2011-07-13 13:23:34 +000017183 // The last frame is an anonymous function which has the initial eval call.
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017184 checkStackFrame(origin, "", 8, 7, false, false,
17185 stackTrace->GetFrame(3));
17186
17187 CHECK(stackTrace->AsArray()->IsArray());
17188 } else if (testGroup == kDetailedTest) {
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000017189 v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
17190 args.GetIsolate(), 10, v8::StackTrace::kDetailed);
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017191 CHECK_EQ(4, stackTrace->GetFrameCount());
17192 checkStackFrame(origin, "bat", 4, 22, false, false,
17193 stackTrace->GetFrame(0));
17194 checkStackFrame(origin, "baz", 8, 3, false, true,
17195 stackTrace->GetFrame(1));
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +000017196#ifdef ENABLE_DEBUGGER_SUPPORT
17197 bool is_eval = true;
17198#else // ENABLE_DEBUGGER_SUPPORT
17199 bool is_eval = false;
17200#endif // ENABLE_DEBUGGER_SUPPORT
17201
whesse@chromium.org030d38e2011-07-13 13:23:34 +000017202 // This is the source string inside the eval which has the call to baz.
17203 checkStackFrame(NULL, "", 1, 5, is_eval, false,
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017204 stackTrace->GetFrame(2));
whesse@chromium.org030d38e2011-07-13 13:23:34 +000017205 // The last frame is an anonymous function which has the initial eval call.
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017206 checkStackFrame(origin, "", 10, 1, false, false,
17207 stackTrace->GetFrame(3));
17208
17209 CHECK(stackTrace->AsArray()->IsArray());
17210 }
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017211}
17212
17213
17214// Tests the C++ StackTrace API.
kasperl@chromium.orga5551262010-12-07 12:49:48 +000017215// TODO(3074796): Reenable this as a THREADED_TEST once it passes.
17216// THREADED_TEST(CaptureStackTrace) {
17217TEST(CaptureStackTrace) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017218 v8::Isolate* isolate = CcTest::isolate();
17219 v8::HandleScope scope(isolate);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000017220 v8::Handle<v8::String> origin =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017221 v8::String::NewFromUtf8(isolate, "capture-stack-trace-test");
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000017222 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017223 templ->Set(v8_str("AnalyzeStackInNativeCode"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017224 v8::FunctionTemplate::New(isolate, AnalyzeStackInNativeCode));
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017225 LocalContext context(0, templ);
17226
17227 // Test getting OVERVIEW information. Should ignore information that is not
17228 // script name, function name, line number, and column offset.
17229 const char *overview_source =
17230 "function bar() {\n"
17231 " var y; AnalyzeStackInNativeCode(1);\n"
17232 "}\n"
17233 "function foo() {\n"
17234 "\n"
17235 " bar();\n"
17236 "}\n"
17237 "var x;eval('new foo();');";
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000017238 v8::Handle<v8::String> overview_src =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017239 v8::String::NewFromUtf8(isolate, overview_source);
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000017240 v8::Handle<Value> overview_result(
17241 v8::Script::New(overview_src, origin)->Run());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000017242 CHECK(!overview_result.IsEmpty());
17243 CHECK(overview_result->IsObject());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017244
17245 // Test getting DETAILED information.
17246 const char *detailed_source =
17247 "function bat() {AnalyzeStackInNativeCode(2);\n"
17248 "}\n"
17249 "\n"
17250 "function baz() {\n"
17251 " bat();\n"
17252 "}\n"
17253 "eval('new baz();');";
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000017254 v8::Handle<v8::String> detailed_src =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017255 v8::String::NewFromUtf8(isolate, detailed_source);
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017256 // Make the script using a non-zero line and column offset.
ulan@chromium.org0f13e742014-01-03 15:51:11 +000017257 v8::Handle<v8::Integer> line_offset = v8::Integer::New(isolate, 3);
17258 v8::Handle<v8::Integer> column_offset = v8::Integer::New(isolate, 5);
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017259 v8::ScriptOrigin detailed_origin(origin, line_offset, column_offset);
17260 v8::Handle<v8::Script> detailed_script(
17261 v8::Script::New(detailed_src, &detailed_origin));
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000017262 v8::Handle<Value> detailed_result(detailed_script->Run());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000017263 CHECK(!detailed_result.IsEmpty());
17264 CHECK(detailed_result->IsObject());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000017265}
17266
17267
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000017268static void StackTraceForUncaughtExceptionListener(
17269 v8::Handle<v8::Message> message,
17270 v8::Handle<Value>) {
17271 v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
17272 CHECK_EQ(2, stack_trace->GetFrameCount());
17273 checkStackFrame("origin", "foo", 2, 3, false, false,
17274 stack_trace->GetFrame(0));
17275 checkStackFrame("origin", "bar", 5, 3, false, false,
17276 stack_trace->GetFrame(1));
17277}
17278
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000017279
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000017280TEST(CaptureStackTraceForUncaughtException) {
17281 report_count = 0;
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000017282 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017283 v8::HandleScope scope(env->GetIsolate());
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +000017284 v8::V8::AddMessageListener(StackTraceForUncaughtExceptionListener);
17285 v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
17286
17287 Script::Compile(v8_str("function foo() {\n"
17288 " throw 1;\n"
17289 "};\n"
17290 "function bar() {\n"
17291 " foo();\n"
17292 "};"),
17293 v8_str("origin"))->Run();
17294 v8::Local<v8::Object> global = env->Global();
17295 Local<Value> trouble = global->Get(v8_str("bar"));
17296 CHECK(trouble->IsFunction());
17297 Function::Cast(*trouble)->Call(global, 0, NULL);
17298 v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
17299 v8::V8::RemoveMessageListeners(StackTraceForUncaughtExceptionListener);
17300}
17301
17302
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000017303TEST(CaptureStackTraceForUncaughtExceptionAndSetters) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000017304 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017305 v8::HandleScope scope(env->GetIsolate());
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000017306 v8::V8::SetCaptureStackTraceForUncaughtExceptions(true,
17307 1024,
17308 v8::StackTrace::kDetailed);
17309
17310 CompileRun(
17311 "var setters = ['column', 'lineNumber', 'scriptName',\n"
17312 " 'scriptNameOrSourceURL', 'functionName', 'isEval',\n"
17313 " 'isConstructor'];\n"
17314 "for (var i = 0; i < setters.length; i++) {\n"
17315 " var prop = setters[i];\n"
17316 " Object.prototype.__defineSetter__(prop, function() { throw prop; });\n"
17317 "}\n");
17318 CompileRun("throw 'exception';");
17319 v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
17320}
17321
17322
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000017323static void RethrowStackTraceHandler(v8::Handle<v8::Message> message,
17324 v8::Handle<v8::Value> data) {
17325 // Use the frame where JavaScript is called from.
17326 v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
17327 CHECK(!stack_trace.IsEmpty());
17328 int frame_count = stack_trace->GetFrameCount();
17329 CHECK_EQ(3, frame_count);
17330 int line_number[] = {1, 2, 5};
17331 for (int i = 0; i < frame_count; i++) {
17332 CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber());
17333 }
17334}
17335
17336
17337// Test that we only return the stack trace at the site where the exception
17338// is first thrown (not where it is rethrown).
17339TEST(RethrowStackTrace) {
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000017340 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017341 v8::HandleScope scope(env->GetIsolate());
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000017342 // We make sure that
17343 // - the stack trace of the ReferenceError in g() is reported.
17344 // - the stack trace is not overwritten when e1 is rethrown by t().
17345 // - the stack trace of e2 does not overwrite that of e1.
17346 const char* source =
17347 "function g() { error; } \n"
17348 "function f() { g(); } \n"
17349 "function t(e) { throw e; } \n"
17350 "try { \n"
17351 " f(); \n"
17352 "} catch (e1) { \n"
17353 " try { \n"
17354 " error; \n"
17355 " } catch (e2) { \n"
17356 " t(e1); \n"
17357 " } \n"
17358 "} \n";
17359 v8::V8::AddMessageListener(RethrowStackTraceHandler);
17360 v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
17361 CompileRun(source);
17362 v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
17363 v8::V8::RemoveMessageListeners(RethrowStackTraceHandler);
17364}
17365
17366
17367static void RethrowPrimitiveStackTraceHandler(v8::Handle<v8::Message> message,
17368 v8::Handle<v8::Value> data) {
17369 v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
17370 CHECK(!stack_trace.IsEmpty());
17371 int frame_count = stack_trace->GetFrameCount();
17372 CHECK_EQ(2, frame_count);
17373 int line_number[] = {3, 7};
17374 for (int i = 0; i < frame_count; i++) {
17375 CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber());
17376 }
17377}
17378
17379
17380// Test that we do not recognize identity for primitive exceptions.
17381TEST(RethrowPrimitiveStackTrace) {
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000017382 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017383 v8::HandleScope scope(env->GetIsolate());
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000017384 // We do not capture stack trace for non Error objects on creation time.
17385 // Instead, we capture the stack trace on last throw.
17386 const char* source =
17387 "function g() { throw 404; } \n"
17388 "function f() { g(); } \n"
17389 "function t(e) { throw e; } \n"
17390 "try { \n"
17391 " f(); \n"
17392 "} catch (e1) { \n"
17393 " t(e1) \n"
17394 "} \n";
17395 v8::V8::AddMessageListener(RethrowPrimitiveStackTraceHandler);
17396 v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
17397 CompileRun(source);
17398 v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
17399 v8::V8::RemoveMessageListeners(RethrowPrimitiveStackTraceHandler);
17400}
17401
17402
17403static void RethrowExistingStackTraceHandler(v8::Handle<v8::Message> message,
17404 v8::Handle<v8::Value> data) {
17405 // Use the frame where JavaScript is called from.
17406 v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
17407 CHECK(!stack_trace.IsEmpty());
17408 CHECK_EQ(1, stack_trace->GetFrameCount());
17409 CHECK_EQ(1, stack_trace->GetFrame(0)->GetLineNumber());
17410}
17411
17412
17413// Test that the stack trace is captured when the error object is created and
17414// not where it is thrown.
17415TEST(RethrowExistingStackTrace) {
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000017416 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017417 v8::HandleScope scope(env->GetIsolate());
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000017418 const char* source =
17419 "var e = new Error(); \n"
17420 "throw e; \n";
17421 v8::V8::AddMessageListener(RethrowExistingStackTraceHandler);
17422 v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
17423 CompileRun(source);
17424 v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
17425 v8::V8::RemoveMessageListeners(RethrowExistingStackTraceHandler);
17426}
17427
17428
17429static void RethrowBogusErrorStackTraceHandler(v8::Handle<v8::Message> message,
17430 v8::Handle<v8::Value> data) {
17431 // Use the frame where JavaScript is called from.
17432 v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
17433 CHECK(!stack_trace.IsEmpty());
17434 CHECK_EQ(1, stack_trace->GetFrameCount());
17435 CHECK_EQ(2, stack_trace->GetFrame(0)->GetLineNumber());
17436}
17437
17438
17439// Test that the stack trace is captured where the bogus Error object is thrown.
17440TEST(RethrowBogusErrorStackTrace) {
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000017441 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017442 v8::HandleScope scope(env->GetIsolate());
jkummerow@chromium.orgab7dad42012-02-07 12:07:34 +000017443 const char* source =
17444 "var e = {__proto__: new Error()} \n"
17445 "throw e; \n";
17446 v8::V8::AddMessageListener(RethrowBogusErrorStackTraceHandler);
17447 v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
17448 CompileRun(source);
17449 v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
17450 v8::V8::RemoveMessageListeners(RethrowBogusErrorStackTraceHandler);
17451}
17452
17453
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000017454void AnalyzeStackOfEvalWithSourceURL(
17455 const v8::FunctionCallbackInfo<v8::Value>& args) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017456 v8::HandleScope scope(args.GetIsolate());
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000017457 v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
17458 args.GetIsolate(), 10, v8::StackTrace::kDetailed);
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000017459 CHECK_EQ(5, stackTrace->GetFrameCount());
17460 v8::Handle<v8::String> url = v8_str("eval_url");
17461 for (int i = 0; i < 3; i++) {
17462 v8::Handle<v8::String> name =
17463 stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
17464 CHECK(!name.IsEmpty());
17465 CHECK_EQ(url, name);
17466 }
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000017467}
17468
17469
17470TEST(SourceURLInStackTrace) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017471 v8::Isolate* isolate = CcTest::isolate();
17472 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000017473 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000017474 templ->Set(v8_str("AnalyzeStackOfEvalWithSourceURL"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017475 v8::FunctionTemplate::New(isolate,
17476 AnalyzeStackOfEvalWithSourceURL));
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000017477 LocalContext context(0, templ);
17478
17479 const char *source =
17480 "function outer() {\n"
17481 "function bar() {\n"
17482 " AnalyzeStackOfEvalWithSourceURL();\n"
17483 "}\n"
17484 "function foo() {\n"
17485 "\n"
17486 " bar();\n"
17487 "}\n"
17488 "foo();\n"
17489 "}\n"
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000017490 "eval('(' + outer +')()%s');";
17491
17492 i::ScopedVector<char> code(1024);
17493 i::OS::SNPrintF(code, source, "//# sourceURL=eval_url");
17494 CHECK(CompileRun(code.start())->IsUndefined());
17495 i::OS::SNPrintF(code, source, "//@ sourceURL=eval_url");
17496 CHECK(CompileRun(code.start())->IsUndefined());
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000017497}
17498
17499
jkummerow@chromium.org8fa5bd92013-09-02 11:45:09 +000017500static int scriptIdInStack[2];
17501
17502void AnalyzeScriptIdInStack(
17503 const v8::FunctionCallbackInfo<v8::Value>& args) {
17504 v8::HandleScope scope(args.GetIsolate());
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000017505 v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
17506 args.GetIsolate(), 10, v8::StackTrace::kScriptId);
jkummerow@chromium.org8fa5bd92013-09-02 11:45:09 +000017507 CHECK_EQ(2, stackTrace->GetFrameCount());
17508 for (int i = 0; i < 2; i++) {
17509 scriptIdInStack[i] = stackTrace->GetFrame(i)->GetScriptId();
17510 }
17511}
17512
17513
17514TEST(ScriptIdInStackTrace) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017515 v8::Isolate* isolate = CcTest::isolate();
17516 v8::HandleScope scope(isolate);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000017517 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
jkummerow@chromium.org8fa5bd92013-09-02 11:45:09 +000017518 templ->Set(v8_str("AnalyzeScriptIdInStack"),
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017519 v8::FunctionTemplate::New(isolate, AnalyzeScriptIdInStack));
jkummerow@chromium.org8fa5bd92013-09-02 11:45:09 +000017520 LocalContext context(0, templ);
17521
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000017522 v8::Handle<v8::String> scriptSource = v8::String::NewFromUtf8(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017523 isolate,
jkummerow@chromium.org8fa5bd92013-09-02 11:45:09 +000017524 "function foo() {\n"
17525 " AnalyzeScriptIdInStack();"
17526 "}\n"
17527 "foo();\n");
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000017528 v8::ScriptOrigin origin =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017529 v8::ScriptOrigin(v8::String::NewFromUtf8(isolate, "test"));
jkummerow@chromium.org8fa5bd92013-09-02 11:45:09 +000017530 v8::Local<v8::Script> script(v8::Script::Compile(scriptSource, &origin));
17531 script->Run();
17532 for (int i = 0; i < 2; i++) {
17533 CHECK(scriptIdInStack[i] != v8::Message::kNoScriptIdInfo);
17534 CHECK_EQ(scriptIdInStack[i], script->GetId());
17535 }
17536}
17537
17538
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000017539void AnalyzeStackOfInlineScriptWithSourceURL(
17540 const v8::FunctionCallbackInfo<v8::Value>& args) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017541 v8::HandleScope scope(args.GetIsolate());
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000017542 v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
17543 args.GetIsolate(), 10, v8::StackTrace::kDetailed);
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000017544 CHECK_EQ(4, stackTrace->GetFrameCount());
17545 v8::Handle<v8::String> url = v8_str("url");
17546 for (int i = 0; i < 3; i++) {
17547 v8::Handle<v8::String> name =
17548 stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
17549 CHECK(!name.IsEmpty());
17550 CHECK_EQ(url, name);
17551 }
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000017552}
17553
17554
17555TEST(InlineScriptWithSourceURLInStackTrace) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000017556 v8::Isolate* isolate = CcTest::isolate();
17557 v8::HandleScope scope(isolate);
17558 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000017559 templ->Set(v8_str("AnalyzeStackOfInlineScriptWithSourceURL"),
17560 v8::FunctionTemplate::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017561 CcTest::isolate(), AnalyzeStackOfInlineScriptWithSourceURL));
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000017562 LocalContext context(0, templ);
17563
17564 const char *source =
17565 "function outer() {\n"
17566 "function bar() {\n"
17567 " AnalyzeStackOfInlineScriptWithSourceURL();\n"
17568 "}\n"
17569 "function foo() {\n"
17570 "\n"
17571 " bar();\n"
17572 "}\n"
17573 "foo();\n"
17574 "}\n"
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000017575 "outer()\n%s";
17576
17577 i::ScopedVector<char> code(1024);
17578 i::OS::SNPrintF(code, source, "//# sourceURL=source_url");
17579 CHECK(CompileRunWithOrigin(code.start(), "url", 0, 1)->IsUndefined());
17580 i::OS::SNPrintF(code, source, "//@ sourceURL=source_url");
17581 CHECK(CompileRunWithOrigin(code.start(), "url", 0, 1)->IsUndefined());
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000017582}
17583
17584
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000017585void AnalyzeStackOfDynamicScriptWithSourceURL(
17586 const v8::FunctionCallbackInfo<v8::Value>& args) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017587 v8::HandleScope scope(args.GetIsolate());
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000017588 v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
17589 args.GetIsolate(), 10, v8::StackTrace::kDetailed);
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000017590 CHECK_EQ(4, stackTrace->GetFrameCount());
17591 v8::Handle<v8::String> url = v8_str("source_url");
17592 for (int i = 0; i < 3; i++) {
17593 v8::Handle<v8::String> name =
17594 stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
17595 CHECK(!name.IsEmpty());
17596 CHECK_EQ(url, name);
17597 }
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000017598}
17599
17600
17601TEST(DynamicWithSourceURLInStackTrace) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000017602 v8::Isolate* isolate = CcTest::isolate();
17603 v8::HandleScope scope(isolate);
17604 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000017605 templ->Set(v8_str("AnalyzeStackOfDynamicScriptWithSourceURL"),
17606 v8::FunctionTemplate::New(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017607 CcTest::isolate(), AnalyzeStackOfDynamicScriptWithSourceURL));
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000017608 LocalContext context(0, templ);
17609
17610 const char *source =
17611 "function outer() {\n"
17612 "function bar() {\n"
17613 " AnalyzeStackOfDynamicScriptWithSourceURL();\n"
17614 "}\n"
17615 "function foo() {\n"
17616 "\n"
17617 " bar();\n"
17618 "}\n"
17619 "foo();\n"
17620 "}\n"
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000017621 "outer()\n%s";
17622
17623 i::ScopedVector<char> code(1024);
17624 i::OS::SNPrintF(code, source, "//# sourceURL=source_url");
17625 CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined());
17626 i::OS::SNPrintF(code, source, "//@ sourceURL=source_url");
17627 CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined());
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000017628}
17629
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000017630
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017631static void CreateGarbageInOldSpace() {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017632 i::Factory* factory = CcTest::i_isolate()->factory();
17633 v8::HandleScope scope(CcTest::isolate());
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017634 i::AlwaysAllocateScope always_allocate;
17635 for (int i = 0; i < 1000; i++) {
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000017636 factory->NewFixedArray(1000, i::TENURED);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017637 }
svenpanne@chromium.orgecb9dd62011-12-01 08:22:35 +000017638}
17639
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000017640
svenpanne@chromium.orgecb9dd62011-12-01 08:22:35 +000017641// Test that idle notification can be handled and eventually returns true.
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017642TEST(IdleNotification) {
17643 const intptr_t MB = 1024 * 1024;
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017644 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017645 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017646 intptr_t initial_size = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017647 CreateGarbageInOldSpace();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017648 intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017649 CHECK_GT(size_with_garbage, initial_size + MB);
17650 bool finished = false;
17651 for (int i = 0; i < 200 && !finished; i++) {
17652 finished = v8::V8::IdleNotification();
17653 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017654 intptr_t final_size = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017655 CHECK(finished);
17656 CHECK_LT(final_size, initial_size + 1);
17657}
17658
17659
17660// Test that idle notification can be handled and eventually collects garbage.
yangguo@chromium.org56454712012-02-16 15:33:53 +000017661TEST(IdleNotificationWithSmallHint) {
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017662 const intptr_t MB = 1024 * 1024;
17663 const int IdlePauseInMs = 900;
svenpanne@chromium.orgecb9dd62011-12-01 08:22:35 +000017664 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017665 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017666 intptr_t initial_size = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017667 CreateGarbageInOldSpace();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017668 intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017669 CHECK_GT(size_with_garbage, initial_size + MB);
17670 bool finished = false;
17671 for (int i = 0; i < 200 && !finished; i++) {
17672 finished = v8::V8::IdleNotification(IdlePauseInMs);
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017673 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017674 intptr_t final_size = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017675 CHECK(finished);
17676 CHECK_LT(final_size, initial_size + 1);
yangguo@chromium.org56454712012-02-16 15:33:53 +000017677}
17678
17679
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017680// Test that idle notification can be handled and eventually collects garbage.
yangguo@chromium.org56454712012-02-16 15:33:53 +000017681TEST(IdleNotificationWithLargeHint) {
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017682 const intptr_t MB = 1024 * 1024;
17683 const int IdlePauseInMs = 900;
yangguo@chromium.org56454712012-02-16 15:33:53 +000017684 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017685 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017686 intptr_t initial_size = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017687 CreateGarbageInOldSpace();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017688 intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017689 CHECK_GT(size_with_garbage, initial_size + MB);
17690 bool finished = false;
17691 for (int i = 0; i < 200 && !finished; i++) {
17692 finished = v8::V8::IdleNotification(IdlePauseInMs);
yangguo@chromium.org56454712012-02-16 15:33:53 +000017693 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017694 intptr_t final_size = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017695 CHECK(finished);
17696 CHECK_LT(final_size, initial_size + 1);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017697}
17698
17699
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017700TEST(Regress2107) {
17701 const intptr_t MB = 1024 * 1024;
17702 const int kShortIdlePauseInMs = 100;
17703 const int kLongIdlePauseInMs = 1000;
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017704 LocalContext env;
ulan@chromium.org57ff8812013-05-10 08:16:55 +000017705 v8::Isolate* isolate = env->GetIsolate();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017706 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017707 intptr_t initial_size = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017708 // Send idle notification to start a round of incremental GCs.
17709 v8::V8::IdleNotification(kShortIdlePauseInMs);
17710 // Emulate 7 page reloads.
17711 for (int i = 0; i < 7; i++) {
ulan@chromium.org57ff8812013-05-10 08:16:55 +000017712 {
17713 v8::HandleScope inner_scope(env->GetIsolate());
17714 v8::Local<v8::Context> ctx = v8::Context::New(isolate);
17715 ctx->Enter();
17716 CreateGarbageInOldSpace();
17717 ctx->Exit();
17718 }
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017719 v8::V8::ContextDisposedNotification();
17720 v8::V8::IdleNotification(kLongIdlePauseInMs);
17721 }
17722 // Create garbage and check that idle notification still collects it.
17723 CreateGarbageInOldSpace();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017724 intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017725 CHECK_GT(size_with_garbage, initial_size + MB);
17726 bool finished = false;
17727 for (int i = 0; i < 200 && !finished; i++) {
17728 finished = v8::V8::IdleNotification(kShortIdlePauseInMs);
17729 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017730 intptr_t final_size = CcTest::heap()->SizeOfObjects();
danno@chromium.org2c26cb12012-05-03 09:06:43 +000017731 CHECK_LT(final_size, initial_size + 1);
17732}
17733
machenbach@chromium.orgb5be0a92013-11-15 10:32:41 +000017734
17735TEST(Regress2333) {
17736 LocalContext env;
17737 for (int i = 0; i < 3; i++) {
17738 CcTest::heap()->PerformScavenge();
17739 }
17740}
17741
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017742static uint32_t* stack_limit;
17743
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000017744static void GetStackLimitCallback(
17745 const v8::FunctionCallbackInfo<v8::Value>& args) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000017746 stack_limit = reinterpret_cast<uint32_t*>(
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017747 CcTest::i_isolate()->stack_guard()->real_climit());
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017748}
17749
17750
17751// Uses the address of a local variable to determine the stack top now.
17752// Given a size, returns an address that is that far from the current
17753// top of stack.
17754static uint32_t* ComputeStackLimit(uint32_t size) {
17755 uint32_t* answer = &size - (size / sizeof(size));
17756 // If the size is very large and the stack is very near the bottom of
17757 // memory then the calculation above may wrap around and give an address
17758 // that is above the (downwards-growing) stack. In that case we return
17759 // a very low address.
17760 if (answer > &size) return reinterpret_cast<uint32_t*>(sizeof(size));
17761 return answer;
17762}
17763
17764
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +000017765// We need at least 165kB for an x64 debug build with clang and ASAN.
17766static const int stack_breathing_room = 256 * i::KB;
17767
17768
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017769TEST(SetResourceConstraints) {
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +000017770 uint32_t* set_limit = ComputeStackLimit(stack_breathing_room);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017771
17772 // Set stack limit.
17773 v8::ResourceConstraints constraints;
17774 constraints.set_stack_limit(set_limit);
machenbach@chromium.org7ff76072013-11-21 09:47:43 +000017775 CHECK(v8::SetResourceConstraints(CcTest::isolate(), &constraints));
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017776
17777 // Execute a script.
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017778 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017779 v8::HandleScope scope(env->GetIsolate());
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017780 Local<v8::FunctionTemplate> fun_templ =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017781 v8::FunctionTemplate::New(env->GetIsolate(), GetStackLimitCallback);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017782 Local<Function> fun = fun_templ->GetFunction();
17783 env->Global()->Set(v8_str("get_stack_limit"), fun);
17784 CompileRun("get_stack_limit();");
17785
17786 CHECK(stack_limit == set_limit);
17787}
17788
17789
17790TEST(SetResourceConstraintsInThread) {
17791 uint32_t* set_limit;
17792 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017793 v8::Locker locker(CcTest::isolate());
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +000017794 set_limit = ComputeStackLimit(stack_breathing_room);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017795
17796 // Set stack limit.
17797 v8::ResourceConstraints constraints;
17798 constraints.set_stack_limit(set_limit);
machenbach@chromium.org7ff76072013-11-21 09:47:43 +000017799 CHECK(v8::SetResourceConstraints(CcTest::isolate(), &constraints));
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017800
17801 // Execute a script.
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017802 v8::HandleScope scope(CcTest::isolate());
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017803 LocalContext env;
17804 Local<v8::FunctionTemplate> fun_templ =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000017805 v8::FunctionTemplate::New(CcTest::isolate(), GetStackLimitCallback);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017806 Local<Function> fun = fun_templ->GetFunction();
17807 env->Global()->Set(v8_str("get_stack_limit"), fun);
17808 CompileRun("get_stack_limit();");
17809
17810 CHECK(stack_limit == set_limit);
17811 }
17812 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017813 v8::Locker locker(CcTest::isolate());
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000017814 CHECK(stack_limit == set_limit);
17815 }
ager@chromium.org96c75b52009-08-26 09:13:16 +000017816}
ager@chromium.org3811b432009-10-28 14:53:37 +000017817
17818
17819THREADED_TEST(GetHeapStatistics) {
ager@chromium.org3811b432009-10-28 14:53:37 +000017820 LocalContext c1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017821 v8::HandleScope scope(c1->GetIsolate());
ager@chromium.org3811b432009-10-28 14:53:37 +000017822 v8::HeapStatistics heap_statistics;
ager@chromium.orgc4c92722009-11-18 14:12:51 +000017823 CHECK_EQ(static_cast<int>(heap_statistics.total_heap_size()), 0);
17824 CHECK_EQ(static_cast<int>(heap_statistics.used_heap_size()), 0);
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +000017825 c1->GetIsolate()->GetHeapStatistics(&heap_statistics);
ager@chromium.orgc4c92722009-11-18 14:12:51 +000017826 CHECK_NE(static_cast<int>(heap_statistics.total_heap_size()), 0);
17827 CHECK_NE(static_cast<int>(heap_statistics.used_heap_size()), 0);
ager@chromium.org3811b432009-10-28 14:53:37 +000017828}
17829
17830
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017831class VisitorImpl : public v8::ExternalResourceVisitor {
17832 public:
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017833 explicit VisitorImpl(TestResource** resource) {
17834 for (int i = 0; i < 4; i++) {
17835 resource_[i] = resource[i];
17836 found_resource_[i] = false;
17837 }
17838 }
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017839 virtual ~VisitorImpl() {}
17840 virtual void VisitExternalString(v8::Handle<v8::String> string) {
17841 if (!string->IsExternal()) {
17842 CHECK(string->IsExternalAscii());
17843 return;
17844 }
17845 v8::String::ExternalStringResource* resource =
17846 string->GetExternalStringResource();
17847 CHECK(resource);
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017848 for (int i = 0; i < 4; i++) {
17849 if (resource_[i] == resource) {
17850 CHECK(!found_resource_[i]);
17851 found_resource_[i] = true;
17852 }
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017853 }
17854 }
17855 void CheckVisitedResources() {
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017856 for (int i = 0; i < 4; i++) {
17857 CHECK(found_resource_[i]);
17858 }
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017859 }
17860
17861 private:
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017862 v8::String::ExternalStringResource* resource_[4];
17863 bool found_resource_[4];
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017864};
17865
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000017866
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017867TEST(VisitExternalStrings) {
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017868 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000017869 v8::HandleScope scope(env->GetIsolate());
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017870 const char* string = "Some string";
17871 uint16_t* two_byte_string = AsciiToTwoByteString(string);
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017872 TestResource* resource[4];
17873 resource[0] = new TestResource(two_byte_string);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000017874 v8::Local<v8::String> string0 =
17875 v8::String::NewExternal(env->GetIsolate(), resource[0]);
machenbach@chromium.org57a54ac2014-01-31 14:01:53 +000017876 resource[1] = new TestResource(two_byte_string, NULL, false);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000017877 v8::Local<v8::String> string1 =
17878 v8::String::NewExternal(env->GetIsolate(), resource[1]);
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017879
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017880 // Externalized symbol.
machenbach@chromium.org57a54ac2014-01-31 14:01:53 +000017881 resource[2] = new TestResource(two_byte_string, NULL, false);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000017882 v8::Local<v8::String> string2 = v8::String::NewFromUtf8(
17883 env->GetIsolate(), string, v8::String::kInternalizedString);
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017884 CHECK(string2->MakeExternal(resource[2]));
17885
17886 // Symbolized External.
17887 resource[3] = new TestResource(AsciiToTwoByteString("Some other string"));
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000017888 v8::Local<v8::String> string3 =
17889 v8::String::NewExternal(env->GetIsolate(), resource[3]);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017890 CcTest::heap()->CollectAllAvailableGarbage(); // Tenure string.
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017891 // Turn into a symbol.
17892 i::Handle<i::String> string3_i = v8::Utils::OpenHandle(*string3);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000017893 CHECK(!CcTest::heap()->InternalizeString(*string3_i)->IsFailure());
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +000017894 CHECK(string3_i->IsInternalizedString());
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017895
17896 // We need to add usages for string* to avoid warnings in GCC 4.7
17897 CHECK(string0->IsExternal());
ulan@chromium.org2efb9002012-01-19 15:36:35 +000017898 CHECK(string1->IsExternal());
17899 CHECK(string2->IsExternal());
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017900 CHECK(string3->IsExternal());
ulan@chromium.org2efb9002012-01-19 15:36:35 +000017901
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +000017902 VisitorImpl visitor(resource);
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000017903 v8::V8::VisitExternalResources(&visitor);
17904 visitor.CheckVisitedResources();
17905}
17906
17907
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000017908TEST(ExternalStringCollectedAtTearDown) {
17909 int destroyed = 0;
17910 v8::Isolate* isolate = v8::Isolate::New();
17911 { v8::Isolate::Scope isolate_scope(isolate);
17912 v8::HandleScope handle_scope(isolate);
17913 const char* s = "One string to test them all, one string to find them.";
17914 TestAsciiResource* inscription =
17915 new TestAsciiResource(i::StrDup(s), &destroyed);
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000017916 v8::Local<v8::String> ring = v8::String::NewExternal(isolate, inscription);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000017917 // Ring is still alive. Orcs are roaming freely across our lands.
17918 CHECK_EQ(0, destroyed);
17919 USE(ring);
17920 }
17921
17922 isolate->Dispose();
17923 // Ring has been destroyed. Free Peoples of Middle-earth Rejoice.
17924 CHECK_EQ(1, destroyed);
17925}
17926
17927
jkummerow@chromium.org113035e2013-12-13 15:13:40 +000017928TEST(ExternalInternalizedStringCollectedAtTearDown) {
17929 int destroyed = 0;
17930 v8::Isolate* isolate = v8::Isolate::New();
17931 { v8::Isolate::Scope isolate_scope(isolate);
17932 LocalContext env(isolate);
17933 v8::HandleScope handle_scope(isolate);
17934 CompileRun("var ring = 'One string to test them all';");
17935 const char* s = "One string to test them all";
17936 TestAsciiResource* inscription =
17937 new TestAsciiResource(i::StrDup(s), &destroyed);
17938 v8::Local<v8::String> ring = CompileRun("ring")->ToString();
17939 CHECK(v8::Utils::OpenHandle(*ring)->IsInternalizedString());
17940 ring->MakeExternal(inscription);
17941 // Ring is still alive. Orcs are roaming freely across our lands.
17942 CHECK_EQ(0, destroyed);
17943 USE(ring);
17944 }
17945
17946 isolate->Dispose();
17947 // Ring has been destroyed. Free Peoples of Middle-earth Rejoice.
17948 CHECK_EQ(1, destroyed);
17949}
17950
17951
17952TEST(ExternalInternalizedStringCollectedAtGC) {
17953 int destroyed = 0;
17954 { LocalContext env;
17955 v8::HandleScope handle_scope(env->GetIsolate());
17956 CompileRun("var ring = 'One string to test them all';");
17957 const char* s = "One string to test them all";
17958 TestAsciiResource* inscription =
17959 new TestAsciiResource(i::StrDup(s), &destroyed);
17960 v8::Local<v8::String> ring = CompileRun("ring")->ToString();
17961 CHECK(v8::Utils::OpenHandle(*ring)->IsInternalizedString());
17962 ring->MakeExternal(inscription);
17963 // Ring is still alive. Orcs are roaming freely across our lands.
17964 CHECK_EQ(0, destroyed);
17965 USE(ring);
17966 }
17967
17968 // Garbage collector deals swift blows to evil.
17969 CcTest::i_isolate()->compilation_cache()->Clear();
17970 CcTest::heap()->CollectAllAvailableGarbage();
17971
17972 // Ring has been destroyed. Free Peoples of Middle-earth Rejoice.
17973 CHECK_EQ(1, destroyed);
17974}
17975
17976
ager@chromium.org3811b432009-10-28 14:53:37 +000017977static double DoubleFromBits(uint64_t value) {
17978 double target;
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +000017979 i::OS::MemCopy(&target, &value, sizeof(target));
ager@chromium.org3811b432009-10-28 14:53:37 +000017980 return target;
17981}
17982
17983
17984static uint64_t DoubleToBits(double value) {
17985 uint64_t target;
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +000017986 i::OS::MemCopy(&target, &value, sizeof(target));
ager@chromium.org3811b432009-10-28 14:53:37 +000017987 return target;
17988}
17989
17990
17991static double DoubleToDateTime(double input) {
17992 double date_limit = 864e13;
ulan@chromium.org77ca49a2013-04-22 09:43:56 +000017993 if (std::isnan(input) || input < -date_limit || input > date_limit) {
ager@chromium.org3811b432009-10-28 14:53:37 +000017994 return i::OS::nan_value();
17995 }
machenbach@chromium.orge31286d2014-01-15 10:29:52 +000017996 return (input < 0) ? -(std::floor(-input)) : std::floor(input);
ager@chromium.org3811b432009-10-28 14:53:37 +000017997}
17998
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000017999
ager@chromium.org3811b432009-10-28 14:53:37 +000018000// We don't have a consistent way to write 64-bit constants syntactically, so we
18001// split them into two 32-bit constants and combine them programmatically.
18002static double DoubleFromBits(uint32_t high_bits, uint32_t low_bits) {
18003 return DoubleFromBits((static_cast<uint64_t>(high_bits) << 32) | low_bits);
18004}
18005
18006
18007THREADED_TEST(QuietSignalingNaNs) {
ager@chromium.org3811b432009-10-28 14:53:37 +000018008 LocalContext context;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018009 v8::Isolate* isolate = context->GetIsolate();
18010 v8::HandleScope scope(isolate);
ager@chromium.org3811b432009-10-28 14:53:37 +000018011 v8::TryCatch try_catch;
18012
18013 // Special double values.
18014 double snan = DoubleFromBits(0x7ff00000, 0x00000001);
18015 double qnan = DoubleFromBits(0x7ff80000, 0x00000000);
18016 double infinity = DoubleFromBits(0x7ff00000, 0x00000000);
18017 double max_normal = DoubleFromBits(0x7fefffff, 0xffffffffu);
18018 double min_normal = DoubleFromBits(0x00100000, 0x00000000);
18019 double max_denormal = DoubleFromBits(0x000fffff, 0xffffffffu);
18020 double min_denormal = DoubleFromBits(0x00000000, 0x00000001);
18021
18022 // Date values are capped at +/-100000000 days (times 864e5 ms per day)
18023 // on either side of the epoch.
18024 double date_limit = 864e13;
18025
18026 double test_values[] = {
18027 snan,
18028 qnan,
18029 infinity,
18030 max_normal,
18031 date_limit + 1,
18032 date_limit,
18033 min_normal,
18034 max_denormal,
18035 min_denormal,
18036 0,
18037 -0,
18038 -min_denormal,
18039 -max_denormal,
18040 -min_normal,
18041 -date_limit,
18042 -date_limit - 1,
18043 -max_normal,
18044 -infinity,
18045 -qnan,
18046 -snan
18047 };
18048 int num_test_values = 20;
18049
18050 for (int i = 0; i < num_test_values; i++) {
18051 double test_value = test_values[i];
18052
18053 // Check that Number::New preserves non-NaNs and quiets SNaNs.
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018054 v8::Handle<v8::Value> number = v8::Number::New(isolate, test_value);
ager@chromium.org3811b432009-10-28 14:53:37 +000018055 double stored_number = number->NumberValue();
ulan@chromium.org77ca49a2013-04-22 09:43:56 +000018056 if (!std::isnan(test_value)) {
ager@chromium.org3811b432009-10-28 14:53:37 +000018057 CHECK_EQ(test_value, stored_number);
18058 } else {
18059 uint64_t stored_bits = DoubleToBits(stored_number);
18060 // Check if quiet nan (bits 51..62 all set).
danno@chromium.orgc612e022011-11-10 11:38:15 +000018061#if defined(V8_TARGET_ARCH_MIPS) && !defined(USE_SIMULATOR)
18062 // Most significant fraction bit for quiet nan is set to 0
18063 // on MIPS architecture. Allowed by IEEE-754.
18064 CHECK_EQ(0xffe, static_cast<int>((stored_bits >> 51) & 0xfff));
18065#else
ager@chromium.org3811b432009-10-28 14:53:37 +000018066 CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff));
danno@chromium.orgc612e022011-11-10 11:38:15 +000018067#endif
ager@chromium.org3811b432009-10-28 14:53:37 +000018068 }
18069
18070 // Check that Date::New preserves non-NaNs in the date range and
18071 // quiets SNaNs.
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000018072 v8::Handle<v8::Value> date =
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018073 v8::Date::New(isolate, test_value);
ager@chromium.org3811b432009-10-28 14:53:37 +000018074 double expected_stored_date = DoubleToDateTime(test_value);
18075 double stored_date = date->NumberValue();
ulan@chromium.org77ca49a2013-04-22 09:43:56 +000018076 if (!std::isnan(expected_stored_date)) {
ager@chromium.org3811b432009-10-28 14:53:37 +000018077 CHECK_EQ(expected_stored_date, stored_date);
18078 } else {
18079 uint64_t stored_bits = DoubleToBits(stored_date);
18080 // Check if quiet nan (bits 51..62 all set).
danno@chromium.orgc612e022011-11-10 11:38:15 +000018081#if defined(V8_TARGET_ARCH_MIPS) && !defined(USE_SIMULATOR)
18082 // Most significant fraction bit for quiet nan is set to 0
18083 // on MIPS architecture. Allowed by IEEE-754.
18084 CHECK_EQ(0xffe, static_cast<int>((stored_bits >> 51) & 0xfff));
18085#else
ager@chromium.org3811b432009-10-28 14:53:37 +000018086 CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff));
danno@chromium.orgc612e022011-11-10 11:38:15 +000018087#endif
ager@chromium.org3811b432009-10-28 14:53:37 +000018088 }
18089 }
18090}
christian.plesner.hansen@gmail.comb9ce6372009-11-03 11:38:18 +000018091
18092
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018093static void SpaghettiIncident(
18094 const v8::FunctionCallbackInfo<v8::Value>& args) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018095 v8::HandleScope scope(args.GetIsolate());
christian.plesner.hansen@gmail.comb9ce6372009-11-03 11:38:18 +000018096 v8::TryCatch tc;
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000018097 v8::Handle<v8::String> str(args[0]->ToString());
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000018098 USE(str);
christian.plesner.hansen@gmail.comb9ce6372009-11-03 11:38:18 +000018099 if (tc.HasCaught())
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018100 tc.ReThrow();
christian.plesner.hansen@gmail.comb9ce6372009-11-03 11:38:18 +000018101}
18102
18103
18104// Test that an exception can be propagated down through a spaghetti
18105// stack using ReThrow.
18106THREADED_TEST(SpaghettiStackReThrow) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000018107 v8::Isolate* isolate = CcTest::isolate();
18108 v8::HandleScope scope(isolate);
christian.plesner.hansen@gmail.comb9ce6372009-11-03 11:38:18 +000018109 LocalContext context;
18110 context->Global()->Set(
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000018111 v8::String::NewFromUtf8(isolate, "s"),
18112 v8::FunctionTemplate::New(isolate, SpaghettiIncident)->GetFunction());
christian.plesner.hansen@gmail.comb9ce6372009-11-03 11:38:18 +000018113 v8::TryCatch try_catch;
18114 CompileRun(
18115 "var i = 0;"
18116 "var o = {"
18117 " toString: function () {"
18118 " if (i == 10) {"
18119 " throw 'Hey!';"
18120 " } else {"
18121 " i++;"
18122 " return s(o);"
18123 " }"
18124 " }"
18125 "};"
18126 "s(o);");
18127 CHECK(try_catch.HasCaught());
18128 v8::String::Utf8Value value(try_catch.Exception());
18129 CHECK_EQ(0, strcmp(*value, "Hey!"));
18130}
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018131
18132
sgjesse@chromium.org98180592009-12-02 08:17:28 +000018133TEST(Regress528) {
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018134 v8::V8::Initialize();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018135 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000018136 v8::HandleScope scope(isolate);
18137 v8::Local<Context> other_context;
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018138 int gc_count;
18139
ager@chromium.org60121232009-12-03 11:25:37 +000018140 // Create a context used to keep the code from aging in the compilation
18141 // cache.
ulan@chromium.org57ff8812013-05-10 08:16:55 +000018142 other_context = Context::New(isolate);
ager@chromium.org60121232009-12-03 11:25:37 +000018143
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018144 // Context-dependent context data creates reference from the compilation
18145 // cache to the global object.
ager@chromium.org60121232009-12-03 11:25:37 +000018146 const char* source_simple = "1";
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018147 {
ulan@chromium.org57ff8812013-05-10 08:16:55 +000018148 v8::HandleScope scope(isolate);
18149 v8::Local<Context> context = Context::New(isolate);
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018150
18151 context->Enter();
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018152 Local<v8::String> obj = v8::String::NewFromUtf8(isolate, "");
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000018153 context->SetEmbedderData(0, obj);
ager@chromium.org60121232009-12-03 11:25:37 +000018154 CompileRun(source_simple);
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018155 context->Exit();
18156 }
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000018157 v8::V8::ContextDisposedNotification();
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018158 for (gc_count = 1; gc_count < 10; gc_count++) {
ager@chromium.org60121232009-12-03 11:25:37 +000018159 other_context->Enter();
18160 CompileRun(source_simple);
18161 other_context->Exit();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018162 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org60121232009-12-03 11:25:37 +000018163 if (GetGlobalObjectsCount() == 1) break;
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018164 }
ager@chromium.org60121232009-12-03 11:25:37 +000018165 CHECK_GE(2, gc_count);
18166 CHECK_EQ(1, GetGlobalObjectsCount());
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018167
18168 // Eval in a function creates reference from the compilation cache to the
18169 // global object.
ager@chromium.org60121232009-12-03 11:25:37 +000018170 const char* source_eval = "function f(){eval('1')}; f()";
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018171 {
ulan@chromium.org57ff8812013-05-10 08:16:55 +000018172 v8::HandleScope scope(isolate);
18173 v8::Local<Context> context = Context::New(isolate);
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018174
18175 context->Enter();
ager@chromium.org60121232009-12-03 11:25:37 +000018176 CompileRun(source_eval);
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018177 context->Exit();
18178 }
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000018179 v8::V8::ContextDisposedNotification();
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018180 for (gc_count = 1; gc_count < 10; gc_count++) {
ager@chromium.org60121232009-12-03 11:25:37 +000018181 other_context->Enter();
18182 CompileRun(source_eval);
18183 other_context->Exit();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018184 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org60121232009-12-03 11:25:37 +000018185 if (GetGlobalObjectsCount() == 1) break;
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018186 }
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +000018187 CHECK_GE(2, gc_count);
sgjesse@chromium.org98180592009-12-02 08:17:28 +000018188 CHECK_EQ(1, GetGlobalObjectsCount());
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018189
18190 // Looking up the line number for an exception creates reference from the
18191 // compilation cache to the global object.
ager@chromium.org60121232009-12-03 11:25:37 +000018192 const char* source_exception = "function f(){throw 1;} f()";
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018193 {
ulan@chromium.org57ff8812013-05-10 08:16:55 +000018194 v8::HandleScope scope(isolate);
18195 v8::Local<Context> context = Context::New(isolate);
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018196
18197 context->Enter();
18198 v8::TryCatch try_catch;
ager@chromium.org60121232009-12-03 11:25:37 +000018199 CompileRun(source_exception);
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018200 CHECK(try_catch.HasCaught());
18201 v8::Handle<v8::Message> message = try_catch.Message();
18202 CHECK(!message.IsEmpty());
18203 CHECK_EQ(1, message->GetLineNumber());
18204 context->Exit();
18205 }
svenpanne@chromium.orgc859c4f2012-10-15 11:51:39 +000018206 v8::V8::ContextDisposedNotification();
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018207 for (gc_count = 1; gc_count < 10; gc_count++) {
ager@chromium.org60121232009-12-03 11:25:37 +000018208 other_context->Enter();
18209 CompileRun(source_exception);
18210 other_context->Exit();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018211 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.org60121232009-12-03 11:25:37 +000018212 if (GetGlobalObjectsCount() == 1) break;
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018213 }
ager@chromium.org60121232009-12-03 11:25:37 +000018214 CHECK_GE(2, gc_count);
18215 CHECK_EQ(1, GetGlobalObjectsCount());
18216
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000018217 v8::V8::ContextDisposedNotification();
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +000018218}
ager@chromium.org5c838252010-02-19 08:53:10 +000018219
18220
18221THREADED_TEST(ScriptOrigin) {
ager@chromium.org5c838252010-02-19 08:53:10 +000018222 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018223 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018224 v8::ScriptOrigin origin =
18225 v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
18226 v8::Handle<v8::String> script = v8::String::NewFromUtf8(
18227 env->GetIsolate(), "function f() {}\n\nfunction g() {}");
ager@chromium.org5c838252010-02-19 08:53:10 +000018228 v8::Script::Compile(script, &origin)->Run();
18229 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018230 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
ager@chromium.org5c838252010-02-19 08:53:10 +000018231 v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018232 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
ager@chromium.org5c838252010-02-19 08:53:10 +000018233
18234 v8::ScriptOrigin script_origin_f = f->GetScriptOrigin();
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000018235 CHECK_EQ("test", *v8::String::Utf8Value(script_origin_f.ResourceName()));
ager@chromium.org5c838252010-02-19 08:53:10 +000018236 CHECK_EQ(0, script_origin_f.ResourceLineOffset()->Int32Value());
18237
18238 v8::ScriptOrigin script_origin_g = g->GetScriptOrigin();
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000018239 CHECK_EQ("test", *v8::String::Utf8Value(script_origin_g.ResourceName()));
ager@chromium.org5c838252010-02-19 08:53:10 +000018240 CHECK_EQ(0, script_origin_g.ResourceLineOffset()->Int32Value());
18241}
18242
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000018243
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000018244THREADED_TEST(FunctionGetInferredName) {
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000018245 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018246 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018247 v8::ScriptOrigin origin =
18248 v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
18249 v8::Handle<v8::String> script = v8::String::NewFromUtf8(
18250 env->GetIsolate(),
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000018251 "var foo = { bar : { baz : function() {}}}; var f = foo.bar.baz;");
18252 v8::Script::Compile(script, &origin)->Run();
18253 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018254 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
ulan@chromium.org906e2fb2013-05-14 08:14:38 +000018255 CHECK_EQ("foo.bar.baz", *v8::String::Utf8Value(f->GetInferredName()));
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000018256}
ager@chromium.org5c838252010-02-19 08:53:10 +000018257
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000018258
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +000018259THREADED_TEST(FunctionGetDisplayName) {
18260 LocalContext env;
18261 v8::HandleScope scope(env->GetIsolate());
18262 const char* code = "var error = false;"
18263 "function a() { this.x = 1; };"
18264 "a.displayName = 'display_a';"
18265 "var b = (function() {"
18266 " var f = function() { this.x = 2; };"
18267 " f.displayName = 'display_b';"
18268 " return f;"
18269 "})();"
18270 "var c = function() {};"
18271 "c.__defineGetter__('displayName', function() {"
18272 " error = true;"
18273 " throw new Error();"
18274 "});"
18275 "function d() {};"
18276 "d.__defineGetter__('displayName', function() {"
18277 " error = true;"
18278 " return 'wrong_display_name';"
18279 "});"
18280 "function e() {};"
18281 "e.displayName = 'wrong_display_name';"
18282 "e.__defineSetter__('displayName', function() {"
18283 " error = true;"
18284 " throw new Error();"
18285 "});"
18286 "function f() {};"
18287 "f.displayName = { 'foo': 6, toString: function() {"
18288 " error = true;"
18289 " return 'wrong_display_name';"
18290 "}};"
18291 "var g = function() {"
18292 " arguments.callee.displayName = 'set_in_runtime';"
18293 "}; g();"
18294 ;
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018295 v8::ScriptOrigin origin =
18296 v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
18297 v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(), code), &origin)
18298 ->Run();
18299 v8::Local<v8::Value> error =
18300 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "error"));
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +000018301 v8::Local<v8::Function> a = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018302 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "a")));
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +000018303 v8::Local<v8::Function> b = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018304 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "b")));
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +000018305 v8::Local<v8::Function> c = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018306 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "c")));
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +000018307 v8::Local<v8::Function> d = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018308 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "d")));
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +000018309 v8::Local<v8::Function> e = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018310 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "e")));
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +000018311 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018312 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +000018313 v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018314 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +000018315 CHECK_EQ(false, error->BooleanValue());
18316 CHECK_EQ("display_a", *v8::String::Utf8Value(a->GetDisplayName()));
18317 CHECK_EQ("display_b", *v8::String::Utf8Value(b->GetDisplayName()));
18318 CHECK(c->GetDisplayName()->IsUndefined());
18319 CHECK(d->GetDisplayName()->IsUndefined());
18320 CHECK(e->GetDisplayName()->IsUndefined());
18321 CHECK(f->GetDisplayName()->IsUndefined());
18322 CHECK_EQ("set_in_runtime", *v8::String::Utf8Value(g->GetDisplayName()));
18323}
18324
18325
ager@chromium.org5c838252010-02-19 08:53:10 +000018326THREADED_TEST(ScriptLineNumber) {
ager@chromium.org5c838252010-02-19 08:53:10 +000018327 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018328 v8::HandleScope scope(env->GetIsolate());
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018329 v8::ScriptOrigin origin =
18330 v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
18331 v8::Handle<v8::String> script = v8::String::NewFromUtf8(
18332 env->GetIsolate(), "function f() {}\n\nfunction g() {}");
ager@chromium.org5c838252010-02-19 08:53:10 +000018333 v8::Script::Compile(script, &origin)->Run();
18334 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018335 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
ager@chromium.org5c838252010-02-19 08:53:10 +000018336 v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018337 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
ager@chromium.org5c838252010-02-19 08:53:10 +000018338 CHECK_EQ(0, f->GetScriptLineNumber());
18339 CHECK_EQ(2, g->GetScriptLineNumber());
18340}
18341
18342
danno@chromium.orgc612e022011-11-10 11:38:15 +000018343THREADED_TEST(ScriptColumnNumber) {
danno@chromium.orgc612e022011-11-10 11:38:15 +000018344 LocalContext env;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018345 v8::Isolate* isolate = env->GetIsolate();
18346 v8::HandleScope scope(isolate);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018347 v8::ScriptOrigin origin =
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018348 v8::ScriptOrigin(v8::String::NewFromUtf8(isolate, "test"),
18349 v8::Integer::New(isolate, 3),
18350 v8::Integer::New(isolate, 2));
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018351 v8::Handle<v8::String> script = v8::String::NewFromUtf8(
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018352 isolate, "function foo() {}\n\n function bar() {}");
danno@chromium.orgc612e022011-11-10 11:38:15 +000018353 v8::Script::Compile(script, &origin)->Run();
18354 v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018355 env->Global()->Get(v8::String::NewFromUtf8(isolate, "foo")));
danno@chromium.orgc612e022011-11-10 11:38:15 +000018356 v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018357 env->Global()->Get(v8::String::NewFromUtf8(isolate, "bar")));
danno@chromium.orgc612e022011-11-10 11:38:15 +000018358 CHECK_EQ(14, foo->GetScriptColumnNumber());
18359 CHECK_EQ(17, bar->GetScriptColumnNumber());
18360}
18361
18362
bmeurer@chromium.orgdb783292013-10-23 06:51:00 +000018363THREADED_TEST(FunctionIsBuiltin) {
18364 LocalContext env;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018365 v8::Isolate* isolate = env->GetIsolate();
18366 v8::HandleScope scope(isolate);
bmeurer@chromium.orgdb783292013-10-23 06:51:00 +000018367 v8::Local<v8::Function> f;
18368 f = v8::Local<v8::Function>::Cast(CompileRun("Math.floor"));
18369 CHECK(f->IsBuiltin());
18370 f = v8::Local<v8::Function>::Cast(CompileRun("Object"));
18371 CHECK(f->IsBuiltin());
18372 f = v8::Local<v8::Function>::Cast(CompileRun("Object.__defineSetter__"));
18373 CHECK(f->IsBuiltin());
18374 f = v8::Local<v8::Function>::Cast(CompileRun("Array.prototype.toString"));
18375 CHECK(f->IsBuiltin());
18376 f = v8::Local<v8::Function>::Cast(CompileRun("function a() {}; a;"));
18377 CHECK(!f->IsBuiltin());
18378}
18379
18380
danno@chromium.orgc612e022011-11-10 11:38:15 +000018381THREADED_TEST(FunctionGetScriptId) {
danno@chromium.orgc612e022011-11-10 11:38:15 +000018382 LocalContext env;
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018383 v8::Isolate* isolate = env->GetIsolate();
18384 v8::HandleScope scope(isolate);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018385 v8::ScriptOrigin origin =
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018386 v8::ScriptOrigin(v8::String::NewFromUtf8(isolate, "test"),
18387 v8::Integer::New(isolate, 3),
18388 v8::Integer::New(isolate, 2));
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018389 v8::Handle<v8::String> scriptSource = v8::String::NewFromUtf8(
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018390 isolate, "function foo() {}\n\n function bar() {}");
danno@chromium.orgc612e022011-11-10 11:38:15 +000018391 v8::Local<v8::Script> script(v8::Script::Compile(scriptSource, &origin));
18392 script->Run();
18393 v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018394 env->Global()->Get(v8::String::NewFromUtf8(isolate, "foo")));
danno@chromium.orgc612e022011-11-10 11:38:15 +000018395 v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
ulan@chromium.org0f13e742014-01-03 15:51:11 +000018396 env->Global()->Get(v8::String::NewFromUtf8(isolate, "bar")));
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000018397 CHECK_EQ(script->GetId(), foo->ScriptId());
18398 CHECK_EQ(script->GetId(), bar->ScriptId());
danno@chromium.orgc612e022011-11-10 11:38:15 +000018399}
18400
18401
yangguo@chromium.org49546742013-12-23 16:17:49 +000018402THREADED_TEST(FunctionGetBoundFunction) {
18403 LocalContext env;
18404 v8::HandleScope scope(env->GetIsolate());
18405 v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::NewFromUtf8(
18406 env->GetIsolate(), "test"));
18407 v8::Handle<v8::String> script = v8::String::NewFromUtf8(
18408 env->GetIsolate(),
18409 "var a = new Object();\n"
18410 "a.x = 1;\n"
18411 "function f () { return this.x };\n"
18412 "var g = f.bind(a);\n"
18413 "var b = g();");
18414 v8::Script::Compile(script, &origin)->Run();
18415 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
18416 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
18417 v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
18418 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
18419 CHECK(g->GetBoundFunction()->IsFunction());
18420 Local<v8::Function> original_function = Local<v8::Function>::Cast(
18421 g->GetBoundFunction());
18422 CHECK_EQ(f->GetName(), original_function->GetName());
18423 CHECK_EQ(f->GetScriptLineNumber(), original_function->GetScriptLineNumber());
18424 CHECK_EQ(f->GetScriptColumnNumber(),
18425 original_function->GetScriptColumnNumber());
18426}
18427
18428
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018429static void GetterWhichReturns42(
18430 Local<String> name,
18431 const v8::PropertyCallbackInfo<v8::Value>& info) {
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000018432 CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
18433 CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018434 info.GetReturnValue().Set(v8_num(42));
ager@chromium.org5c838252010-02-19 08:53:10 +000018435}
18436
18437
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018438static void SetterWhichSetsYOnThisTo23(
18439 Local<String> name,
18440 Local<Value> value,
18441 const v8::PropertyCallbackInfo<void>& info) {
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000018442 CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
18443 CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
ager@chromium.org5c838252010-02-19 08:53:10 +000018444 info.This()->Set(v8_str("y"), v8_num(23));
18445}
18446
18447
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018448void FooGetInterceptor(Local<String> name,
18449 const v8::PropertyCallbackInfo<v8::Value>& info) {
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000018450 CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
18451 CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018452 if (!name->Equals(v8_str("foo"))) return;
18453 info.GetReturnValue().Set(v8_num(42));
erik.corry@gmail.com88767242012-08-08 14:43:45 +000018454}
18455
18456
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018457void FooSetInterceptor(Local<String> name,
18458 Local<Value> value,
18459 const v8::PropertyCallbackInfo<v8::Value>& info) {
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000018460 CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
18461 CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018462 if (!name->Equals(v8_str("foo"))) return;
erik.corry@gmail.com88767242012-08-08 14:43:45 +000018463 info.This()->Set(v8_str("y"), v8_num(23));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018464 info.GetReturnValue().Set(v8_num(23));
erik.corry@gmail.com88767242012-08-08 14:43:45 +000018465}
18466
18467
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000018468TEST(SetterOnConstructorPrototype) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000018469 v8::Isolate* isolate = CcTest::isolate();
18470 v8::HandleScope scope(isolate);
18471 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +000018472 templ->SetAccessor(v8_str("x"),
18473 GetterWhichReturns42,
18474 SetterWhichSetsYOnThisTo23);
18475 LocalContext context;
18476 context->Global()->Set(v8_str("P"), templ->NewInstance());
18477 CompileRun("function C1() {"
18478 " this.x = 23;"
18479 "};"
18480 "C1.prototype = P;"
18481 "function C2() {"
18482 " this.x = 23"
18483 "};"
18484 "C2.prototype = { };"
18485 "C2.prototype.__proto__ = P;");
18486
18487 v8::Local<v8::Script> script;
18488 script = v8::Script::Compile(v8_str("new C1();"));
18489 for (int i = 0; i < 10; i++) {
18490 v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
18491 CHECK_EQ(42, c1->Get(v8_str("x"))->Int32Value());
18492 CHECK_EQ(23, c1->Get(v8_str("y"))->Int32Value());
18493 }
18494
18495 script = v8::Script::Compile(v8_str("new C2();"));
18496 for (int i = 0; i < 10; i++) {
18497 v8::Handle<v8::Object> c2 = v8::Handle<v8::Object>::Cast(script->Run());
18498 CHECK_EQ(42, c2->Get(v8_str("x"))->Int32Value());
18499 CHECK_EQ(23, c2->Get(v8_str("y"))->Int32Value());
18500 }
18501}
18502
18503
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018504static void NamedPropertyGetterWhichReturns42(
18505 Local<String> name,
18506 const v8::PropertyCallbackInfo<v8::Value>& info) {
18507 info.GetReturnValue().Set(v8_num(42));
ager@chromium.org5c838252010-02-19 08:53:10 +000018508}
18509
18510
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018511static void NamedPropertySetterWhichSetsYOnThisTo23(
18512 Local<String> name,
18513 Local<Value> value,
18514 const v8::PropertyCallbackInfo<v8::Value>& info) {
ager@chromium.org5c838252010-02-19 08:53:10 +000018515 if (name->Equals(v8_str("x"))) {
18516 info.This()->Set(v8_str("y"), v8_num(23));
18517 }
ager@chromium.org5c838252010-02-19 08:53:10 +000018518}
18519
18520
18521THREADED_TEST(InterceptorOnConstructorPrototype) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000018522 v8::Isolate* isolate = CcTest::isolate();
18523 v8::HandleScope scope(isolate);
18524 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.org5c838252010-02-19 08:53:10 +000018525 templ->SetNamedPropertyHandler(NamedPropertyGetterWhichReturns42,
18526 NamedPropertySetterWhichSetsYOnThisTo23);
18527 LocalContext context;
18528 context->Global()->Set(v8_str("P"), templ->NewInstance());
18529 CompileRun("function C1() {"
18530 " this.x = 23;"
18531 "};"
18532 "C1.prototype = P;"
18533 "function C2() {"
18534 " this.x = 23"
18535 "};"
18536 "C2.prototype = { };"
18537 "C2.prototype.__proto__ = P;");
18538
18539 v8::Local<v8::Script> script;
18540 script = v8::Script::Compile(v8_str("new C1();"));
18541 for (int i = 0; i < 10; i++) {
18542 v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
18543 CHECK_EQ(23, c1->Get(v8_str("x"))->Int32Value());
18544 CHECK_EQ(42, c1->Get(v8_str("y"))->Int32Value());
18545 }
18546
18547 script = v8::Script::Compile(v8_str("new C2();"));
18548 for (int i = 0; i < 10; i++) {
18549 v8::Handle<v8::Object> c2 = v8::Handle<v8::Object>::Cast(script->Run());
18550 CHECK_EQ(23, c2->Get(v8_str("x"))->Int32Value());
18551 CHECK_EQ(42, c2->Get(v8_str("y"))->Int32Value());
18552 }
18553}
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000018554
18555
danno@chromium.orgf005df62013-04-30 16:36:45 +000018556TEST(Regress618) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000018557 const char* source = "function C1() {"
18558 " this.x = 23;"
18559 "};"
18560 "C1.prototype = P;";
18561
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000018562 LocalContext context;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000018563 v8::Isolate* isolate = context->GetIsolate();
18564 v8::HandleScope scope(isolate);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000018565 v8::Local<v8::Script> script;
18566
18567 // Use a simple object as prototype.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000018568 v8::Local<v8::Object> prototype = v8::Object::New(isolate);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000018569 prototype->Set(v8_str("y"), v8_num(42));
18570 context->Global()->Set(v8_str("P"), prototype);
18571
18572 // This compile will add the code to the compilation cache.
18573 CompileRun(source);
18574
18575 script = v8::Script::Compile(v8_str("new C1();"));
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +000018576 // Allow enough iterations for the inobject slack tracking logic
18577 // to finalize instance size and install the fast construct stub.
18578 for (int i = 0; i < 256; i++) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000018579 v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
18580 CHECK_EQ(23, c1->Get(v8_str("x"))->Int32Value());
18581 CHECK_EQ(42, c1->Get(v8_str("y"))->Int32Value());
18582 }
18583
18584 // Use an API object with accessors as prototype.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000018585 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000018586 templ->SetAccessor(v8_str("x"),
18587 GetterWhichReturns42,
18588 SetterWhichSetsYOnThisTo23);
18589 context->Global()->Set(v8_str("P"), templ->NewInstance());
18590
18591 // This compile will get the code from the compilation cache.
18592 CompileRun(source);
18593
18594 script = v8::Script::Compile(v8_str("new C1();"));
18595 for (int i = 0; i < 10; i++) {
18596 v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
18597 CHECK_EQ(42, c1->Get(v8_str("x"))->Int32Value());
18598 CHECK_EQ(23, c1->Get(v8_str("y"))->Int32Value());
18599 }
18600}
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018601
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018602v8::Isolate* gc_callbacks_isolate = NULL;
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018603int prologue_call_count = 0;
18604int epilogue_call_count = 0;
18605int prologue_call_count_second = 0;
18606int epilogue_call_count_second = 0;
18607
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018608void PrologueCallback(v8::GCType, v8::GCCallbackFlags flags) {
18609 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018610 ++prologue_call_count;
18611}
18612
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000018613
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018614void PrologueCallback(v8::Isolate* isolate,
18615 v8::GCType,
18616 v8::GCCallbackFlags flags) {
18617 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
18618 CHECK_EQ(gc_callbacks_isolate, isolate);
18619 ++prologue_call_count;
18620}
18621
18622
18623void EpilogueCallback(v8::GCType, v8::GCCallbackFlags flags) {
18624 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018625 ++epilogue_call_count;
18626}
18627
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000018628
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018629void EpilogueCallback(v8::Isolate* isolate,
18630 v8::GCType,
18631 v8::GCCallbackFlags flags) {
18632 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
18633 CHECK_EQ(gc_callbacks_isolate, isolate);
18634 ++epilogue_call_count;
18635}
18636
18637
18638void PrologueCallbackSecond(v8::GCType, v8::GCCallbackFlags flags) {
18639 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018640 ++prologue_call_count_second;
18641}
18642
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000018643
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018644void PrologueCallbackSecond(v8::Isolate* isolate,
18645 v8::GCType,
18646 v8::GCCallbackFlags flags) {
18647 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
18648 CHECK_EQ(gc_callbacks_isolate, isolate);
18649 ++prologue_call_count_second;
18650}
18651
18652
18653void EpilogueCallbackSecond(v8::GCType, v8::GCCallbackFlags flags) {
18654 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018655 ++epilogue_call_count_second;
18656}
18657
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000018658
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018659void EpilogueCallbackSecond(v8::Isolate* isolate,
18660 v8::GCType,
18661 v8::GCCallbackFlags flags) {
18662 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
18663 CHECK_EQ(gc_callbacks_isolate, isolate);
18664 ++epilogue_call_count_second;
18665}
18666
18667
18668TEST(GCCallbacksOld) {
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018669 LocalContext context;
18670
18671 v8::V8::AddGCPrologueCallback(PrologueCallback);
18672 v8::V8::AddGCEpilogueCallback(EpilogueCallback);
18673 CHECK_EQ(0, prologue_call_count);
18674 CHECK_EQ(0, epilogue_call_count);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018675 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018676 CHECK_EQ(1, prologue_call_count);
18677 CHECK_EQ(1, epilogue_call_count);
18678 v8::V8::AddGCPrologueCallback(PrologueCallbackSecond);
18679 v8::V8::AddGCEpilogueCallback(EpilogueCallbackSecond);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018680 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018681 CHECK_EQ(2, prologue_call_count);
18682 CHECK_EQ(2, epilogue_call_count);
18683 CHECK_EQ(1, prologue_call_count_second);
18684 CHECK_EQ(1, epilogue_call_count_second);
18685 v8::V8::RemoveGCPrologueCallback(PrologueCallback);
18686 v8::V8::RemoveGCEpilogueCallback(EpilogueCallback);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018687 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018688 CHECK_EQ(2, prologue_call_count);
18689 CHECK_EQ(2, epilogue_call_count);
18690 CHECK_EQ(2, prologue_call_count_second);
18691 CHECK_EQ(2, epilogue_call_count_second);
18692 v8::V8::RemoveGCPrologueCallback(PrologueCallbackSecond);
18693 v8::V8::RemoveGCEpilogueCallback(EpilogueCallbackSecond);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018694 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
18695 CHECK_EQ(2, prologue_call_count);
18696 CHECK_EQ(2, epilogue_call_count);
18697 CHECK_EQ(2, prologue_call_count_second);
18698 CHECK_EQ(2, epilogue_call_count_second);
18699}
18700
18701
18702TEST(GCCallbacks) {
18703 LocalContext context;
18704 v8::Isolate* isolate = context->GetIsolate();
18705 gc_callbacks_isolate = isolate;
18706 isolate->AddGCPrologueCallback(PrologueCallback);
18707 isolate->AddGCEpilogueCallback(EpilogueCallback);
18708 CHECK_EQ(0, prologue_call_count);
18709 CHECK_EQ(0, epilogue_call_count);
18710 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
18711 CHECK_EQ(1, prologue_call_count);
18712 CHECK_EQ(1, epilogue_call_count);
18713 isolate->AddGCPrologueCallback(PrologueCallbackSecond);
18714 isolate->AddGCEpilogueCallback(EpilogueCallbackSecond);
18715 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
18716 CHECK_EQ(2, prologue_call_count);
18717 CHECK_EQ(2, epilogue_call_count);
18718 CHECK_EQ(1, prologue_call_count_second);
18719 CHECK_EQ(1, epilogue_call_count_second);
18720 isolate->RemoveGCPrologueCallback(PrologueCallback);
18721 isolate->RemoveGCEpilogueCallback(EpilogueCallback);
18722 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
18723 CHECK_EQ(2, prologue_call_count);
18724 CHECK_EQ(2, epilogue_call_count);
18725 CHECK_EQ(2, prologue_call_count_second);
18726 CHECK_EQ(2, epilogue_call_count_second);
18727 isolate->RemoveGCPrologueCallback(PrologueCallbackSecond);
18728 isolate->RemoveGCEpilogueCallback(EpilogueCallbackSecond);
18729 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +000018730 CHECK_EQ(2, prologue_call_count);
18731 CHECK_EQ(2, epilogue_call_count);
18732 CHECK_EQ(2, prologue_call_count_second);
18733 CHECK_EQ(2, epilogue_call_count_second);
18734}
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018735
18736
18737THREADED_TEST(AddToJSFunctionResultCache) {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000018738 i::FLAG_stress_compaction = false;
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018739 i::FLAG_allow_natives_syntax = true;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018740 v8::HandleScope scope(CcTest::isolate());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018741
18742 LocalContext context;
18743
18744 const char* code =
18745 "(function() {"
18746 " var key0 = 'a';"
18747 " var key1 = 'b';"
18748 " var r0 = %_GetFromCache(0, key0);"
18749 " var r1 = %_GetFromCache(0, key1);"
18750 " var r0_ = %_GetFromCache(0, key0);"
18751 " if (r0 !== r0_)"
18752 " return 'Different results for ' + key0 + ': ' + r0 + ' vs. ' + r0_;"
18753 " var r1_ = %_GetFromCache(0, key1);"
18754 " if (r1 !== r1_)"
18755 " return 'Different results for ' + key1 + ': ' + r1 + ' vs. ' + r1_;"
18756 " return 'PASSED';"
18757 "})()";
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018758 CcTest::heap()->ClearJSFunctionResultCaches();
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018759 ExpectString(code, "PASSED");
18760}
18761
18762
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018763THREADED_TEST(FillJSFunctionResultCache) {
18764 i::FLAG_allow_natives_syntax = true;
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018765 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018766 v8::HandleScope scope(context->GetIsolate());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018767
18768 const char* code =
18769 "(function() {"
18770 " var k = 'a';"
18771 " var r = %_GetFromCache(0, k);"
18772 " for (var i = 0; i < 16; i++) {"
18773 " %_GetFromCache(0, 'a' + i);"
18774 " };"
18775 " if (r === %_GetFromCache(0, k))"
18776 " return 'FAILED: k0CacheSize is too small';"
18777 " return 'PASSED';"
18778 "})()";
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018779 CcTest::heap()->ClearJSFunctionResultCaches();
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018780 ExpectString(code, "PASSED");
18781}
18782
18783
18784THREADED_TEST(RoundRobinGetFromCache) {
18785 i::FLAG_allow_natives_syntax = true;
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018786 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018787 v8::HandleScope scope(context->GetIsolate());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018788
18789 const char* code =
18790 "(function() {"
18791 " var keys = [];"
18792 " for (var i = 0; i < 16; i++) keys.push(i);"
18793 " var values = [];"
18794 " for (var i = 0; i < 16; i++) values[i] = %_GetFromCache(0, keys[i]);"
18795 " for (var i = 0; i < 16; i++) {"
18796 " var v = %_GetFromCache(0, keys[i]);"
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000018797 " if (v.toString() !== values[i].toString())"
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018798 " return 'Wrong value for ' + "
18799 " keys[i] + ': ' + v + ' vs. ' + values[i];"
18800 " };"
18801 " return 'PASSED';"
18802 "})()";
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018803 CcTest::heap()->ClearJSFunctionResultCaches();
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018804 ExpectString(code, "PASSED");
18805}
18806
18807
18808THREADED_TEST(ReverseGetFromCache) {
18809 i::FLAG_allow_natives_syntax = true;
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018810 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018811 v8::HandleScope scope(context->GetIsolate());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018812
18813 const char* code =
18814 "(function() {"
18815 " var keys = [];"
18816 " for (var i = 0; i < 16; i++) keys.push(i);"
18817 " var values = [];"
18818 " for (var i = 0; i < 16; i++) values[i] = %_GetFromCache(0, keys[i]);"
18819 " for (var i = 15; i >= 16; i--) {"
18820 " var v = %_GetFromCache(0, keys[i]);"
18821 " if (v !== values[i])"
18822 " return 'Wrong value for ' + "
18823 " keys[i] + ': ' + v + ' vs. ' + values[i];"
18824 " };"
18825 " return 'PASSED';"
18826 "})()";
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018827 CcTest::heap()->ClearJSFunctionResultCaches();
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018828 ExpectString(code, "PASSED");
18829}
18830
18831
18832THREADED_TEST(TestEviction) {
18833 i::FLAG_allow_natives_syntax = true;
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018834 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018835 v8::HandleScope scope(context->GetIsolate());
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018836
18837 const char* code =
18838 "(function() {"
18839 " for (var i = 0; i < 2*16; i++) {"
18840 " %_GetFromCache(0, 'a' + i);"
18841 " };"
18842 " return 'PASSED';"
18843 "})()";
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018844 CcTest::heap()->ClearJSFunctionResultCaches();
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000018845 ExpectString(code, "PASSED");
18846}
lrn@chromium.org32d961d2010-06-30 09:09:34 +000018847
18848
18849THREADED_TEST(TwoByteStringInAsciiCons) {
18850 // See Chromium issue 47824.
lrn@chromium.org32d961d2010-06-30 09:09:34 +000018851 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000018852 v8::HandleScope scope(context->GetIsolate());
18853
lrn@chromium.org32d961d2010-06-30 09:09:34 +000018854 const char* init_code =
18855 "var str1 = 'abelspendabel';"
18856 "var str2 = str1 + str1 + str1;"
18857 "str2;";
18858 Local<Value> result = CompileRun(init_code);
18859
ricow@chromium.orgddd545c2011-08-24 12:02:41 +000018860 Local<Value> indexof = CompileRun("str2.indexOf('els')");
18861 Local<Value> lastindexof = CompileRun("str2.lastIndexOf('dab')");
18862
lrn@chromium.org32d961d2010-06-30 09:09:34 +000018863 CHECK(result->IsString());
18864 i::Handle<i::String> string = v8::Utils::OpenHandle(String::Cast(*result));
18865 int length = string->length();
ulan@chromium.org8e8d8822012-11-23 14:36:46 +000018866 CHECK(string->IsOneByteRepresentation());
lrn@chromium.org32d961d2010-06-30 09:09:34 +000018867
18868 FlattenString(string);
18869 i::Handle<i::String> flat_string = FlattenGetString(string);
18870
ulan@chromium.org8e8d8822012-11-23 14:36:46 +000018871 CHECK(string->IsOneByteRepresentation());
18872 CHECK(flat_string->IsOneByteRepresentation());
lrn@chromium.org32d961d2010-06-30 09:09:34 +000018873
18874 // Create external resource.
18875 uint16_t* uc16_buffer = new uint16_t[length + 1];
18876
18877 i::String::WriteToFlat(*flat_string, uc16_buffer, 0, length);
18878 uc16_buffer[length] = 0;
18879
18880 TestResource resource(uc16_buffer);
18881
18882 flat_string->MakeExternal(&resource);
18883
18884 CHECK(flat_string->IsTwoByteRepresentation());
18885
jkummerow@chromium.org7bd87f02013-03-20 18:06:29 +000018886 // If the cons string has been short-circuited, skip the following checks.
18887 if (!string.is_identical_to(flat_string)) {
18888 // At this point, we should have a Cons string which is flat and ASCII,
18889 // with a first half that is a two-byte string (although it only contains
18890 // ASCII characters). This is a valid sequence of steps, and it can happen
18891 // in real pages.
18892 CHECK(string->IsOneByteRepresentation());
18893 i::ConsString* cons = i::ConsString::cast(*string);
18894 CHECK_EQ(0, cons->second()->length());
18895 CHECK(cons->first()->IsTwoByteRepresentation());
18896 }
lrn@chromium.org32d961d2010-06-30 09:09:34 +000018897
18898 // Check that some string operations work.
18899
18900 // Atom RegExp.
18901 Local<Value> reresult = CompileRun("str2.match(/abel/g).length;");
18902 CHECK_EQ(6, reresult->Int32Value());
18903
18904 // Nonatom RegExp.
18905 reresult = CompileRun("str2.match(/abe./g).length;");
18906 CHECK_EQ(6, reresult->Int32Value());
18907
18908 reresult = CompileRun("str2.search(/bel/g);");
18909 CHECK_EQ(1, reresult->Int32Value());
18910
18911 reresult = CompileRun("str2.search(/be./g);");
18912 CHECK_EQ(1, reresult->Int32Value());
18913
18914 ExpectTrue("/bel/g.test(str2);");
18915
18916 ExpectTrue("/be./g.test(str2);");
18917
18918 reresult = CompileRun("/bel/g.exec(str2);");
18919 CHECK(!reresult->IsNull());
18920
18921 reresult = CompileRun("/be./g.exec(str2);");
18922 CHECK(!reresult->IsNull());
18923
18924 ExpectString("str2.substring(2, 10);", "elspenda");
18925
18926 ExpectString("str2.substring(2, 20);", "elspendabelabelspe");
18927
18928 ExpectString("str2.charAt(2);", "e");
18929
ricow@chromium.orgddd545c2011-08-24 12:02:41 +000018930 ExpectObject("str2.indexOf('els');", indexof);
18931
18932 ExpectObject("str2.lastIndexOf('dab');", lastindexof);
18933
lrn@chromium.org32d961d2010-06-30 09:09:34 +000018934 reresult = CompileRun("str2.charCodeAt(2);");
18935 CHECK_EQ(static_cast<int32_t>('e'), reresult->Int32Value());
18936}
ager@chromium.orgea4f62e2010-08-16 16:28:43 +000018937
18938
ulan@chromium.orgdfe53072013-06-06 14:14:51 +000018939TEST(ContainsOnlyOneByte) {
18940 v8::V8::Initialize();
machenbach@chromium.org528ce022013-09-23 14:09:36 +000018941 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.orgdfe53072013-06-06 14:14:51 +000018942 v8::HandleScope scope(isolate);
18943 // Make a buffer long enough that it won't automatically be converted.
verwaest@chromium.org8a00e822013-06-10 15:11:22 +000018944 const int length = 512;
18945 // Ensure word aligned assignment.
18946 const int aligned_length = length*sizeof(uintptr_t)/sizeof(uint16_t);
18947 i::SmartArrayPointer<uintptr_t>
18948 aligned_contents(new uintptr_t[aligned_length]);
machenbach@chromium.orgafbdadc2013-12-09 16:12:18 +000018949 uint16_t* string_contents =
18950 reinterpret_cast<uint16_t*>(aligned_contents.get());
ulan@chromium.orgdfe53072013-06-06 14:14:51 +000018951 // Set to contain only one byte.
18952 for (int i = 0; i < length-1; i++) {
18953 string_contents[i] = 0x41;
18954 }
18955 string_contents[length-1] = 0;
18956 // Simple case.
machenbach@chromium.org57a54ac2014-01-31 14:01:53 +000018957 Handle<String> string =
18958 String::NewExternal(isolate,
18959 new TestResource(string_contents, NULL, false));
ulan@chromium.orgdfe53072013-06-06 14:14:51 +000018960 CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
18961 // Counter example.
verwaest@chromium.org8a00e822013-06-10 15:11:22 +000018962 string = String::NewFromTwoByte(isolate, string_contents);
ulan@chromium.orgdfe53072013-06-06 14:14:51 +000018963 CHECK(string->IsOneByte() && string->ContainsOnlyOneByte());
18964 // Test left right and balanced cons strings.
18965 Handle<String> base = String::NewFromUtf8(isolate, "a");
18966 Handle<String> left = base;
18967 Handle<String> right = base;
18968 for (int i = 0; i < 1000; i++) {
18969 left = String::Concat(base, left);
18970 right = String::Concat(right, base);
18971 }
18972 Handle<String> balanced = String::Concat(left, base);
18973 balanced = String::Concat(balanced, right);
18974 Handle<String> cons_strings[] = {left, balanced, right};
18975 Handle<String> two_byte =
machenbach@chromium.org57a54ac2014-01-31 14:01:53 +000018976 String::NewExternal(isolate,
18977 new TestResource(string_contents, NULL, false));
18978 USE(two_byte); USE(cons_strings);
ulan@chromium.orgdfe53072013-06-06 14:14:51 +000018979 for (size_t i = 0; i < ARRAY_SIZE(cons_strings); i++) {
18980 // Base assumptions.
18981 string = cons_strings[i];
18982 CHECK(string->IsOneByte() && string->ContainsOnlyOneByte());
18983 // Test left and right concatentation.
18984 string = String::Concat(two_byte, cons_strings[i]);
18985 CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
18986 string = String::Concat(cons_strings[i], two_byte);
18987 CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
18988 }
verwaest@chromium.org8a00e822013-06-10 15:11:22 +000018989 // Set bits in different positions
18990 // for strings of different lengths and alignments.
18991 for (int alignment = 0; alignment < 7; alignment++) {
18992 for (int size = 2; alignment + size < length; size *= 2) {
18993 int zero_offset = size + alignment;
18994 string_contents[zero_offset] = 0;
18995 for (int i = 0; i < size; i++) {
18996 int shift = 8 + (i % 7);
18997 string_contents[alignment + i] = 1 << shift;
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000018998 string = String::NewExternal(
machenbach@chromium.org57a54ac2014-01-31 14:01:53 +000018999 isolate,
19000 new TestResource(string_contents + alignment, NULL, false));
verwaest@chromium.org8a00e822013-06-10 15:11:22 +000019001 CHECK_EQ(size, string->Length());
19002 CHECK(!string->ContainsOnlyOneByte());
19003 string_contents[alignment + i] = 0x41;
19004 }
19005 string_contents[zero_offset] = 0x41;
19006 }
19007 }
ulan@chromium.orgdfe53072013-06-06 14:14:51 +000019008}
19009
19010
ager@chromium.orgea4f62e2010-08-16 16:28:43 +000019011// Failed access check callback that performs a GC on each invocation.
19012void FailedAccessCheckCallbackGC(Local<v8::Object> target,
19013 v8::AccessType type,
19014 Local<v8::Value> data) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019015 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ager@chromium.orgea4f62e2010-08-16 16:28:43 +000019016}
19017
19018
19019TEST(GCInFailedAccessCheckCallback) {
19020 // Install a failed access check callback that performs a GC on each
19021 // invocation. Then force the callback to be called from va
19022
19023 v8::V8::Initialize();
19024 v8::V8::SetFailedAccessCheckCallbackFunction(&FailedAccessCheckCallbackGC);
19025
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000019026 v8::Isolate* isolate = CcTest::isolate();
19027 v8::HandleScope scope(isolate);
ager@chromium.orgea4f62e2010-08-16 16:28:43 +000019028
19029 // Create an ObjectTemplate for global objects and install access
19030 // check callbacks that will block access.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000019031 v8::Handle<v8::ObjectTemplate> global_template =
19032 v8::ObjectTemplate::New(isolate);
ager@chromium.orgea4f62e2010-08-16 16:28:43 +000019033 global_template->SetAccessCheckCallbacks(NamedGetAccessBlocker,
19034 IndexedGetAccessBlocker,
19035 v8::Handle<v8::Value>(),
19036 false);
19037
19038 // Create a context and set an x property on it's global object.
19039 LocalContext context0(NULL, global_template);
19040 context0->Global()->Set(v8_str("x"), v8_num(42));
19041 v8::Handle<v8::Object> global0 = context0->Global();
19042
19043 // Create a context with a different security token so that the
19044 // failed access check callback will be called on each access.
19045 LocalContext context1(NULL, global_template);
19046 context1->Global()->Set(v8_str("other"), global0);
19047
19048 // Get property with failed access check.
19049 ExpectUndefined("other.x");
19050
19051 // Get element with failed access check.
19052 ExpectUndefined("other[0]");
19053
19054 // Set property with failed access check.
19055 v8::Handle<v8::Value> result = CompileRun("other.x = new Object()");
19056 CHECK(result->IsObject());
19057
19058 // Set element with failed access check.
19059 result = CompileRun("other[0] = new Object()");
19060 CHECK(result->IsObject());
19061
19062 // Get property attribute with failed access check.
19063 ExpectFalse("\'x\' in other");
19064
19065 // Get property attribute for element with failed access check.
19066 ExpectFalse("0 in other");
19067
19068 // Delete property.
19069 ExpectFalse("delete other.x");
19070
19071 // Delete element.
19072 CHECK_EQ(false, global0->Delete(0));
19073
19074 // DefineAccessor.
19075 CHECK_EQ(false,
19076 global0->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("x")));
19077
19078 // Define JavaScript accessor.
19079 ExpectUndefined("Object.prototype.__defineGetter__.call("
19080 " other, \'x\', function() { return 42; })");
19081
19082 // LookupAccessor.
19083 ExpectUndefined("Object.prototype.__lookupGetter__.call("
19084 " other, \'x\')");
19085
19086 // HasLocalElement.
19087 ExpectFalse("Object.prototype.hasOwnProperty.call(other, \'0\')");
19088
19089 CHECK_EQ(false, global0->HasRealIndexedProperty(0));
19090 CHECK_EQ(false, global0->HasRealNamedProperty(v8_str("x")));
19091 CHECK_EQ(false, global0->HasRealNamedCallbackProperty(v8_str("x")));
19092
19093 // Reset the failed access check callback so it does not influence
19094 // the other tests.
19095 v8::V8::SetFailedAccessCheckCallbackFunction(NULL);
19096}
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019097
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019098
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019099TEST(IsolateNewDispose) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019100 v8::Isolate* current_isolate = CcTest::isolate();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019101 v8::Isolate* isolate = v8::Isolate::New();
19102 CHECK(isolate != NULL);
19103 CHECK(!reinterpret_cast<i::Isolate*>(isolate)->IsDefaultIsolate());
19104 CHECK(current_isolate != isolate);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019105 CHECK(current_isolate == CcTest::isolate());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019106
19107 v8::V8::SetFatalErrorHandler(StoringErrorCallback);
19108 last_location = last_message = NULL;
19109 isolate->Dispose();
19110 CHECK_EQ(last_location, NULL);
19111 CHECK_EQ(last_message, NULL);
19112}
19113
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019114
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019115UNINITIALIZED_TEST(DisposeIsolateWhenInUse) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019116 v8::Isolate* isolate = v8::Isolate::New();
19117 CHECK(isolate);
19118 isolate->Enter();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019119 v8::HandleScope scope(isolate);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019120 LocalContext context(isolate);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019121 // Run something in this isolate.
19122 ExpectTrue("true");
19123 v8::V8::SetFatalErrorHandler(StoringErrorCallback);
19124 last_location = last_message = NULL;
19125 // Still entered, should fail.
19126 isolate->Dispose();
19127 CHECK_NE(last_location, NULL);
19128 CHECK_NE(last_message, NULL);
19129}
19130
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019131
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019132TEST(RunTwoIsolatesOnSingleThread) {
19133 // Run isolate 1.
19134 v8::Isolate* isolate1 = v8::Isolate::New();
19135 isolate1->Enter();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000019136 v8::Persistent<v8::Context> context1;
19137 {
19138 v8::HandleScope scope(isolate1);
19139 context1.Reset(isolate1, Context::New(isolate1));
19140 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019141
19142 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019143 v8::HandleScope scope(isolate1);
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000019144 v8::Local<v8::Context> context =
19145 v8::Local<v8::Context>::New(isolate1, context1);
19146 v8::Context::Scope context_scope(context);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019147 // Run something in new isolate.
19148 CompileRun("var foo = 'isolate 1';");
19149 ExpectString("function f() { return foo; }; f()", "isolate 1");
19150 }
19151
19152 // Run isolate 2.
19153 v8::Isolate* isolate2 = v8::Isolate::New();
19154 v8::Persistent<v8::Context> context2;
19155
19156 {
19157 v8::Isolate::Scope iscope(isolate2);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019158 v8::HandleScope scope(isolate2);
ulan@chromium.org57ff8812013-05-10 08:16:55 +000019159 context2.Reset(isolate2, Context::New(isolate2));
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000019160 v8::Local<v8::Context> context =
19161 v8::Local<v8::Context>::New(isolate2, context2);
19162 v8::Context::Scope context_scope(context);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019163
19164 // Run something in new isolate.
19165 CompileRun("var foo = 'isolate 2';");
19166 ExpectString("function f() { return foo; }; f()", "isolate 2");
19167 }
19168
19169 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019170 v8::HandleScope scope(isolate1);
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000019171 v8::Local<v8::Context> context =
19172 v8::Local<v8::Context>::New(isolate1, context1);
19173 v8::Context::Scope context_scope(context);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019174 // Now again in isolate 1
19175 ExpectString("function f() { return foo; }; f()", "isolate 1");
19176 }
19177
19178 isolate1->Exit();
19179
19180 // Run some stuff in default isolate.
ulan@chromium.org57ff8812013-05-10 08:16:55 +000019181 v8::Persistent<v8::Context> context_default;
19182 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019183 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000019184 v8::Isolate::Scope iscope(isolate);
19185 v8::HandleScope scope(isolate);
19186 context_default.Reset(isolate, Context::New(isolate));
19187 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019188
19189 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019190 v8::HandleScope scope(CcTest::isolate());
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000019191 v8::Local<v8::Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019192 v8::Local<v8::Context>::New(CcTest::isolate(), context_default);
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000019193 v8::Context::Scope context_scope(context);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019194 // Variables in other isolates should be not available, verify there
19195 // is an exception.
19196 ExpectTrue("function f() {"
19197 " try {"
19198 " foo;"
19199 " return false;"
19200 " } catch(e) {"
19201 " return true;"
19202 " }"
19203 "};"
19204 "var isDefaultIsolate = true;"
19205 "f()");
19206 }
19207
19208 isolate1->Enter();
19209
19210 {
19211 v8::Isolate::Scope iscope(isolate2);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019212 v8::HandleScope scope(isolate2);
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000019213 v8::Local<v8::Context> context =
19214 v8::Local<v8::Context>::New(isolate2, context2);
19215 v8::Context::Scope context_scope(context);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019216 ExpectString("function f() { return foo; }; f()", "isolate 2");
19217 }
19218
19219 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019220 v8::HandleScope scope(v8::Isolate::GetCurrent());
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000019221 v8::Local<v8::Context> context =
19222 v8::Local<v8::Context>::New(v8::Isolate::GetCurrent(), context1);
19223 v8::Context::Scope context_scope(context);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019224 ExpectString("function f() { return foo; }; f()", "isolate 1");
19225 }
19226
19227 {
19228 v8::Isolate::Scope iscope(isolate2);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000019229 context2.Reset();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019230 }
19231
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000019232 context1.Reset();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019233 isolate1->Exit();
19234
19235 v8::V8::SetFatalErrorHandler(StoringErrorCallback);
19236 last_location = last_message = NULL;
19237
19238 isolate1->Dispose();
19239 CHECK_EQ(last_location, NULL);
19240 CHECK_EQ(last_message, NULL);
19241
19242 isolate2->Dispose();
19243 CHECK_EQ(last_location, NULL);
19244 CHECK_EQ(last_message, NULL);
19245
19246 // Check that default isolate still runs.
19247 {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019248 v8::HandleScope scope(CcTest::isolate());
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000019249 v8::Local<v8::Context> context =
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019250 v8::Local<v8::Context>::New(CcTest::isolate(), context_default);
jkummerow@chromium.orgc1184022013-05-28 16:58:15 +000019251 v8::Context::Scope context_scope(context);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019252 ExpectTrue("function f() { return isDefaultIsolate; }; f()");
19253 }
19254}
19255
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019256
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019257static int CalcFibonacci(v8::Isolate* isolate, int limit) {
19258 v8::Isolate::Scope isolate_scope(isolate);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019259 v8::HandleScope scope(isolate);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019260 LocalContext context(isolate);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019261 i::ScopedVector<char> code(1024);
19262 i::OS::SNPrintF(code, "function fib(n) {"
19263 " if (n <= 2) return 1;"
19264 " return fib(n-1) + fib(n-2);"
19265 "}"
19266 "fib(%d)", limit);
19267 Local<Value> value = CompileRun(code.start());
19268 CHECK(value->IsNumber());
19269 return static_cast<int>(value->NumberValue());
19270}
19271
19272class IsolateThread : public v8::internal::Thread {
19273 public:
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000019274 IsolateThread(v8::Isolate* isolate, int fib_limit)
19275 : Thread("IsolateThread"),
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019276 isolate_(isolate),
19277 fib_limit_(fib_limit),
19278 result_(0) { }
19279
19280 void Run() {
19281 result_ = CalcFibonacci(isolate_, fib_limit_);
19282 }
19283
19284 int result() { return result_; }
19285
19286 private:
19287 v8::Isolate* isolate_;
19288 int fib_limit_;
19289 int result_;
19290};
19291
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019292
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019293TEST(MultipleIsolatesOnIndividualThreads) {
19294 v8::Isolate* isolate1 = v8::Isolate::New();
19295 v8::Isolate* isolate2 = v8::Isolate::New();
19296
19297 IsolateThread thread1(isolate1, 21);
19298 IsolateThread thread2(isolate2, 12);
19299
19300 // Compute some fibonacci numbers on 3 threads in 3 isolates.
19301 thread1.Start();
19302 thread2.Start();
19303
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019304 int result1 = CalcFibonacci(CcTest::isolate(), 21);
19305 int result2 = CalcFibonacci(CcTest::isolate(), 12);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019306
19307 thread1.Join();
19308 thread2.Join();
19309
19310 // Compare results. The actual fibonacci numbers for 12 and 21 are taken
19311 // (I'm lazy!) from http://en.wikipedia.org/wiki/Fibonacci_number
19312 CHECK_EQ(result1, 10946);
19313 CHECK_EQ(result2, 144);
19314 CHECK_EQ(result1, thread1.result());
19315 CHECK_EQ(result2, thread2.result());
19316
19317 isolate1->Dispose();
19318 isolate2->Dispose();
19319}
19320
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019321
lrn@chromium.org1c092762011-05-09 09:42:16 +000019322TEST(IsolateDifferentContexts) {
19323 v8::Isolate* isolate = v8::Isolate::New();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000019324 Local<v8::Context> context;
lrn@chromium.org1c092762011-05-09 09:42:16 +000019325 {
19326 v8::Isolate::Scope isolate_scope(isolate);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019327 v8::HandleScope handle_scope(isolate);
ulan@chromium.org57ff8812013-05-10 08:16:55 +000019328 context = v8::Context::New(isolate);
lrn@chromium.org1c092762011-05-09 09:42:16 +000019329 v8::Context::Scope context_scope(context);
19330 Local<Value> v = CompileRun("2");
19331 CHECK(v->IsNumber());
19332 CHECK_EQ(2, static_cast<int>(v->NumberValue()));
19333 }
19334 {
19335 v8::Isolate::Scope isolate_scope(isolate);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019336 v8::HandleScope handle_scope(isolate);
ulan@chromium.org57ff8812013-05-10 08:16:55 +000019337 context = v8::Context::New(isolate);
lrn@chromium.org1c092762011-05-09 09:42:16 +000019338 v8::Context::Scope context_scope(context);
19339 Local<Value> v = CompileRun("22");
19340 CHECK(v->IsNumber());
19341 CHECK_EQ(22, static_cast<int>(v->NumberValue()));
19342 }
19343}
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019344
19345class InitDefaultIsolateThread : public v8::internal::Thread {
19346 public:
sgjesse@chromium.orge0599052011-03-25 07:34:35 +000019347 enum TestCase {
19348 IgnoreOOM,
19349 SetResourceConstraints,
19350 SetFatalHandler,
19351 SetCounterFunction,
19352 SetCreateHistogramFunction,
19353 SetAddHistogramSampleFunction
19354 };
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019355
19356 explicit InitDefaultIsolateThread(TestCase testCase)
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000019357 : Thread("InitDefaultIsolateThread"),
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019358 testCase_(testCase),
19359 result_(false) { }
19360
19361 void Run() {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019362 v8::Isolate* isolate = v8::Isolate::New();
19363 isolate->Enter();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019364 switch (testCase_) {
19365 case IgnoreOOM:
19366 v8::V8::IgnoreOutOfMemoryException();
19367 break;
19368
19369 case SetResourceConstraints: {
19370 static const int K = 1024;
19371 v8::ResourceConstraints constraints;
19372 constraints.set_max_young_space_size(256 * K);
19373 constraints.set_max_old_space_size(4 * K * K);
machenbach@chromium.org7ff76072013-11-21 09:47:43 +000019374 v8::SetResourceConstraints(CcTest::isolate(), &constraints);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019375 break;
19376 }
19377
19378 case SetFatalHandler:
19379 v8::V8::SetFatalErrorHandler(NULL);
19380 break;
sgjesse@chromium.orge0599052011-03-25 07:34:35 +000019381
19382 case SetCounterFunction:
19383 v8::V8::SetCounterFunction(NULL);
19384 break;
19385
19386 case SetCreateHistogramFunction:
19387 v8::V8::SetCreateHistogramFunction(NULL);
19388 break;
19389
19390 case SetAddHistogramSampleFunction:
19391 v8::V8::SetAddHistogramSampleFunction(NULL);
19392 break;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019393 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019394 isolate->Exit();
19395 isolate->Dispose();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019396 result_ = true;
19397 }
19398
19399 bool result() { return result_; }
19400
19401 private:
19402 TestCase testCase_;
19403 bool result_;
19404};
19405
19406
19407static void InitializeTestHelper(InitDefaultIsolateThread::TestCase testCase) {
19408 InitDefaultIsolateThread thread(testCase);
19409 thread.Start();
19410 thread.Join();
19411 CHECK_EQ(thread.result(), true);
19412}
19413
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019414
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019415TEST(InitializeDefaultIsolateOnSecondaryThread1) {
19416 InitializeTestHelper(InitDefaultIsolateThread::IgnoreOOM);
19417}
19418
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019419
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019420TEST(InitializeDefaultIsolateOnSecondaryThread2) {
19421 InitializeTestHelper(InitDefaultIsolateThread::SetResourceConstraints);
19422}
19423
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019424
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000019425TEST(InitializeDefaultIsolateOnSecondaryThread3) {
19426 InitializeTestHelper(InitDefaultIsolateThread::SetFatalHandler);
19427}
19428
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019429
sgjesse@chromium.orge0599052011-03-25 07:34:35 +000019430TEST(InitializeDefaultIsolateOnSecondaryThread4) {
19431 InitializeTestHelper(InitDefaultIsolateThread::SetCounterFunction);
19432}
19433
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019434
sgjesse@chromium.orge0599052011-03-25 07:34:35 +000019435TEST(InitializeDefaultIsolateOnSecondaryThread5) {
19436 InitializeTestHelper(InitDefaultIsolateThread::SetCreateHistogramFunction);
19437}
19438
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +000019439
sgjesse@chromium.orge0599052011-03-25 07:34:35 +000019440TEST(InitializeDefaultIsolateOnSecondaryThread6) {
19441 InitializeTestHelper(InitDefaultIsolateThread::SetAddHistogramSampleFunction);
19442}
19443
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019444
19445TEST(StringCheckMultipleContexts) {
19446 const char* code =
19447 "(function() { return \"a\".charAt(0); })()";
19448
19449 {
19450 // Run the code twice in the first context to initialize the call IC.
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019451 LocalContext context1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019452 v8::HandleScope scope(context1->GetIsolate());
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019453 ExpectString(code, "a");
19454 ExpectString(code, "a");
19455 }
19456
19457 {
19458 // Change the String.prototype in the second context and check
19459 // that the right function gets called.
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019460 LocalContext context2;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019461 v8::HandleScope scope(context2->GetIsolate());
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019462 CompileRun("String.prototype.charAt = function() { return \"not a\"; }");
19463 ExpectString(code, "not a");
19464 }
19465}
19466
19467
19468TEST(NumberCheckMultipleContexts) {
19469 const char* code =
19470 "(function() { return (42).toString(); })()";
19471
19472 {
19473 // Run the code twice in the first context to initialize the call IC.
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019474 LocalContext context1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019475 v8::HandleScope scope(context1->GetIsolate());
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019476 ExpectString(code, "42");
19477 ExpectString(code, "42");
19478 }
19479
19480 {
19481 // Change the Number.prototype in the second context and check
19482 // that the right function gets called.
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019483 LocalContext context2;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019484 v8::HandleScope scope(context2->GetIsolate());
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019485 CompileRun("Number.prototype.toString = function() { return \"not 42\"; }");
19486 ExpectString(code, "not 42");
19487 }
19488}
19489
19490
19491TEST(BooleanCheckMultipleContexts) {
19492 const char* code =
19493 "(function() { return true.toString(); })()";
19494
19495 {
19496 // Run the code twice in the first context to initialize the call IC.
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019497 LocalContext context1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019498 v8::HandleScope scope(context1->GetIsolate());
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019499 ExpectString(code, "true");
19500 ExpectString(code, "true");
19501 }
19502
19503 {
19504 // Change the Boolean.prototype in the second context and check
19505 // that the right function gets called.
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019506 LocalContext context2;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019507 v8::HandleScope scope(context2->GetIsolate());
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000019508 CompileRun("Boolean.prototype.toString = function() { return \"\"; }");
19509 ExpectString(code, "");
19510 }
19511}
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000019512
19513
19514TEST(DontDeleteCellLoadIC) {
19515 const char* function_code =
19516 "function readCell() { while (true) { return cell; } }";
19517
19518 {
19519 // Run the code twice in the first context to initialize the load
19520 // IC for a don't delete cell.
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000019521 LocalContext context1;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019522 v8::HandleScope scope(context1->GetIsolate());
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000019523 CompileRun("var cell = \"first\";");
19524 ExpectBoolean("delete cell", false);
19525 CompileRun(function_code);
19526 ExpectString("readCell()", "first");
19527 ExpectString("readCell()", "first");
19528 }
19529
19530 {
19531 // Use a deletable cell in the second context.
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000019532 LocalContext context2;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019533 v8::HandleScope scope(context2->GetIsolate());
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000019534 CompileRun("cell = \"second\";");
19535 CompileRun(function_code);
19536 ExpectString("readCell()", "second");
19537 ExpectBoolean("delete cell", true);
19538 ExpectString("(function() {"
19539 " try {"
19540 " return readCell();"
19541 " } catch(e) {"
19542 " return e.toString();"
19543 " }"
19544 "})()",
19545 "ReferenceError: cell is not defined");
19546 CompileRun("cell = \"new_second\";");
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019547 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000019548 ExpectString("readCell()", "new_second");
19549 ExpectString("readCell()", "new_second");
19550 }
19551}
19552
19553
19554TEST(DontDeleteCellLoadICForceDelete) {
19555 const char* function_code =
19556 "function readCell() { while (true) { return cell; } }";
19557
19558 // Run the code twice to initialize the load IC for a don't delete
19559 // cell.
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000019560 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019561 v8::HandleScope scope(context->GetIsolate());
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000019562 CompileRun("var cell = \"value\";");
19563 ExpectBoolean("delete cell", false);
19564 CompileRun(function_code);
19565 ExpectString("readCell()", "value");
19566 ExpectString("readCell()", "value");
19567
19568 // Delete the cell using the API and check the inlined code works
19569 // correctly.
19570 CHECK(context->Global()->ForceDelete(v8_str("cell")));
19571 ExpectString("(function() {"
19572 " try {"
19573 " return readCell();"
19574 " } catch(e) {"
19575 " return e.toString();"
19576 " }"
19577 "})()",
19578 "ReferenceError: cell is not defined");
19579}
19580
19581
19582TEST(DontDeleteCellLoadICAPI) {
19583 const char* function_code =
19584 "function readCell() { while (true) { return cell; } }";
19585
19586 // Run the code twice to initialize the load IC for a don't delete
19587 // cell created using the API.
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000019588 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019589 v8::HandleScope scope(context->GetIsolate());
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +000019590 context->Global()->Set(v8_str("cell"), v8_str("value"), v8::DontDelete);
19591 ExpectBoolean("delete cell", false);
19592 CompileRun(function_code);
19593 ExpectString("readCell()", "value");
19594 ExpectString("readCell()", "value");
19595
19596 // Delete the cell using the API and check the inlined code works
19597 // correctly.
19598 CHECK(context->Global()->ForceDelete(v8_str("cell")));
19599 ExpectString("(function() {"
19600 " try {"
19601 " return readCell();"
19602 " } catch(e) {"
19603 " return e.toString();"
19604 " }"
19605 "})()",
19606 "ReferenceError: cell is not defined");
19607}
19608
19609
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000019610class Visitor42 : public v8::PersistentHandleVisitor {
19611 public:
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000019612 explicit Visitor42(v8::Persistent<v8::Object>* object)
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000019613 : counter_(0), object_(object) { }
19614
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000019615 virtual void VisitPersistentHandle(Persistent<Value>* value,
19616 uint16_t class_id) {
19617 if (class_id != 42) return;
19618 CHECK_EQ(42, value->WrapperClassId());
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019619 v8::Isolate* isolate = CcTest::isolate();
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000019620 v8::HandleScope handle_scope(isolate);
19621 v8::Handle<v8::Value> handle = v8::Local<v8::Value>::New(isolate, *value);
19622 v8::Handle<v8::Value> object =
19623 v8::Local<v8::Object>::New(isolate, *object_);
19624 CHECK(handle->IsObject());
19625 CHECK_EQ(Handle<Object>::Cast(handle), object);
19626 ++counter_;
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000019627 }
19628
19629 int counter_;
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000019630 v8::Persistent<v8::Object>* object_;
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000019631};
19632
19633
19634TEST(PersistentHandleVisitor) {
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000019635 LocalContext context;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000019636 v8::Isolate* isolate = context->GetIsolate();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019637 v8::HandleScope scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000019638 v8::Persistent<v8::Object> object(isolate, v8::Object::New(isolate));
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000019639 CHECK_EQ(0, object.WrapperClassId());
19640 object.SetWrapperClassId(42);
19641 CHECK_EQ(42, object.WrapperClassId());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000019642
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000019643 Visitor42 visitor(&object);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000019644 v8::V8::VisitHandlesWithClassIds(&visitor);
19645 CHECK_EQ(1, visitor.counter_);
19646
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000019647 object.Reset();
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000019648}
19649
19650
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000019651TEST(WrapperClassId) {
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000019652 LocalContext context;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000019653 v8::Isolate* isolate = context->GetIsolate();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019654 v8::HandleScope scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000019655 v8::Persistent<v8::Object> object(isolate, v8::Object::New(isolate));
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000019656 CHECK_EQ(0, object.WrapperClassId());
19657 object.SetWrapperClassId(65535);
19658 CHECK_EQ(65535, object.WrapperClassId());
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000019659 object.Reset();
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000019660}
19661
19662
yangguo@chromium.org003650e2013-01-24 16:31:08 +000019663TEST(PersistentHandleInNewSpaceVisitor) {
yangguo@chromium.org003650e2013-01-24 16:31:08 +000019664 LocalContext context;
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000019665 v8::Isolate* isolate = context->GetIsolate();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019666 v8::HandleScope scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000019667 v8::Persistent<v8::Object> object1(isolate, v8::Object::New(isolate));
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000019668 CHECK_EQ(0, object1.WrapperClassId());
19669 object1.SetWrapperClassId(42);
19670 CHECK_EQ(42, object1.WrapperClassId());
yangguo@chromium.org003650e2013-01-24 16:31:08 +000019671
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019672 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
yangguo@chromium.org003650e2013-01-24 16:31:08 +000019673
ulan@chromium.org0f13e742014-01-03 15:51:11 +000019674 v8::Persistent<v8::Object> object2(isolate, v8::Object::New(isolate));
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000019675 CHECK_EQ(0, object2.WrapperClassId());
19676 object2.SetWrapperClassId(42);
19677 CHECK_EQ(42, object2.WrapperClassId());
yangguo@chromium.org003650e2013-01-24 16:31:08 +000019678
rossberg@chromium.orgb99c7542013-05-31 11:40:45 +000019679 Visitor42 visitor(&object2);
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +000019680 v8::V8::VisitHandlesForPartialDependence(isolate, &visitor);
yangguo@chromium.org003650e2013-01-24 16:31:08 +000019681 CHECK_EQ(1, visitor.counter_);
19682
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000019683 object1.Reset();
19684 object2.Reset();
yangguo@chromium.org003650e2013-01-24 16:31:08 +000019685}
19686
19687
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019688TEST(RegExp) {
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019689 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019690 v8::HandleScope scope(context->GetIsolate());
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019691
19692 v8::Handle<v8::RegExp> re = v8::RegExp::New(v8_str("foo"), v8::RegExp::kNone);
19693 CHECK(re->IsRegExp());
19694 CHECK(re->GetSource()->Equals(v8_str("foo")));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000019695 CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019696
19697 re = v8::RegExp::New(v8_str("bar"),
19698 static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
19699 v8::RegExp::kGlobal));
19700 CHECK(re->IsRegExp());
19701 CHECK(re->GetSource()->Equals(v8_str("bar")));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000019702 CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kGlobal,
19703 static_cast<int>(re->GetFlags()));
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019704
19705 re = v8::RegExp::New(v8_str("baz"),
19706 static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
19707 v8::RegExp::kMultiline));
19708 CHECK(re->IsRegExp());
19709 CHECK(re->GetSource()->Equals(v8_str("baz")));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000019710 CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
19711 static_cast<int>(re->GetFlags()));
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019712
19713 re = CompileRun("/quux/").As<v8::RegExp>();
19714 CHECK(re->IsRegExp());
19715 CHECK(re->GetSource()->Equals(v8_str("quux")));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000019716 CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019717
19718 re = CompileRun("/quux/gm").As<v8::RegExp>();
19719 CHECK(re->IsRegExp());
19720 CHECK(re->GetSource()->Equals(v8_str("quux")));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000019721 CHECK_EQ(v8::RegExp::kGlobal | v8::RegExp::kMultiline,
19722 static_cast<int>(re->GetFlags()));
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019723
19724 // Override the RegExp constructor and check the API constructor
19725 // still works.
19726 CompileRun("RegExp = function() {}");
19727
19728 re = v8::RegExp::New(v8_str("foobar"), v8::RegExp::kNone);
19729 CHECK(re->IsRegExp());
19730 CHECK(re->GetSource()->Equals(v8_str("foobar")));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000019731 CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019732
19733 re = v8::RegExp::New(v8_str("foobarbaz"),
19734 static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
19735 v8::RegExp::kMultiline));
19736 CHECK(re->IsRegExp());
19737 CHECK(re->GetSource()->Equals(v8_str("foobarbaz")));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000019738 CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
19739 static_cast<int>(re->GetFlags()));
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019740
19741 context->Global()->Set(v8_str("re"), re);
19742 ExpectTrue("re.test('FoobarbaZ')");
19743
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000019744 // RegExps are objects on which you can set properties.
ulan@chromium.org0f13e742014-01-03 15:51:11 +000019745 re->Set(v8_str("property"), v8::Integer::New(context->GetIsolate(), 32));
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +000019746 v8::Handle<v8::Value> value(CompileRun("re.property"));
yangguo@chromium.org659ceec2012-01-26 07:37:54 +000019747 CHECK_EQ(32, value->Int32Value());
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000019748
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019749 v8::TryCatch try_catch;
19750 re = v8::RegExp::New(v8_str("foo["), v8::RegExp::kNone);
19751 CHECK(re.IsEmpty());
19752 CHECK(try_catch.HasCaught());
19753 context->Global()->Set(v8_str("ex"), try_catch.Exception());
19754 ExpectTrue("ex instanceof SyntaxError");
19755}
19756
19757
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000019758THREADED_TEST(Equals) {
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000019759 LocalContext localContext;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019760 v8::HandleScope handleScope(localContext->GetIsolate());
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +000019761
19762 v8::Handle<v8::Object> globalProxy = localContext->Global();
19763 v8::Handle<Value> global = globalProxy->GetPrototype();
19764
19765 CHECK(global->StrictEquals(global));
19766 CHECK(!global->StrictEquals(globalProxy));
19767 CHECK(!globalProxy->StrictEquals(global));
19768 CHECK(globalProxy->StrictEquals(globalProxy));
19769
19770 CHECK(global->Equals(global));
19771 CHECK(!global->Equals(globalProxy));
19772 CHECK(!globalProxy->Equals(global));
19773 CHECK(globalProxy->Equals(globalProxy));
19774}
19775
19776
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000019777static void Getter(v8::Local<v8::String> property,
19778 const v8::PropertyCallbackInfo<v8::Value>& info ) {
19779 info.GetReturnValue().Set(v8_str("42!"));
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019780}
19781
19782
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000019783static void Enumerator(const v8::PropertyCallbackInfo<v8::Array>& info) {
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000019784 v8::Handle<v8::Array> result = v8::Array::New(info.GetIsolate());
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019785 result->Set(0, v8_str("universalAnswer"));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000019786 info.GetReturnValue().Set(result);
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019787}
19788
19789
19790TEST(NamedEnumeratorAndForIn) {
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019791 LocalContext context;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000019792 v8::Isolate* isolate = context->GetIsolate();
19793 v8::HandleScope handle_scope(isolate);
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019794 v8::Context::Scope context_scope(context.local());
19795
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000019796 v8::Handle<v8::ObjectTemplate> tmpl = v8::ObjectTemplate::New(isolate);
ager@chromium.orgb61a0d12010-10-13 08:35:23 +000019797 tmpl->SetNamedPropertyHandler(Getter, NULL, NULL, NULL, Enumerator);
19798 context->Global()->Set(v8_str("o"), tmpl->NewInstance());
19799 v8::Handle<v8::Array> result = v8::Handle<v8::Array>::Cast(CompileRun(
19800 "var result = []; for (var k in o) result.push(k); result"));
19801 CHECK_EQ(1, result->Length());
19802 CHECK_EQ(v8_str("universalAnswer"), result->Get(0));
19803}
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +000019804
19805
19806TEST(DefinePropertyPostDetach) {
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +000019807 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000019808 v8::HandleScope scope(context->GetIsolate());
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +000019809 v8::Handle<v8::Object> proxy = context->Global();
19810 v8::Handle<v8::Function> define_property =
19811 CompileRun("(function() {"
19812 " Object.defineProperty("
19813 " this,"
19814 " 1,"
19815 " { configurable: true, enumerable: true, value: 3 });"
19816 "})").As<Function>();
19817 context->DetachGlobal();
19818 define_property->Call(proxy, 0, NULL);
19819}
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000019820
19821
19822static void InstallContextId(v8::Handle<Context> context, int id) {
19823 Context::Scope scope(context);
19824 CompileRun("Object.prototype").As<Object>()->
ulan@chromium.org0f13e742014-01-03 15:51:11 +000019825 Set(v8_str("context_id"), v8::Integer::New(context->GetIsolate(), id));
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000019826}
19827
19828
19829static void CheckContextId(v8::Handle<Object> object, int expected) {
19830 CHECK_EQ(expected, object->Get(v8_str("context_id"))->Int32Value());
19831}
19832
19833
19834THREADED_TEST(CreationContext) {
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000019835 v8::Isolate* isolate = CcTest::isolate();
19836 HandleScope handle_scope(isolate);
19837 Handle<Context> context1 = Context::New(isolate);
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000019838 InstallContextId(context1, 1);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000019839 Handle<Context> context2 = Context::New(isolate);
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000019840 InstallContextId(context2, 2);
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000019841 Handle<Context> context3 = Context::New(isolate);
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000019842 InstallContextId(context3, 3);
19843
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000019844 Local<v8::FunctionTemplate> tmpl = v8::FunctionTemplate::New(isolate);
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000019845
19846 Local<Object> object1;
19847 Local<Function> func1;
19848 {
19849 Context::Scope scope(context1);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000019850 object1 = Object::New(isolate);
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000019851 func1 = tmpl->GetFunction();
19852 }
19853
19854 Local<Object> object2;
19855 Local<Function> func2;
19856 {
19857 Context::Scope scope(context2);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000019858 object2 = Object::New(isolate);
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000019859 func2 = tmpl->GetFunction();
19860 }
19861
19862 Local<Object> instance1;
19863 Local<Object> instance2;
19864
19865 {
19866 Context::Scope scope(context3);
19867 instance1 = func1->NewInstance();
19868 instance2 = func2->NewInstance();
19869 }
19870
19871 CHECK(object1->CreationContext() == context1);
19872 CheckContextId(object1, 1);
19873 CHECK(func1->CreationContext() == context1);
19874 CheckContextId(func1, 1);
19875 CHECK(instance1->CreationContext() == context1);
19876 CheckContextId(instance1, 1);
19877 CHECK(object2->CreationContext() == context2);
19878 CheckContextId(object2, 2);
19879 CHECK(func2->CreationContext() == context2);
19880 CheckContextId(func2, 2);
19881 CHECK(instance2->CreationContext() == context2);
19882 CheckContextId(instance2, 2);
19883
19884 {
19885 Context::Scope scope(context1);
19886 CHECK(object1->CreationContext() == context1);
19887 CheckContextId(object1, 1);
19888 CHECK(func1->CreationContext() == context1);
19889 CheckContextId(func1, 1);
19890 CHECK(instance1->CreationContext() == context1);
19891 CheckContextId(instance1, 1);
19892 CHECK(object2->CreationContext() == context2);
19893 CheckContextId(object2, 2);
19894 CHECK(func2->CreationContext() == context2);
19895 CheckContextId(func2, 2);
19896 CHECK(instance2->CreationContext() == context2);
19897 CheckContextId(instance2, 2);
19898 }
19899
19900 {
19901 Context::Scope scope(context2);
19902 CHECK(object1->CreationContext() == context1);
19903 CheckContextId(object1, 1);
19904 CHECK(func1->CreationContext() == context1);
19905 CheckContextId(func1, 1);
19906 CHECK(instance1->CreationContext() == context1);
19907 CheckContextId(instance1, 1);
19908 CHECK(object2->CreationContext() == context2);
19909 CheckContextId(object2, 2);
19910 CHECK(func2->CreationContext() == context2);
19911 CheckContextId(func2, 2);
19912 CHECK(instance2->CreationContext() == context2);
19913 CheckContextId(instance2, 2);
19914 }
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000019915}
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019916
19917
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +000019918THREADED_TEST(CreationContextOfJsFunction) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000019919 HandleScope handle_scope(CcTest::isolate());
19920 Handle<Context> context = Context::New(CcTest::isolate());
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +000019921 InstallContextId(context, 1);
19922
19923 Local<Object> function;
19924 {
19925 Context::Scope scope(context);
19926 function = CompileRun("function foo() {}; foo").As<Object>();
19927 }
19928
19929 CHECK(function->CreationContext() == context);
19930 CheckContextId(function, 1);
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +000019931}
19932
19933
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000019934void HasOwnPropertyIndexedPropertyGetter(
19935 uint32_t index,
19936 const v8::PropertyCallbackInfo<v8::Value>& info) {
19937 if (index == 42) info.GetReturnValue().Set(v8_str("yes"));
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019938}
19939
19940
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000019941void HasOwnPropertyNamedPropertyGetter(
19942 Local<String> property,
19943 const v8::PropertyCallbackInfo<v8::Value>& info) {
19944 if (property->Equals(v8_str("foo"))) info.GetReturnValue().Set(v8_str("yes"));
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019945}
19946
19947
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000019948void HasOwnPropertyIndexedPropertyQuery(
19949 uint32_t index, const v8::PropertyCallbackInfo<v8::Integer>& info) {
19950 if (index == 42) info.GetReturnValue().Set(1);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019951}
19952
19953
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000019954void HasOwnPropertyNamedPropertyQuery(
19955 Local<String> property,
19956 const v8::PropertyCallbackInfo<v8::Integer>& info) {
19957 if (property->Equals(v8_str("foo"))) info.GetReturnValue().Set(1);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019958}
19959
19960
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000019961void HasOwnPropertyNamedPropertyQuery2(
19962 Local<String> property,
19963 const v8::PropertyCallbackInfo<v8::Integer>& info) {
19964 if (property->Equals(v8_str("bar"))) info.GetReturnValue().Set(1);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019965}
19966
19967
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000019968void HasOwnPropertyAccessorGetter(
19969 Local<String> property,
19970 const v8::PropertyCallbackInfo<v8::Value>& info) {
19971 info.GetReturnValue().Set(v8_str("yes"));
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019972}
19973
19974
19975TEST(HasOwnProperty) {
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019976 LocalContext env;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000019977 v8::Isolate* isolate = env->GetIsolate();
19978 v8::HandleScope scope(isolate);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000019979 { // Check normal properties and defined getters.
19980 Handle<Value> value = CompileRun(
19981 "function Foo() {"
19982 " this.foo = 11;"
19983 " this.__defineGetter__('baz', function() { return 1; });"
19984 "};"
19985 "function Bar() { "
19986 " this.bar = 13;"
19987 " this.__defineGetter__('bla', function() { return 2; });"
19988 "};"
19989 "Bar.prototype = new Foo();"
19990 "new Bar();");
19991 CHECK(value->IsObject());
19992 Handle<Object> object = value->ToObject();
19993 CHECK(object->Has(v8_str("foo")));
19994 CHECK(!object->HasOwnProperty(v8_str("foo")));
19995 CHECK(object->HasOwnProperty(v8_str("bar")));
19996 CHECK(object->Has(v8_str("baz")));
19997 CHECK(!object->HasOwnProperty(v8_str("baz")));
19998 CHECK(object->HasOwnProperty(v8_str("bla")));
19999 }
20000 { // Check named getter interceptors.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000020001 Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000020002 templ->SetNamedPropertyHandler(HasOwnPropertyNamedPropertyGetter);
20003 Handle<Object> instance = templ->NewInstance();
20004 CHECK(!instance->HasOwnProperty(v8_str("42")));
20005 CHECK(instance->HasOwnProperty(v8_str("foo")));
20006 CHECK(!instance->HasOwnProperty(v8_str("bar")));
20007 }
20008 { // Check indexed getter interceptors.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000020009 Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000020010 templ->SetIndexedPropertyHandler(HasOwnPropertyIndexedPropertyGetter);
20011 Handle<Object> instance = templ->NewInstance();
20012 CHECK(instance->HasOwnProperty(v8_str("42")));
20013 CHECK(!instance->HasOwnProperty(v8_str("43")));
20014 CHECK(!instance->HasOwnProperty(v8_str("foo")));
20015 }
20016 { // Check named query interceptors.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000020017 Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000020018 templ->SetNamedPropertyHandler(0, 0, HasOwnPropertyNamedPropertyQuery);
20019 Handle<Object> instance = templ->NewInstance();
20020 CHECK(instance->HasOwnProperty(v8_str("foo")));
20021 CHECK(!instance->HasOwnProperty(v8_str("bar")));
20022 }
20023 { // Check indexed query interceptors.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000020024 Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000020025 templ->SetIndexedPropertyHandler(0, 0, HasOwnPropertyIndexedPropertyQuery);
20026 Handle<Object> instance = templ->NewInstance();
20027 CHECK(instance->HasOwnProperty(v8_str("42")));
20028 CHECK(!instance->HasOwnProperty(v8_str("41")));
20029 }
20030 { // Check callbacks.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000020031 Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000020032 templ->SetAccessor(v8_str("foo"), HasOwnPropertyAccessorGetter);
20033 Handle<Object> instance = templ->NewInstance();
20034 CHECK(instance->HasOwnProperty(v8_str("foo")));
20035 CHECK(!instance->HasOwnProperty(v8_str("bar")));
20036 }
20037 { // Check that query wins on disagreement.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000020038 Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +000020039 templ->SetNamedPropertyHandler(HasOwnPropertyNamedPropertyGetter,
20040 0,
20041 HasOwnPropertyNamedPropertyQuery2);
20042 Handle<Object> instance = templ->NewInstance();
20043 CHECK(!instance->HasOwnProperty(v8_str("foo")));
20044 CHECK(instance->HasOwnProperty(v8_str("bar")));
20045 }
20046}
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000020047
20048
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +000020049TEST(IndexedInterceptorWithStringProto) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000020050 v8::Isolate* isolate = CcTest::isolate();
20051 v8::HandleScope scope(isolate);
20052 Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +000020053 templ->SetIndexedPropertyHandler(NULL,
20054 NULL,
20055 HasOwnPropertyIndexedPropertyQuery);
20056 LocalContext context;
20057 context->Global()->Set(v8_str("obj"), templ->NewInstance());
20058 CompileRun("var s = new String('foobar'); obj.__proto__ = s;");
20059 // These should be intercepted.
20060 CHECK(CompileRun("42 in obj")->BooleanValue());
20061 CHECK(CompileRun("'42' in obj")->BooleanValue());
20062 // These should fall through to the String prototype.
20063 CHECK(CompileRun("0 in obj")->BooleanValue());
20064 CHECK(CompileRun("'0' in obj")->BooleanValue());
20065 // And these should both fail.
20066 CHECK(!CompileRun("32 in obj")->BooleanValue());
20067 CHECK(!CompileRun("'32' in obj")->BooleanValue());
20068}
20069
20070
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000020071void CheckCodeGenerationAllowed() {
20072 Handle<Value> result = CompileRun("eval('42')");
20073 CHECK_EQ(42, result->Int32Value());
20074 result = CompileRun("(function(e) { return e('42'); })(eval)");
20075 CHECK_EQ(42, result->Int32Value());
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000020076 result = CompileRun("var f = new Function('return 42'); f()");
20077 CHECK_EQ(42, result->Int32Value());
20078}
20079
20080
20081void CheckCodeGenerationDisallowed() {
20082 TryCatch try_catch;
20083
20084 Handle<Value> result = CompileRun("eval('42')");
20085 CHECK(result.IsEmpty());
20086 CHECK(try_catch.HasCaught());
20087 try_catch.Reset();
20088
20089 result = CompileRun("(function(e) { return e('42'); })(eval)");
20090 CHECK(result.IsEmpty());
20091 CHECK(try_catch.HasCaught());
20092 try_catch.Reset();
20093
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000020094 result = CompileRun("var f = new Function('return 42'); f()");
20095 CHECK(result.IsEmpty());
20096 CHECK(try_catch.HasCaught());
20097}
20098
20099
20100bool CodeGenerationAllowed(Local<Context> context) {
20101 ApiTestFuzzer::Fuzz();
20102 return true;
20103}
20104
20105
20106bool CodeGenerationDisallowed(Local<Context> context) {
20107 ApiTestFuzzer::Fuzz();
20108 return false;
20109}
20110
20111
20112THREADED_TEST(AllowCodeGenFromStrings) {
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000020113 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020114 v8::HandleScope scope(context->GetIsolate());
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000020115
ager@chromium.orgea91cc52011-05-23 06:06:11 +000020116 // eval and the Function constructor allowed by default.
jkummerow@chromium.org1145ef82012-02-02 16:21:15 +000020117 CHECK(context->IsCodeGenerationFromStringsAllowed());
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000020118 CheckCodeGenerationAllowed();
20119
ager@chromium.orgea91cc52011-05-23 06:06:11 +000020120 // Disallow eval and the Function constructor.
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000020121 context->AllowCodeGenerationFromStrings(false);
jkummerow@chromium.org1145ef82012-02-02 16:21:15 +000020122 CHECK(!context->IsCodeGenerationFromStringsAllowed());
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000020123 CheckCodeGenerationDisallowed();
20124
20125 // Allow again.
20126 context->AllowCodeGenerationFromStrings(true);
20127 CheckCodeGenerationAllowed();
20128
20129 // Disallow but setting a global callback that will allow the calls.
20130 context->AllowCodeGenerationFromStrings(false);
20131 V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationAllowed);
jkummerow@chromium.org1145ef82012-02-02 16:21:15 +000020132 CHECK(!context->IsCodeGenerationFromStringsAllowed());
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000020133 CheckCodeGenerationAllowed();
20134
20135 // Set a callback that disallows the code generation.
20136 V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationDisallowed);
jkummerow@chromium.org1145ef82012-02-02 16:21:15 +000020137 CHECK(!context->IsCodeGenerationFromStringsAllowed());
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000020138 CheckCodeGenerationDisallowed();
20139}
lrn@chromium.org1c092762011-05-09 09:42:16 +000020140
20141
ulan@chromium.org56c14af2012-09-20 12:51:09 +000020142TEST(SetErrorMessageForCodeGenFromStrings) {
ulan@chromium.org56c14af2012-09-20 12:51:09 +000020143 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020144 v8::HandleScope scope(context->GetIsolate());
ulan@chromium.org56c14af2012-09-20 12:51:09 +000020145 TryCatch try_catch;
20146
20147 Handle<String> message = v8_str("Message") ;
20148 Handle<String> expected_message = v8_str("Uncaught EvalError: Message");
20149 V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationDisallowed);
20150 context->AllowCodeGenerationFromStrings(false);
20151 context->SetErrorMessageForCodeGenerationFromStrings(message);
20152 Handle<Value> result = CompileRun("eval('42')");
20153 CHECK(result.IsEmpty());
20154 CHECK(try_catch.HasCaught());
20155 Handle<String> actual_message = try_catch.Message()->Get();
20156 CHECK(expected_message->Equals(actual_message));
20157}
20158
20159
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000020160static void NonObjectThis(const v8::FunctionCallbackInfo<v8::Value>& args) {
lrn@chromium.org1c092762011-05-09 09:42:16 +000020161}
20162
20163
20164THREADED_TEST(CallAPIFunctionOnNonObject) {
lrn@chromium.org1c092762011-05-09 09:42:16 +000020165 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000020166 v8::Isolate* isolate = context->GetIsolate();
20167 v8::HandleScope scope(isolate);
20168 Handle<FunctionTemplate> templ =
20169 v8::FunctionTemplate::New(isolate, NonObjectThis);
lrn@chromium.org1c092762011-05-09 09:42:16 +000020170 Handle<Function> function = templ->GetFunction();
20171 context->Global()->Set(v8_str("f"), function);
20172 TryCatch try_catch;
20173 CompileRun("f.call(2)");
lrn@chromium.org1c092762011-05-09 09:42:16 +000020174}
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000020175
20176
20177// Regression test for issue 1470.
20178THREADED_TEST(ReadOnlyIndexedProperties) {
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000020179 v8::Isolate* isolate = CcTest::isolate();
20180 v8::HandleScope scope(isolate);
20181 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000020182
20183 LocalContext context;
20184 Local<v8::Object> obj = templ->NewInstance();
20185 context->Global()->Set(v8_str("obj"), obj);
20186 obj->Set(v8_str("1"), v8_str("DONT_CHANGE"), v8::ReadOnly);
20187 obj->Set(v8_str("1"), v8_str("foobar"));
20188 CHECK_EQ(v8_str("DONT_CHANGE"), obj->Get(v8_str("1")));
20189 obj->Set(v8_num(2), v8_str("DONT_CHANGE"), v8::ReadOnly);
20190 obj->Set(v8_num(2), v8_str("foobar"));
20191 CHECK_EQ(v8_str("DONT_CHANGE"), obj->Get(v8_num(2)));
20192
20193 // Test non-smi case.
20194 obj->Set(v8_str("2000000000"), v8_str("DONT_CHANGE"), v8::ReadOnly);
20195 obj->Set(v8_str("2000000000"), v8_str("foobar"));
20196 CHECK_EQ(v8_str("DONT_CHANGE"), obj->Get(v8_str("2000000000")));
20197}
ricow@chromium.org4f693d62011-07-04 14:01:31 +000020198
20199
20200THREADED_TEST(Regress1516) {
ricow@chromium.org4f693d62011-07-04 14:01:31 +000020201 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020202 v8::HandleScope scope(context->GetIsolate());
20203
20204 { v8::HandleScope temp_scope(context->GetIsolate());
ricow@chromium.org4f693d62011-07-04 14:01:31 +000020205 CompileRun("({'a': 0})");
20206 }
20207
20208 int elements;
20209 { i::MapCache* map_cache =
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020210 i::MapCache::cast(CcTest::i_isolate()->context()->map_cache());
ricow@chromium.org4f693d62011-07-04 14:01:31 +000020211 elements = map_cache->NumberOfElements();
20212 CHECK_LE(1, elements);
20213 }
20214
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020215 CcTest::heap()->CollectAllGarbage(
yangguo@chromium.orgd2899aa2012-06-21 11:16:20 +000020216 i::Heap::kAbortIncrementalMarkingMask);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020217 { i::Object* raw_map_cache = CcTest::i_isolate()->context()->map_cache();
20218 if (raw_map_cache != CcTest::heap()->undefined_value()) {
ricow@chromium.org4f693d62011-07-04 14:01:31 +000020219 i::MapCache* map_cache = i::MapCache::cast(raw_map_cache);
20220 CHECK_GT(elements, map_cache->NumberOfElements());
20221 }
20222 }
20223}
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020224
20225
20226static bool BlockProtoNamedSecurityTestCallback(Local<v8::Object> global,
20227 Local<Value> name,
20228 v8::AccessType type,
20229 Local<Value> data) {
20230 // Only block read access to __proto__.
20231 if (type == v8::ACCESS_GET &&
20232 name->IsString() &&
20233 name->ToString()->Length() == 9 &&
20234 name->ToString()->Utf8Length() == 9) {
20235 char buffer[10];
20236 CHECK_EQ(10, name->ToString()->WriteUtf8(buffer));
20237 return strncmp(buffer, "__proto__", 9) != 0;
20238 }
20239
20240 return true;
20241}
20242
20243
20244THREADED_TEST(Regress93759) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020245 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000020246 HandleScope scope(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020247
20248 // Template for object with security check.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000020249 Local<ObjectTemplate> no_proto_template = v8::ObjectTemplate::New(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020250 // We don't do indexing, so any callback can be used for that.
20251 no_proto_template->SetAccessCheckCallbacks(
20252 BlockProtoNamedSecurityTestCallback,
20253 IndexedSecurityTestCallback);
20254
20255 // Templates for objects with hidden prototypes and possibly security check.
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000020256 Local<FunctionTemplate> hidden_proto_template =
20257 v8::FunctionTemplate::New(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020258 hidden_proto_template->SetHiddenPrototype(true);
20259
20260 Local<FunctionTemplate> protected_hidden_proto_template =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000020261 v8::FunctionTemplate::New(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020262 protected_hidden_proto_template->InstanceTemplate()->SetAccessCheckCallbacks(
20263 BlockProtoNamedSecurityTestCallback,
20264 IndexedSecurityTestCallback);
20265 protected_hidden_proto_template->SetHiddenPrototype(true);
20266
20267 // Context for "foreign" objects used in test.
ulan@chromium.org57ff8812013-05-10 08:16:55 +000020268 Local<Context> context = v8::Context::New(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020269 context->Enter();
20270
20271 // Plain object, no security check.
ulan@chromium.org0f13e742014-01-03 15:51:11 +000020272 Local<Object> simple_object = Object::New(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020273
20274 // Object with explicit security check.
20275 Local<Object> protected_object =
20276 no_proto_template->NewInstance();
20277
20278 // JSGlobalProxy object, always have security check.
20279 Local<Object> proxy_object =
20280 context->Global();
20281
20282 // Global object, the prototype of proxy_object. No security checks.
20283 Local<Object> global_object =
20284 proxy_object->GetPrototype()->ToObject();
20285
20286 // Hidden prototype without security check.
20287 Local<Object> hidden_prototype =
20288 hidden_proto_template->GetFunction()->NewInstance();
20289 Local<Object> object_with_hidden =
ulan@chromium.org0f13e742014-01-03 15:51:11 +000020290 Object::New(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020291 object_with_hidden->SetPrototype(hidden_prototype);
20292
20293 // Hidden prototype with security check on the hidden prototype.
20294 Local<Object> protected_hidden_prototype =
20295 protected_hidden_proto_template->GetFunction()->NewInstance();
20296 Local<Object> object_with_protected_hidden =
ulan@chromium.org0f13e742014-01-03 15:51:11 +000020297 Object::New(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020298 object_with_protected_hidden->SetPrototype(protected_hidden_prototype);
20299
20300 context->Exit();
20301
20302 // Template for object for second context. Values to test are put on it as
20303 // properties.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000020304 Local<ObjectTemplate> global_template = ObjectTemplate::New(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020305 global_template->Set(v8_str("simple"), simple_object);
20306 global_template->Set(v8_str("protected"), protected_object);
20307 global_template->Set(v8_str("global"), global_object);
20308 global_template->Set(v8_str("proxy"), proxy_object);
20309 global_template->Set(v8_str("hidden"), object_with_hidden);
20310 global_template->Set(v8_str("phidden"), object_with_protected_hidden);
20311
20312 LocalContext context2(NULL, global_template);
20313
20314 Local<Value> result1 = CompileRun("Object.getPrototypeOf(simple)");
20315 CHECK(result1->Equals(simple_object->GetPrototype()));
20316
20317 Local<Value> result2 = CompileRun("Object.getPrototypeOf(protected)");
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000020318 CHECK(result2->Equals(Undefined(isolate)));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020319
20320 Local<Value> result3 = CompileRun("Object.getPrototypeOf(global)");
20321 CHECK(result3->Equals(global_object->GetPrototype()));
20322
20323 Local<Value> result4 = CompileRun("Object.getPrototypeOf(proxy)");
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000020324 CHECK(result4->Equals(Undefined(isolate)));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020325
20326 Local<Value> result5 = CompileRun("Object.getPrototypeOf(hidden)");
20327 CHECK(result5->Equals(
20328 object_with_hidden->GetPrototype()->ToObject()->GetPrototype()));
20329
20330 Local<Value> result6 = CompileRun("Object.getPrototypeOf(phidden)");
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000020331 CHECK(result6->Equals(Undefined(isolate)));
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020332}
20333
20334
jkummerow@chromium.org212d9642012-05-11 15:02:09 +000020335THREADED_TEST(Regress125988) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020336 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000020337 Handle<FunctionTemplate> intercept = FunctionTemplate::New(CcTest::isolate());
jkummerow@chromium.org212d9642012-05-11 15:02:09 +000020338 AddInterceptor(intercept, EmptyInterceptorGetter, EmptyInterceptorSetter);
20339 LocalContext env;
20340 env->Global()->Set(v8_str("Intercept"), intercept->GetFunction());
20341 CompileRun("var a = new Object();"
20342 "var b = new Intercept();"
20343 "var c = new Object();"
20344 "c.__proto__ = b;"
20345 "b.__proto__ = a;"
20346 "a.x = 23;"
20347 "for (var i = 0; i < 3; i++) c.x;");
20348 ExpectBoolean("c.hasOwnProperty('x')", false);
20349 ExpectInt32("c.x", 23);
20350 CompileRun("a.y = 42;"
20351 "for (var i = 0; i < 3; i++) c.x;");
20352 ExpectBoolean("c.hasOwnProperty('x')", false);
20353 ExpectInt32("c.x", 23);
20354 ExpectBoolean("c.hasOwnProperty('y')", false);
20355 ExpectInt32("c.y", 42);
20356}
20357
20358
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020359static void TestReceiver(Local<Value> expected_result,
20360 Local<Value> expected_receiver,
20361 const char* code) {
20362 Local<Value> result = CompileRun(code);
20363 CHECK(result->IsObject());
20364 CHECK(expected_receiver->Equals(result->ToObject()->Get(1)));
20365 CHECK(expected_result->Equals(result->ToObject()->Get(0)));
20366}
20367
20368
20369THREADED_TEST(ForeignFunctionReceiver) {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020370 v8::Isolate* isolate = CcTest::isolate();
ulan@chromium.org57ff8812013-05-10 08:16:55 +000020371 HandleScope scope(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020372
20373 // Create two contexts with different "id" properties ('i' and 'o').
20374 // Call a function both from its own context and from a the foreign
20375 // context, and see what "this" is bound to (returning both "this"
20376 // and "this.id" for comparison).
20377
ulan@chromium.org57ff8812013-05-10 08:16:55 +000020378 Local<Context> foreign_context = v8::Context::New(isolate);
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020379 foreign_context->Enter();
20380 Local<Value> foreign_function =
20381 CompileRun("function func() { return { 0: this.id, "
20382 " 1: this, "
20383 " toString: function() { "
20384 " return this[0];"
20385 " }"
20386 " };"
20387 "}"
20388 "var id = 'i';"
20389 "func;");
20390 CHECK(foreign_function->IsFunction());
20391 foreign_context->Exit();
20392
20393 LocalContext context;
20394
20395 Local<String> password = v8_str("Password");
20396 // Don't get hit by security checks when accessing foreign_context's
20397 // global receiver (aka. global proxy).
20398 context->SetSecurityToken(password);
20399 foreign_context->SetSecurityToken(password);
20400
20401 Local<String> i = v8_str("i");
20402 Local<String> o = v8_str("o");
20403 Local<String> id = v8_str("id");
20404
20405 CompileRun("function ownfunc() { return { 0: this.id, "
20406 " 1: this, "
20407 " toString: function() { "
20408 " return this[0];"
20409 " }"
20410 " };"
20411 "}"
20412 "var id = 'o';"
20413 "ownfunc");
20414 context->Global()->Set(v8_str("func"), foreign_function);
20415
20416 // Sanity check the contexts.
20417 CHECK(i->Equals(foreign_context->Global()->Get(id)));
20418 CHECK(o->Equals(context->Global()->Get(id)));
20419
20420 // Checking local function's receiver.
20421 // Calling function using its call/apply methods.
20422 TestReceiver(o, context->Global(), "ownfunc.call()");
20423 TestReceiver(o, context->Global(), "ownfunc.apply()");
20424 // Making calls through built-in functions.
20425 TestReceiver(o, context->Global(), "[1].map(ownfunc)[0]");
20426 CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/,ownfunc)[1]")));
20427 CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/g,ownfunc)[1]")));
20428 CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/g,ownfunc)[3]")));
20429 // Calling with environment record as base.
20430 TestReceiver(o, context->Global(), "ownfunc()");
20431 // Calling with no base.
20432 TestReceiver(o, context->Global(), "(1,ownfunc)()");
20433
20434 // Checking foreign function return value.
20435 // Calling function using its call/apply methods.
20436 TestReceiver(i, foreign_context->Global(), "func.call()");
20437 TestReceiver(i, foreign_context->Global(), "func.apply()");
20438 // Calling function using another context's call/apply methods.
20439 TestReceiver(i, foreign_context->Global(),
20440 "Function.prototype.call.call(func)");
20441 TestReceiver(i, foreign_context->Global(),
20442 "Function.prototype.call.apply(func)");
20443 TestReceiver(i, foreign_context->Global(),
20444 "Function.prototype.apply.call(func)");
20445 TestReceiver(i, foreign_context->Global(),
20446 "Function.prototype.apply.apply(func)");
20447 // Making calls through built-in functions.
20448 TestReceiver(i, foreign_context->Global(), "[1].map(func)[0]");
20449 // ToString(func()) is func()[0], i.e., the returned this.id.
20450 CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/,func)[1]")));
20451 CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/g,func)[1]")));
20452 CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/g,func)[3]")));
20453
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020454 // Calling with environment record as base.
rossberg@chromium.org9ed27462014-01-07 14:16:41 +000020455 TestReceiver(i, foreign_context->Global(), "func()");
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020456 // Calling with no base.
rossberg@chromium.org9ed27462014-01-07 14:16:41 +000020457 TestReceiver(i, foreign_context->Global(), "(1,func)()");
ricow@chromium.org4668a2c2011-08-29 10:41:00 +000020458}
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020459
20460
20461uint8_t callback_fired = 0;
20462
20463
20464void CallCompletedCallback1() {
20465 i::OS::Print("Firing callback 1.\n");
20466 callback_fired ^= 1; // Toggle first bit.
20467}
20468
20469
20470void CallCompletedCallback2() {
20471 i::OS::Print("Firing callback 2.\n");
20472 callback_fired ^= 2; // Toggle second bit.
20473}
20474
20475
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000020476void RecursiveCall(const v8::FunctionCallbackInfo<v8::Value>& args) {
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020477 int32_t level = args[0]->Int32Value();
20478 if (level < 3) {
20479 level++;
20480 i::OS::Print("Entering recursion level %d.\n", level);
20481 char script[64];
20482 i::Vector<char> script_vector(script, sizeof(script));
20483 i::OS::SNPrintF(script_vector, "recursion(%d)", level);
20484 CompileRun(script_vector.start());
20485 i::OS::Print("Leaving recursion level %d.\n", level);
20486 CHECK_EQ(0, callback_fired);
20487 } else {
20488 i::OS::Print("Recursion ends.\n");
20489 CHECK_EQ(0, callback_fired);
20490 }
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020491}
20492
20493
20494TEST(CallCompletedCallback) {
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020495 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020496 v8::HandleScope scope(env->GetIsolate());
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020497 v8::Handle<v8::FunctionTemplate> recursive_runtime =
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000020498 v8::FunctionTemplate::New(env->GetIsolate(), RecursiveCall);
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020499 env->Global()->Set(v8_str("recursion"),
20500 recursive_runtime->GetFunction());
20501 // Adding the same callback a second time has no effect.
20502 v8::V8::AddCallCompletedCallback(CallCompletedCallback1);
20503 v8::V8::AddCallCompletedCallback(CallCompletedCallback1);
20504 v8::V8::AddCallCompletedCallback(CallCompletedCallback2);
20505 i::OS::Print("--- Script (1) ---\n");
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000020506 Local<Script> script = v8::Script::Compile(
20507 v8::String::NewFromUtf8(env->GetIsolate(), "recursion(0)"));
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020508 script->Run();
20509 CHECK_EQ(3, callback_fired);
20510
20511 i::OS::Print("\n--- Script (2) ---\n");
20512 callback_fired = 0;
20513 v8::V8::RemoveCallCompletedCallback(CallCompletedCallback1);
20514 script->Run();
20515 CHECK_EQ(2, callback_fired);
20516
20517 i::OS::Print("\n--- Function ---\n");
20518 callback_fired = 0;
20519 Local<Function> recursive_function =
20520 Local<Function>::Cast(env->Global()->Get(v8_str("recursion")));
20521 v8::Handle<Value> args[] = { v8_num(0) };
20522 recursive_function->Call(env->Global(), 1, args);
20523 CHECK_EQ(2, callback_fired);
20524}
20525
20526
20527void CallCompletedCallbackNoException() {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020528 v8::HandleScope scope(CcTest::isolate());
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020529 CompileRun("1+1;");
20530}
20531
20532
20533void CallCompletedCallbackException() {
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020534 v8::HandleScope scope(CcTest::isolate());
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020535 CompileRun("throw 'second exception';");
20536}
20537
20538
20539TEST(CallCompletedCallbackOneException) {
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020540 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020541 v8::HandleScope scope(env->GetIsolate());
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020542 v8::V8::AddCallCompletedCallback(CallCompletedCallbackNoException);
20543 CompileRun("throw 'exception';");
20544}
20545
20546
20547TEST(CallCompletedCallbackTwoExceptions) {
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020548 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020549 v8::HandleScope scope(env->GetIsolate());
rossberg@chromium.orgfab14982012-01-05 15:02:15 +000020550 v8::V8::AddCallCompletedCallback(CallCompletedCallbackException);
20551 CompileRun("throw 'first exception';");
20552}
ulan@chromium.org812308e2012-02-29 15:58:45 +000020553
20554
20555static int probes_counter = 0;
20556static int misses_counter = 0;
20557static int updates_counter = 0;
20558
20559
20560static int* LookupCounter(const char* name) {
20561 if (strcmp(name, "c:V8.MegamorphicStubCacheProbes") == 0) {
20562 return &probes_counter;
20563 } else if (strcmp(name, "c:V8.MegamorphicStubCacheMisses") == 0) {
20564 return &misses_counter;
20565 } else if (strcmp(name, "c:V8.MegamorphicStubCacheUpdates") == 0) {
20566 return &updates_counter;
20567 }
20568 return NULL;
20569}
20570
20571
20572static const char* kMegamorphicTestProgram =
20573 "function ClassA() { };"
20574 "function ClassB() { };"
20575 "ClassA.prototype.foo = function() { };"
20576 "ClassB.prototype.foo = function() { };"
20577 "function fooify(obj) { obj.foo(); };"
20578 "var a = new ClassA();"
20579 "var b = new ClassB();"
20580 "for (var i = 0; i < 10000; i++) {"
20581 " fooify(a);"
20582 " fooify(b);"
20583 "}";
20584
20585
20586static void StubCacheHelper(bool primary) {
20587 V8::SetCounterFunction(LookupCounter);
20588 USE(kMegamorphicTestProgram);
20589#ifdef DEBUG
20590 i::FLAG_native_code_counters = true;
20591 if (primary) {
20592 i::FLAG_test_primary_stub_cache = true;
20593 } else {
20594 i::FLAG_test_secondary_stub_cache = true;
20595 }
20596 i::FLAG_crankshaft = false;
ulan@chromium.org812308e2012-02-29 15:58:45 +000020597 LocalContext env;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020598 v8::HandleScope scope(env->GetIsolate());
ulan@chromium.org812308e2012-02-29 15:58:45 +000020599 int initial_probes = probes_counter;
20600 int initial_misses = misses_counter;
20601 int initial_updates = updates_counter;
20602 CompileRun(kMegamorphicTestProgram);
20603 int probes = probes_counter - initial_probes;
20604 int misses = misses_counter - initial_misses;
20605 int updates = updates_counter - initial_updates;
20606 CHECK_LT(updates, 10);
20607 CHECK_LT(misses, 10);
machenbach@chromium.orga03ba1e2014-02-01 08:54:43 +000020608 // TODO(verwaest): Update this test to overflow the degree of polymorphism
20609 // before megamorphism. The number of probes will only work once we teach the
20610 // serializer to embed references to counters in the stubs, given that the
20611 // megamorphic_stub_cache_probes is updated in a snapshot-generated stub.
20612 CHECK_GE(probes, 0);
ulan@chromium.org812308e2012-02-29 15:58:45 +000020613#endif
20614}
20615
20616
20617TEST(SecondaryStubCache) {
20618 StubCacheHelper(true);
20619}
20620
20621
20622TEST(PrimaryStubCache) {
20623 StubCacheHelper(false);
20624}
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020625
20626
verwaest@chromium.org057bd502013-11-06 12:03:29 +000020627static int cow_arrays_created_runtime = 0;
20628
20629
20630static int* LookupCounterCOWArrays(const char* name) {
20631 if (strcmp(name, "c:V8.COWArraysCreatedRuntime") == 0) {
20632 return &cow_arrays_created_runtime;
20633 }
20634 return NULL;
20635}
20636
20637
20638TEST(CheckCOWArraysCreatedRuntimeCounter) {
20639 V8::SetCounterFunction(LookupCounterCOWArrays);
20640#ifdef DEBUG
20641 i::FLAG_native_code_counters = true;
20642 LocalContext env;
20643 v8::HandleScope scope(env->GetIsolate());
20644 int initial_cow_arrays = cow_arrays_created_runtime;
20645 CompileRun("var o = [1, 2, 3];");
20646 CHECK_EQ(1, cow_arrays_created_runtime - initial_cow_arrays);
20647 CompileRun("var o = {foo: [4, 5, 6], bar: [3, 0]};");
20648 CHECK_EQ(3, cow_arrays_created_runtime - initial_cow_arrays);
20649 CompileRun("var o = {foo: [1, 2, 3, [4, 5, 6]], bar: 'hi'};");
20650 CHECK_EQ(4, cow_arrays_created_runtime - initial_cow_arrays);
20651#endif
20652}
20653
20654
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020655TEST(StaticGetters) {
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020656 LocalContext context;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020657 i::Factory* factory = CcTest::i_isolate()->factory();
20658 v8::Isolate* isolate = CcTest::isolate();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020659 v8::HandleScope scope(isolate);
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000020660 i::Handle<i::Object> undefined_value = factory->undefined_value();
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020661 CHECK(*v8::Utils::OpenHandle(*v8::Undefined(isolate)) == *undefined_value);
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000020662 i::Handle<i::Object> null_value = factory->null_value();
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020663 CHECK(*v8::Utils::OpenHandle(*v8::Null(isolate)) == *null_value);
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000020664 i::Handle<i::Object> true_value = factory->true_value();
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020665 CHECK(*v8::Utils::OpenHandle(*v8::True(isolate)) == *true_value);
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000020666 i::Handle<i::Object> false_value = factory->false_value();
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020667 CHECK(*v8::Utils::OpenHandle(*v8::False(isolate)) == *false_value);
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020668}
20669
20670
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020671UNINITIALIZED_TEST(IsolateEmbedderData) {
20672 CcTest::DisableAutomaticDispose();
20673 v8::Isolate* isolate = v8::Isolate::New();
20674 isolate->Enter();
hpayer@chromium.orgc5d49712013-09-11 08:25:48 +000020675 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
machenbach@chromium.org7ff76072013-11-21 09:47:43 +000020676 for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
20677 CHECK_EQ(NULL, isolate->GetData(slot));
20678 CHECK_EQ(NULL, i_isolate->GetData(slot));
20679 }
20680 for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
20681 void* data = reinterpret_cast<void*>(0xacce55ed + slot);
20682 isolate->SetData(slot, data);
20683 }
20684 for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
20685 void* data = reinterpret_cast<void*>(0xacce55ed + slot);
20686 CHECK_EQ(data, isolate->GetData(slot));
20687 CHECK_EQ(data, i_isolate->GetData(slot));
20688 }
20689 for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
20690 void* data = reinterpret_cast<void*>(0xdecea5ed + slot);
20691 isolate->SetData(slot, data);
20692 }
20693 for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
20694 void* data = reinterpret_cast<void*>(0xdecea5ed + slot);
20695 CHECK_EQ(data, isolate->GetData(slot));
20696 CHECK_EQ(data, i_isolate->GetData(slot));
20697 }
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020698 isolate->Exit();
20699 isolate->Dispose();
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020700}
20701
20702
20703TEST(StringEmpty) {
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020704 LocalContext context;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020705 i::Factory* factory = CcTest::i_isolate()->factory();
20706 v8::Isolate* isolate = CcTest::isolate();
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020707 v8::HandleScope scope(isolate);
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000020708 i::Handle<i::Object> empty_string = factory->empty_string();
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020709 CHECK(*v8::Utils::OpenHandle(*v8::String::Empty(isolate)) == *empty_string);
yangguo@chromium.orgefdb9d72012-04-26 08:21:05 +000020710}
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020711
20712
20713static int instance_checked_getter_count = 0;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000020714static void InstanceCheckedGetter(
20715 Local<String> name,
20716 const v8::PropertyCallbackInfo<v8::Value>& info) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020717 CHECK_EQ(name, v8_str("foo"));
20718 instance_checked_getter_count++;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000020719 info.GetReturnValue().Set(v8_num(11));
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020720}
20721
20722
20723static int instance_checked_setter_count = 0;
20724static void InstanceCheckedSetter(Local<String> name,
20725 Local<Value> value,
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000020726 const v8::PropertyCallbackInfo<void>& info) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020727 CHECK_EQ(name, v8_str("foo"));
20728 CHECK_EQ(value, v8_num(23));
20729 instance_checked_setter_count++;
20730}
20731
20732
20733static void CheckInstanceCheckedResult(int getters,
20734 int setters,
20735 bool expects_callbacks,
20736 TryCatch* try_catch) {
20737 if (expects_callbacks) {
20738 CHECK(!try_catch->HasCaught());
20739 CHECK_EQ(getters, instance_checked_getter_count);
20740 CHECK_EQ(setters, instance_checked_setter_count);
20741 } else {
20742 CHECK(try_catch->HasCaught());
20743 CHECK_EQ(0, instance_checked_getter_count);
20744 CHECK_EQ(0, instance_checked_setter_count);
20745 }
20746 try_catch->Reset();
20747}
20748
20749
20750static void CheckInstanceCheckedAccessors(bool expects_callbacks) {
20751 instance_checked_getter_count = 0;
20752 instance_checked_setter_count = 0;
20753 TryCatch try_catch;
20754
20755 // Test path through generic runtime code.
20756 CompileRun("obj.foo");
20757 CheckInstanceCheckedResult(1, 0, expects_callbacks, &try_catch);
20758 CompileRun("obj.foo = 23");
20759 CheckInstanceCheckedResult(1, 1, expects_callbacks, &try_catch);
20760
20761 // Test path through generated LoadIC and StoredIC.
20762 CompileRun("function test_get(o) { o.foo; }"
20763 "test_get(obj);");
20764 CheckInstanceCheckedResult(2, 1, expects_callbacks, &try_catch);
20765 CompileRun("test_get(obj);");
20766 CheckInstanceCheckedResult(3, 1, expects_callbacks, &try_catch);
20767 CompileRun("test_get(obj);");
20768 CheckInstanceCheckedResult(4, 1, expects_callbacks, &try_catch);
20769 CompileRun("function test_set(o) { o.foo = 23; }"
20770 "test_set(obj);");
20771 CheckInstanceCheckedResult(4, 2, expects_callbacks, &try_catch);
20772 CompileRun("test_set(obj);");
20773 CheckInstanceCheckedResult(4, 3, expects_callbacks, &try_catch);
20774 CompileRun("test_set(obj);");
20775 CheckInstanceCheckedResult(4, 4, expects_callbacks, &try_catch);
20776
20777 // Test path through optimized code.
20778 CompileRun("%OptimizeFunctionOnNextCall(test_get);"
20779 "test_get(obj);");
20780 CheckInstanceCheckedResult(5, 4, expects_callbacks, &try_catch);
20781 CompileRun("%OptimizeFunctionOnNextCall(test_set);"
20782 "test_set(obj);");
20783 CheckInstanceCheckedResult(5, 5, expects_callbacks, &try_catch);
20784
20785 // Cleanup so that closures start out fresh in next check.
20786 CompileRun("%DeoptimizeFunction(test_get);"
20787 "%ClearFunctionTypeFeedback(test_get);"
20788 "%DeoptimizeFunction(test_set);"
20789 "%ClearFunctionTypeFeedback(test_set);");
20790}
20791
20792
20793THREADED_TEST(InstanceCheckOnInstanceAccessor) {
20794 v8::internal::FLAG_allow_natives_syntax = true;
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020795 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020796 v8::HandleScope scope(context->GetIsolate());
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020797
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000020798 Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020799 Local<ObjectTemplate> inst = templ->InstanceTemplate();
20800 inst->SetAccessor(v8_str("foo"),
20801 InstanceCheckedGetter, InstanceCheckedSetter,
20802 Handle<Value>(),
20803 v8::DEFAULT,
20804 v8::None,
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000020805 v8::AccessorSignature::New(context->GetIsolate(), templ));
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020806 context->Global()->Set(v8_str("f"), templ->GetFunction());
20807
20808 printf("Testing positive ...\n");
20809 CompileRun("var obj = new f();");
20810 CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
20811 CheckInstanceCheckedAccessors(true);
20812
20813 printf("Testing negative ...\n");
20814 CompileRun("var obj = {};"
20815 "obj.__proto__ = new f();");
20816 CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
20817 CheckInstanceCheckedAccessors(false);
20818}
20819
20820
20821THREADED_TEST(InstanceCheckOnInstanceAccessorWithInterceptor) {
20822 v8::internal::FLAG_allow_natives_syntax = true;
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020823 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020824 v8::HandleScope scope(context->GetIsolate());
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020825
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000020826 Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020827 Local<ObjectTemplate> inst = templ->InstanceTemplate();
20828 AddInterceptor(templ, EmptyInterceptorGetter, EmptyInterceptorSetter);
20829 inst->SetAccessor(v8_str("foo"),
20830 InstanceCheckedGetter, InstanceCheckedSetter,
20831 Handle<Value>(),
20832 v8::DEFAULT,
20833 v8::None,
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000020834 v8::AccessorSignature::New(context->GetIsolate(), templ));
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020835 context->Global()->Set(v8_str("f"), templ->GetFunction());
20836
20837 printf("Testing positive ...\n");
20838 CompileRun("var obj = new f();");
20839 CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
20840 CheckInstanceCheckedAccessors(true);
20841
20842 printf("Testing negative ...\n");
20843 CompileRun("var obj = {};"
20844 "obj.__proto__ = new f();");
20845 CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
20846 CheckInstanceCheckedAccessors(false);
20847}
20848
20849
20850THREADED_TEST(InstanceCheckOnPrototypeAccessor) {
20851 v8::internal::FLAG_allow_natives_syntax = true;
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020852 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020853 v8::HandleScope scope(context->GetIsolate());
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020854
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000020855 Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020856 Local<ObjectTemplate> proto = templ->PrototypeTemplate();
20857 proto->SetAccessor(v8_str("foo"),
20858 InstanceCheckedGetter, InstanceCheckedSetter,
20859 Handle<Value>(),
20860 v8::DEFAULT,
20861 v8::None,
machenbach@chromium.org9f18d912013-11-28 13:42:41 +000020862 v8::AccessorSignature::New(context->GetIsolate(), templ));
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020863 context->Global()->Set(v8_str("f"), templ->GetFunction());
20864
20865 printf("Testing positive ...\n");
20866 CompileRun("var obj = new f();");
20867 CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
20868 CheckInstanceCheckedAccessors(true);
20869
20870 printf("Testing negative ...\n");
20871 CompileRun("var obj = {};"
20872 "obj.__proto__ = new f();");
20873 CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
20874 CheckInstanceCheckedAccessors(false);
20875
20876 printf("Testing positive with modified prototype chain ...\n");
20877 CompileRun("var obj = new f();"
20878 "var pro = {};"
20879 "pro.__proto__ = obj.__proto__;"
20880 "obj.__proto__ = pro;");
20881 CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
20882 CheckInstanceCheckedAccessors(true);
20883}
20884
20885
20886TEST(TryFinallyMessage) {
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020887 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000020888 v8::HandleScope scope(context->GetIsolate());
mmassi@chromium.org7028c052012-06-13 11:51:58 +000020889 {
20890 // Test that the original error message is not lost if there is a
20891 // recursive call into Javascript is done in the finally block, e.g. to
20892 // initialize an IC. (crbug.com/129171)
20893 TryCatch try_catch;
20894 const char* trigger_ic =
20895 "try { \n"
20896 " throw new Error('test'); \n"
20897 "} finally { \n"
20898 " var x = 0; \n"
20899 " x++; \n" // Trigger an IC initialization here.
20900 "} \n";
20901 CompileRun(trigger_ic);
20902 CHECK(try_catch.HasCaught());
20903 Local<Message> message = try_catch.Message();
20904 CHECK(!message.IsEmpty());
20905 CHECK_EQ(2, message->GetLineNumber());
20906 }
20907
20908 {
20909 // Test that the original exception message is indeed overwritten if
20910 // a new error is thrown in the finally block.
20911 TryCatch try_catch;
20912 const char* throw_again =
20913 "try { \n"
20914 " throw new Error('test'); \n"
20915 "} finally { \n"
20916 " var x = 0; \n"
20917 " x++; \n"
20918 " throw new Error('again'); \n" // This is the new uncaught error.
20919 "} \n";
20920 CompileRun(throw_again);
20921 CHECK(try_catch.HasCaught());
20922 Local<Message> message = try_catch.Message();
20923 CHECK(!message.IsEmpty());
20924 CHECK_EQ(6, message->GetLineNumber());
20925 }
20926}
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000020927
20928
erik.corry@gmail.com88767242012-08-08 14:43:45 +000020929static void Helper137002(bool do_store,
20930 bool polymorphic,
20931 bool remove_accessor,
20932 bool interceptor) {
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000020933 LocalContext context;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000020934 Local<ObjectTemplate> templ = ObjectTemplate::New(context->GetIsolate());
erik.corry@gmail.com88767242012-08-08 14:43:45 +000020935 if (interceptor) {
20936 templ->SetNamedPropertyHandler(FooGetInterceptor, FooSetInterceptor);
20937 } else {
20938 templ->SetAccessor(v8_str("foo"),
20939 GetterWhichReturns42,
20940 SetterWhichSetsYOnThisTo23);
20941 }
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000020942 context->Global()->Set(v8_str("obj"), templ->NewInstance());
20943
20944 // Turn monomorphic on slow object with native accessor, then turn
20945 // polymorphic, finally optimize to create negative lookup and fail.
erik.corry@gmail.com88767242012-08-08 14:43:45 +000020946 CompileRun(do_store ?
20947 "function f(x) { x.foo = void 0; }" :
20948 "function f(x) { return x.foo; }");
20949 CompileRun("obj.y = void 0;");
20950 if (!interceptor) {
20951 CompileRun("%OptimizeObjectForAddingMultipleProperties(obj, 1);");
20952 }
20953 CompileRun("obj.__proto__ = null;"
20954 "f(obj); f(obj); f(obj);");
20955 if (polymorphic) {
20956 CompileRun("f({});");
20957 }
20958 CompileRun("obj.y = void 0;"
20959 "%OptimizeFunctionOnNextCall(f);");
20960 if (remove_accessor) {
20961 CompileRun("delete obj.foo;");
20962 }
20963 CompileRun("var result = f(obj);");
20964 if (do_store) {
20965 CompileRun("result = obj.y;");
20966 }
20967 if (remove_accessor && !interceptor) {
20968 CHECK(context->Global()->Get(v8_str("result"))->IsUndefined());
20969 } else {
20970 CHECK_EQ(do_store ? 23 : 42,
20971 context->Global()->Get(v8_str("result"))->Int32Value());
20972 }
20973}
20974
20975
20976THREADED_TEST(Regress137002a) {
20977 i::FLAG_allow_natives_syntax = true;
20978 i::FLAG_compilation_cache = false;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000020979 v8::HandleScope scope(CcTest::isolate());
erik.corry@gmail.com88767242012-08-08 14:43:45 +000020980 for (int i = 0; i < 16; i++) {
20981 Helper137002(i & 8, i & 4, i & 2, i & 1);
20982 }
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000020983}
20984
20985
20986THREADED_TEST(Regress137002b) {
20987 i::FLAG_allow_natives_syntax = true;
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000020988 LocalContext context;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000020989 v8::Isolate* isolate = context->GetIsolate();
20990 v8::HandleScope scope(isolate);
20991 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000020992 templ->SetAccessor(v8_str("foo"),
20993 GetterWhichReturns42,
20994 SetterWhichSetsYOnThisTo23);
20995 context->Global()->Set(v8_str("obj"), templ->NewInstance());
20996
20997 // Turn monomorphic on slow object with native accessor, then just
20998 // delete the property and fail.
erik.corry@gmail.com88767242012-08-08 14:43:45 +000020999 CompileRun("function load(x) { return x.foo; }"
21000 "function store(x) { x.foo = void 0; }"
21001 "function keyed_load(x, key) { return x[key]; }"
21002 // Second version of function has a different source (add void 0)
21003 // so that it does not share code with the first version. This
21004 // ensures that the ICs are monomorphic.
21005 "function load2(x) { void 0; return x.foo; }"
21006 "function store2(x) { void 0; x.foo = void 0; }"
21007 "function keyed_load2(x, key) { void 0; return x[key]; }"
21008
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000021009 "obj.y = void 0;"
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000021010 "obj.__proto__ = null;"
erik.corry@gmail.com88767242012-08-08 14:43:45 +000021011 "var subobj = {};"
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000021012 "subobj.y = void 0;"
erik.corry@gmail.com88767242012-08-08 14:43:45 +000021013 "subobj.__proto__ = obj;"
21014 "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
21015
21016 // Make the ICs monomorphic.
21017 "load(obj); load(obj);"
21018 "load2(subobj); load2(subobj);"
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000021019 "store(obj); store(obj);"
21020 "store2(subobj); store2(subobj);"
erik.corry@gmail.com88767242012-08-08 14:43:45 +000021021 "keyed_load(obj, 'foo'); keyed_load(obj, 'foo');"
21022 "keyed_load2(subobj, 'foo'); keyed_load2(subobj, 'foo');"
21023
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000021024 // Actually test the shiny new ICs and better not crash. This
21025 // serves as a regression test for issue 142088 as well.
21026 "load(obj);"
21027 "load2(subobj);"
21028 "store(obj);"
21029 "store2(subobj);"
21030 "keyed_load(obj, 'foo');"
21031 "keyed_load2(subobj, 'foo');"
21032
erik.corry@gmail.com88767242012-08-08 14:43:45 +000021033 // Delete the accessor. It better not be called any more now.
21034 "delete obj.foo;"
21035 "obj.y = void 0;"
21036 "subobj.y = void 0;"
21037
21038 "var load_result = load(obj);"
21039 "var load_result2 = load2(subobj);"
21040 "var keyed_load_result = keyed_load(obj, 'foo');"
21041 "var keyed_load_result2 = keyed_load2(subobj, 'foo');"
21042 "store(obj);"
21043 "store2(subobj);"
21044 "var y_from_obj = obj.y;"
21045 "var y_from_subobj = subobj.y;");
21046 CHECK(context->Global()->Get(v8_str("load_result"))->IsUndefined());
21047 CHECK(context->Global()->Get(v8_str("load_result2"))->IsUndefined());
21048 CHECK(context->Global()->Get(v8_str("keyed_load_result"))->IsUndefined());
21049 CHECK(context->Global()->Get(v8_str("keyed_load_result2"))->IsUndefined());
21050 CHECK(context->Global()->Get(v8_str("y_from_obj"))->IsUndefined());
21051 CHECK(context->Global()->Get(v8_str("y_from_subobj"))->IsUndefined());
jkummerow@chromium.org28583c92012-07-16 11:31:55 +000021052}
verwaest@chromium.org753aee42012-07-17 16:15:42 +000021053
21054
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000021055THREADED_TEST(Regress142088) {
21056 i::FLAG_allow_natives_syntax = true;
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000021057 LocalContext context;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000021058 v8::Isolate* isolate = context->GetIsolate();
21059 v8::HandleScope scope(isolate);
21060 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
verwaest@chromium.orgde64f722012-08-16 15:44:54 +000021061 templ->SetAccessor(v8_str("foo"),
21062 GetterWhichReturns42,
21063 SetterWhichSetsYOnThisTo23);
21064 context->Global()->Set(v8_str("obj"), templ->NewInstance());
21065
21066 CompileRun("function load(x) { return x.foo; }"
21067 "var o = Object.create(obj);"
21068 "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
21069 "load(o); load(o); load(o); load(o);");
21070}
21071
21072
verwaest@chromium.org753aee42012-07-17 16:15:42 +000021073THREADED_TEST(Regress137496) {
21074 i::FLAG_expose_gc = true;
verwaest@chromium.org753aee42012-07-17 16:15:42 +000021075 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000021076 v8::HandleScope scope(context->GetIsolate());
verwaest@chromium.org753aee42012-07-17 16:15:42 +000021077
21078 // Compile a try-finally clause where the finally block causes a GC
21079 // while there still is a message pending for external reporting.
21080 TryCatch try_catch;
21081 try_catch.SetVerbose(true);
21082 CompileRun("try { throw new Error(); } finally { gc(); }");
21083 CHECK(try_catch.HasCaught());
21084}
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000021085
21086
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000021087THREADED_TEST(Regress149912) {
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000021088 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000021089 v8::HandleScope scope(context->GetIsolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000021090 Handle<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
verwaest@chromium.org33e09c82012-10-10 17:07:22 +000021091 AddInterceptor(templ, EmptyInterceptorGetter, EmptyInterceptorSetter);
21092 context->Global()->Set(v8_str("Bug"), templ->GetFunction());
21093 CompileRun("Number.prototype.__proto__ = new Bug; var x = 0; x.foo();");
21094}
21095
21096
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000021097THREADED_TEST(Regress157124) {
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000021098 LocalContext context;
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000021099 v8::Isolate* isolate = context->GetIsolate();
21100 v8::HandleScope scope(isolate);
21101 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +000021102 Local<Object> obj = templ->NewInstance();
21103 obj->GetIdentityHash();
21104 obj->DeleteHiddenValue(v8_str("Bug"));
21105}
21106
21107
ulan@chromium.org6e196bf2013-03-13 09:38:22 +000021108THREADED_TEST(Regress2535) {
21109 i::FLAG_harmony_collections = true;
ulan@chromium.org6e196bf2013-03-13 09:38:22 +000021110 LocalContext context;
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000021111 v8::HandleScope scope(context->GetIsolate());
ulan@chromium.org6e196bf2013-03-13 09:38:22 +000021112 Local<Value> set_value = CompileRun("new Set();");
danno@chromium.orgf95d4b92013-06-13 14:40:17 +000021113 Local<Object> set_object(Local<Object>::Cast(set_value));
ulan@chromium.org6e196bf2013-03-13 09:38:22 +000021114 CHECK_EQ(0, set_object->InternalFieldCount());
21115 Local<Value> map_value = CompileRun("new Map();");
danno@chromium.orgf95d4b92013-06-13 14:40:17 +000021116 Local<Object> map_object(Local<Object>::Cast(map_value));
ulan@chromium.org6e196bf2013-03-13 09:38:22 +000021117 CHECK_EQ(0, map_object->InternalFieldCount());
21118}
21119
21120
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000021121THREADED_TEST(Regress2746) {
21122 LocalContext context;
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000021123 v8::Isolate* isolate = context->GetIsolate();
21124 v8::HandleScope scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000021125 Local<Object> obj = Object::New(isolate);
machenbach@chromium.orgf9841892013-11-25 12:01:13 +000021126 Local<String> key = String::NewFromUtf8(context->GetIsolate(), "key");
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000021127 obj->SetHiddenValue(key, v8::Undefined(isolate));
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000021128 Local<Value> value = obj->GetHiddenValue(key);
21129 CHECK(!value.IsEmpty());
21130 CHECK(value->IsUndefined());
21131}
21132
21133
jkummerow@chromium.org10480472013-07-17 08:22:15 +000021134THREADED_TEST(Regress260106) {
21135 LocalContext context;
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000021136 v8::Isolate* isolate = context->GetIsolate();
21137 v8::HandleScope scope(isolate);
21138 Local<FunctionTemplate> templ = FunctionTemplate::New(isolate,
21139 DummyCallHandler);
jkummerow@chromium.org10480472013-07-17 08:22:15 +000021140 CompileRun("for (var i = 0; i < 128; i++) Object.prototype[i] = 0;");
21141 Local<Function> function = templ->GetFunction();
21142 CHECK(!function.IsEmpty());
21143 CHECK(function->IsFunction());
21144}
21145
21146
danno@chromium.org59400602013-08-13 17:09:37 +000021147THREADED_TEST(JSONParseObject) {
21148 LocalContext context;
21149 HandleScope scope(context->GetIsolate());
21150 Local<Value> obj = v8::JSON::Parse(v8_str("{\"x\":42}"));
21151 Handle<Object> global = context->Global();
21152 global->Set(v8_str("obj"), obj);
21153 ExpectString("JSON.stringify(obj)", "{\"x\":42}");
21154}
21155
21156
21157THREADED_TEST(JSONParseNumber) {
21158 LocalContext context;
21159 HandleScope scope(context->GetIsolate());
21160 Local<Value> obj = v8::JSON::Parse(v8_str("42"));
21161 Handle<Object> global = context->Global();
21162 global->Set(v8_str("obj"), obj);
21163 ExpectString("JSON.stringify(obj)", "42");
21164}
21165
21166
verwaest@chromium.org662436e2013-08-28 08:41:27 +000021167#if V8_OS_POSIX
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000021168class ThreadInterruptTest {
21169 public:
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000021170 ThreadInterruptTest() : sem_(0), sem_value_(0) { }
21171 ~ThreadInterruptTest() {}
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000021172
21173 void RunTest() {
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000021174 InterruptThread i_thread(this);
21175 i_thread.Start();
21176
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000021177 sem_.Wait();
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000021178 CHECK_EQ(kExpectedValue, sem_value_);
21179 }
21180
21181 private:
21182 static const int kExpectedValue = 1;
21183
21184 class InterruptThread : public i::Thread {
21185 public:
21186 explicit InterruptThread(ThreadInterruptTest* test)
21187 : Thread("InterruptThread"), test_(test) {}
21188
21189 virtual void Run() {
21190 struct sigaction action;
21191
21192 // Ensure that we'll enter waiting condition
21193 i::OS::Sleep(100);
21194
21195 // Setup signal handler
21196 memset(&action, 0, sizeof(action));
21197 action.sa_handler = SignalHandler;
21198 sigaction(SIGCHLD, &action, NULL);
21199
21200 // Send signal
21201 kill(getpid(), SIGCHLD);
21202
21203 // Ensure that if wait has returned because of error
21204 i::OS::Sleep(100);
21205
21206 // Set value and signal semaphore
21207 test_->sem_value_ = 1;
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000021208 test_->sem_.Signal();
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000021209 }
21210
21211 static void SignalHandler(int signal) {
21212 }
21213
21214 private:
21215 ThreadInterruptTest* test_;
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000021216 };
21217
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000021218 i::Semaphore sem_;
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000021219 volatile int sem_value_;
21220};
21221
21222
21223THREADED_TEST(SemaphoreInterruption) {
21224 ThreadInterruptTest().RunTest();
21225}
yangguo@chromium.org46a2a512013-01-18 16:29:40 +000021226
danno@chromium.org169691d2013-07-15 08:01:13 +000021227
hpayer@chromium.orgea9b8ba2013-12-20 19:22:39 +000021228#endif // V8_OS_POSIX
21229
21230
danno@chromium.org169691d2013-07-15 08:01:13 +000021231static bool NamedAccessAlwaysBlocked(Local<v8::Object> global,
21232 Local<Value> name,
21233 v8::AccessType type,
21234 Local<Value> data) {
21235 i::PrintF("Named access blocked.\n");
21236 return false;
21237}
21238
21239
21240static bool IndexAccessAlwaysBlocked(Local<v8::Object> global,
21241 uint32_t key,
21242 v8::AccessType type,
21243 Local<Value> data) {
21244 i::PrintF("Indexed access blocked.\n");
21245 return false;
21246}
21247
21248
21249void UnreachableCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
21250 CHECK(false);
21251}
21252
21253
21254TEST(JSONStringifyAccessCheck) {
21255 v8::V8::Initialize();
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000021256 v8::Isolate* isolate = CcTest::isolate();
21257 v8::HandleScope scope(isolate);
danno@chromium.org169691d2013-07-15 08:01:13 +000021258
21259 // Create an ObjectTemplate for global objects and install access
21260 // check callbacks that will block access.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000021261 v8::Handle<v8::ObjectTemplate> global_template =
21262 v8::ObjectTemplate::New(isolate);
danno@chromium.org169691d2013-07-15 08:01:13 +000021263 global_template->SetAccessCheckCallbacks(NamedAccessAlwaysBlocked,
21264 IndexAccessAlwaysBlocked);
21265
21266 // Create a context and set an x property on it's global object.
21267 LocalContext context0(NULL, global_template);
21268 v8::Handle<v8::Object> global0 = context0->Global();
21269 global0->Set(v8_str("x"), v8_num(42));
21270 ExpectString("JSON.stringify(this)", "{\"x\":42}");
21271
21272 for (int i = 0; i < 2; i++) {
21273 if (i == 1) {
21274 // Install a toJSON function on the second run.
21275 v8::Handle<v8::FunctionTemplate> toJSON =
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000021276 v8::FunctionTemplate::New(isolate, UnreachableCallback);
danno@chromium.org169691d2013-07-15 08:01:13 +000021277
21278 global0->Set(v8_str("toJSON"), toJSON->GetFunction());
21279 }
21280 // Create a context with a different security token so that the
21281 // failed access check callback will be called on each access.
21282 LocalContext context1(NULL, global_template);
21283 context1->Global()->Set(v8_str("other"), global0);
21284
21285 ExpectString("JSON.stringify(other)", "{}");
21286 ExpectString("JSON.stringify({ 'a' : other, 'b' : ['c'] })",
21287 "{\"a\":{},\"b\":[\"c\"]}");
21288 ExpectString("JSON.stringify([other, 'b', 'c'])",
21289 "[{},\"b\",\"c\"]");
21290
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000021291 v8::Handle<v8::Array> array = v8::Array::New(isolate, 2);
danno@chromium.org169691d2013-07-15 08:01:13 +000021292 array->Set(0, v8_str("a"));
21293 array->Set(1, v8_str("b"));
21294 context1->Global()->Set(v8_str("array"), array);
21295 ExpectString("JSON.stringify(array)", "[\"a\",\"b\"]");
21296 array->TurnOnAccessCheck();
21297 ExpectString("JSON.stringify(array)", "[]");
21298 ExpectString("JSON.stringify([array])", "[[]]");
21299 ExpectString("JSON.stringify({'a' : array})", "{\"a\":[]}");
21300 }
21301}
21302
21303
21304bool access_check_fail_thrown = false;
21305bool catch_callback_called = false;
21306
21307
21308// Failed access check callback that performs a GC on each invocation.
21309void FailedAccessCheckThrows(Local<v8::Object> target,
21310 v8::AccessType type,
21311 Local<v8::Value> data) {
21312 access_check_fail_thrown = true;
21313 i::PrintF("Access check failed. Error thrown.\n");
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000021314 CcTest::isolate()->ThrowException(
21315 v8::Exception::Error(v8_str("cross context")));
danno@chromium.org169691d2013-07-15 08:01:13 +000021316}
21317
21318
21319void CatcherCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
21320 for (int i = 0; i < args.Length(); i++) {
21321 i::PrintF("%s\n", *String::Utf8Value(args[i]));
21322 }
21323 catch_callback_called = true;
21324}
21325
21326
21327void HasOwnPropertyCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
21328 args[0]->ToObject()->HasOwnProperty(args[1]->ToString());
21329}
21330
21331
21332void CheckCorrectThrow(const char* script) {
21333 // Test that the script, when wrapped into a try-catch, triggers the catch
21334 // clause due to failed access check throwing an exception.
21335 // The subsequent try-catch should run without any exception.
21336 access_check_fail_thrown = false;
21337 catch_callback_called = false;
21338 i::ScopedVector<char> source(1024);
21339 i::OS::SNPrintF(source, "try { %s; } catch (e) { catcher(e); }", script);
21340 CompileRun(source.start());
21341 CHECK(access_check_fail_thrown);
21342 CHECK(catch_callback_called);
21343
21344 access_check_fail_thrown = false;
21345 catch_callback_called = false;
21346 CompileRun("try { [1, 2, 3].sort(); } catch (e) { catcher(e) };");
21347 CHECK(!access_check_fail_thrown);
21348 CHECK(!catch_callback_called);
21349}
21350
21351
21352TEST(AccessCheckThrows) {
21353 i::FLAG_allow_natives_syntax = true;
21354 v8::V8::Initialize();
21355 v8::V8::SetFailedAccessCheckCallbackFunction(&FailedAccessCheckThrows);
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000021356 v8::Isolate* isolate = CcTest::isolate();
21357 v8::HandleScope scope(isolate);
danno@chromium.org169691d2013-07-15 08:01:13 +000021358
21359 // Create an ObjectTemplate for global objects and install access
21360 // check callbacks that will block access.
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000021361 v8::Handle<v8::ObjectTemplate> global_template =
21362 v8::ObjectTemplate::New(isolate);
danno@chromium.org169691d2013-07-15 08:01:13 +000021363 global_template->SetAccessCheckCallbacks(NamedAccessAlwaysBlocked,
21364 IndexAccessAlwaysBlocked);
21365
21366 // Create a context and set an x property on it's global object.
21367 LocalContext context0(NULL, global_template);
21368 context0->Global()->Set(v8_str("x"), v8_num(42));
21369 v8::Handle<v8::Object> global0 = context0->Global();
21370
21371 // Create a context with a different security token so that the
21372 // failed access check callback will be called on each access.
21373 LocalContext context1(NULL, global_template);
21374 context1->Global()->Set(v8_str("other"), global0);
21375
21376 v8::Handle<v8::FunctionTemplate> catcher_fun =
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000021377 v8::FunctionTemplate::New(isolate, CatcherCallback);
danno@chromium.org169691d2013-07-15 08:01:13 +000021378 context1->Global()->Set(v8_str("catcher"), catcher_fun->GetFunction());
21379
21380 v8::Handle<v8::FunctionTemplate> has_own_property_fun =
ulan@chromium.org9cbaabd2014-01-08 10:55:36 +000021381 v8::FunctionTemplate::New(isolate, HasOwnPropertyCallback);
danno@chromium.org169691d2013-07-15 08:01:13 +000021382 context1->Global()->Set(v8_str("has_own_property"),
21383 has_own_property_fun->GetFunction());
21384
21385 { v8::TryCatch try_catch;
21386 access_check_fail_thrown = false;
21387 CompileRun("other.x;");
21388 CHECK(access_check_fail_thrown);
21389 CHECK(try_catch.HasCaught());
21390 }
21391
21392 CheckCorrectThrow("other.x");
21393 CheckCorrectThrow("other[1]");
21394 CheckCorrectThrow("JSON.stringify(other)");
21395 CheckCorrectThrow("has_own_property(other, 'x')");
21396 CheckCorrectThrow("%GetProperty(other, 'x')");
21397 CheckCorrectThrow("%SetProperty(other, 'x', 'foo', 1, 0)");
21398 CheckCorrectThrow("%IgnoreAttributesAndSetProperty(other, 'x', 'foo')");
21399 CheckCorrectThrow("%DeleteProperty(other, 'x', 0)");
21400 CheckCorrectThrow("%DeleteProperty(other, '1', 0)");
21401 CheckCorrectThrow("%HasLocalProperty(other, 'x')");
21402 CheckCorrectThrow("%HasProperty(other, 'x')");
21403 CheckCorrectThrow("%HasElement(other, 1)");
21404 CheckCorrectThrow("%IsPropertyEnumerable(other, 'x')");
21405 CheckCorrectThrow("%GetPropertyNames(other)");
machenbach@chromium.org03453962014-01-10 14:16:31 +000021406 // PROPERTY_ATTRIBUTES_NONE = 0
21407 CheckCorrectThrow("%GetLocalPropertyNames(other, 0)");
danno@chromium.org169691d2013-07-15 08:01:13 +000021408 CheckCorrectThrow("%DefineOrRedefineAccessorProperty("
21409 "other, 'x', null, null, 1)");
verwaest@chromium.org32cb9b22013-08-21 11:18:12 +000021410
21411 // Reset the failed access check callback so it does not influence
21412 // the other tests.
21413 v8::V8::SetFailedAccessCheckCallbackFunction(NULL);
danno@chromium.org169691d2013-07-15 08:01:13 +000021414}
21415
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000021416
21417THREADED_TEST(Regress256330) {
21418 i::FLAG_allow_natives_syntax = true;
21419 LocalContext context;
21420 v8::HandleScope scope(context->GetIsolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000021421 Handle<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000021422 AddInterceptor(templ, EmptyInterceptorGetter, EmptyInterceptorSetter);
21423 context->Global()->Set(v8_str("Bug"), templ->GetFunction());
21424 CompileRun("\"use strict\"; var o = new Bug;"
21425 "function f(o) { o.x = 10; };"
21426 "f(o); f(o); f(o);"
21427 "%OptimizeFunctionOnNextCall(f);"
21428 "f(o);");
21429 ExpectBoolean("%GetOptimizationStatus(f) != 2", true);
21430}
21431
21432
21433THREADED_TEST(CrankshaftInterceptorSetter) {
21434 i::FLAG_allow_natives_syntax = true;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000021435 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000021436 Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000021437 AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
21438 LocalContext env;
21439 env->Global()->Set(v8_str("Obj"), templ->GetFunction());
21440 CompileRun("var obj = new Obj;"
21441 // Initialize fields to avoid transitions later.
21442 "obj.age = 0;"
21443 "obj.accessor_age = 42;"
21444 "function setter(i) { this.accessor_age = i; };"
21445 "function getter() { return this.accessor_age; };"
21446 "function setAge(i) { obj.age = i; };"
21447 "Object.defineProperty(obj, 'age', { get:getter, set:setter });"
21448 "setAge(1);"
21449 "setAge(2);"
21450 "setAge(3);"
21451 "%OptimizeFunctionOnNextCall(setAge);"
21452 "setAge(4);");
21453 // All stores went through the interceptor.
21454 ExpectInt32("obj.interceptor_age", 4);
21455 ExpectInt32("obj.accessor_age", 42);
21456}
21457
21458
21459THREADED_TEST(CrankshaftInterceptorGetter) {
21460 i::FLAG_allow_natives_syntax = true;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000021461 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000021462 Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000021463 AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
21464 LocalContext env;
21465 env->Global()->Set(v8_str("Obj"), templ->GetFunction());
21466 CompileRun("var obj = new Obj;"
21467 // Initialize fields to avoid transitions later.
21468 "obj.age = 1;"
21469 "obj.accessor_age = 42;"
21470 "function getter() { return this.accessor_age; };"
21471 "function getAge() { return obj.interceptor_age; };"
21472 "Object.defineProperty(obj, 'interceptor_age', { get:getter });"
21473 "getAge();"
21474 "getAge();"
21475 "getAge();"
21476 "%OptimizeFunctionOnNextCall(getAge);");
21477 // Access through interceptor.
21478 ExpectInt32("getAge()", 1);
21479}
21480
21481
21482THREADED_TEST(CrankshaftInterceptorFieldRead) {
21483 i::FLAG_allow_natives_syntax = true;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000021484 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000021485 Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000021486 AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
21487 LocalContext env;
21488 env->Global()->Set(v8_str("Obj"), templ->GetFunction());
21489 CompileRun("var obj = new Obj;"
21490 "obj.__proto__.interceptor_age = 42;"
21491 "obj.age = 100;"
21492 "function getAge() { return obj.interceptor_age; };");
21493 ExpectInt32("getAge();", 100);
21494 ExpectInt32("getAge();", 100);
21495 ExpectInt32("getAge();", 100);
21496 CompileRun("%OptimizeFunctionOnNextCall(getAge);");
21497 // Access through interceptor.
21498 ExpectInt32("getAge();", 100);
21499}
21500
21501
21502THREADED_TEST(CrankshaftInterceptorFieldWrite) {
21503 i::FLAG_allow_natives_syntax = true;
machenbach@chromium.org528ce022013-09-23 14:09:36 +000021504 v8::HandleScope scope(CcTest::isolate());
hpayer@chromium.org4f99be92013-12-18 16:23:55 +000021505 Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +000021506 AddInterceptor(templ, InterceptorGetter, InterceptorSetter);
21507 LocalContext env;
21508 env->Global()->Set(v8_str("Obj"), templ->GetFunction());
21509 CompileRun("var obj = new Obj;"
21510 "obj.age = 100000;"
21511 "function setAge(i) { obj.age = i };"
21512 "setAge(100);"
21513 "setAge(101);"
21514 "setAge(102);"
21515 "%OptimizeFunctionOnNextCall(setAge);"
21516 "setAge(103);");
21517 ExpectInt32("obj.age", 100000);
21518 ExpectInt32("obj.interceptor_age", 103);
21519}
21520
dslomov@chromium.org639bac02013-09-09 11:58:54 +000021521
hpayer@chromium.orgea9b8ba2013-12-20 19:22:39 +000021522class RequestInterruptTestBase {
21523 public:
21524 RequestInterruptTestBase()
21525 : env_(),
21526 isolate_(env_->GetIsolate()),
21527 sem_(0),
21528 warmup_(20000),
21529 should_continue_(true) {
21530 }
21531
21532 virtual ~RequestInterruptTestBase() { }
21533
21534 virtual void TestBody() = 0;
21535
21536 void RunTest() {
21537 InterruptThread i_thread(this);
21538 i_thread.Start();
21539
21540 v8::HandleScope handle_scope(isolate_);
21541
21542 TestBody();
21543
21544 isolate_->ClearInterrupt();
21545
21546 // Verify we arrived here because interruptor was called
21547 // not due to a bug causing us to exit the loop too early.
21548 CHECK(!should_continue());
21549 }
21550
21551 void WakeUpInterruptor() {
21552 sem_.Signal();
21553 }
21554
21555 bool should_continue() const { return should_continue_; }
21556
21557 bool ShouldContinue() {
21558 if (warmup_ > 0) {
21559 if (--warmup_ == 0) {
21560 WakeUpInterruptor();
21561 }
21562 }
21563
21564 return should_continue_;
21565 }
21566
21567 protected:
21568 static void ShouldContinueCallback(
21569 const v8::FunctionCallbackInfo<Value>& info) {
21570 RequestInterruptTestBase* test =
21571 reinterpret_cast<RequestInterruptTestBase*>(
21572 info.Data().As<v8::External>()->Value());
21573 info.GetReturnValue().Set(test->ShouldContinue());
21574 }
21575
21576 class InterruptThread : public i::Thread {
21577 public:
21578 explicit InterruptThread(RequestInterruptTestBase* test)
21579 : Thread("RequestInterruptTest"), test_(test) {}
21580
21581 virtual void Run() {
21582 test_->sem_.Wait();
21583 test_->isolate_->RequestInterrupt(&OnInterrupt, test_);
21584 }
21585
21586 static void OnInterrupt(v8::Isolate* isolate, void* data) {
21587 reinterpret_cast<RequestInterruptTestBase*>(data)->
21588 should_continue_ = false;
21589 }
21590
21591 private:
21592 RequestInterruptTestBase* test_;
21593 };
21594
21595 LocalContext env_;
21596 v8::Isolate* isolate_;
21597 i::Semaphore sem_;
21598 int warmup_;
21599 bool should_continue_;
21600};
21601
21602
21603class RequestInterruptTestWithFunctionCall : public RequestInterruptTestBase {
21604 public:
21605 virtual void TestBody() {
21606 Local<Function> func = Function::New(
21607 isolate_, ShouldContinueCallback, v8::External::New(isolate_, this));
21608 env_->Global()->Set(v8_str("ShouldContinue"), func);
21609
21610 CompileRun("while (ShouldContinue()) { }");
21611 }
21612};
21613
21614
21615class RequestInterruptTestWithMethodCall : public RequestInterruptTestBase {
21616 public:
21617 virtual void TestBody() {
21618 v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
21619 v8::Local<v8::Template> proto = t->PrototypeTemplate();
21620 proto->Set(v8_str("shouldContinue"), Function::New(
21621 isolate_, ShouldContinueCallback, v8::External::New(isolate_, this)));
21622 env_->Global()->Set(v8_str("Klass"), t->GetFunction());
21623
21624 CompileRun("var obj = new Klass; while (obj.shouldContinue()) { }");
21625 }
21626};
21627
21628
21629class RequestInterruptTestWithAccessor : public RequestInterruptTestBase {
21630 public:
21631 virtual void TestBody() {
21632 v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
21633 v8::Local<v8::Template> proto = t->PrototypeTemplate();
21634 proto->SetAccessorProperty(v8_str("shouldContinue"), FunctionTemplate::New(
21635 isolate_, ShouldContinueCallback, v8::External::New(isolate_, this)));
21636 env_->Global()->Set(v8_str("Klass"), t->GetFunction());
21637
21638 CompileRun("var obj = new Klass; while (obj.shouldContinue) { }");
21639 }
21640};
21641
21642
21643class RequestInterruptTestWithNativeAccessor : public RequestInterruptTestBase {
21644 public:
21645 virtual void TestBody() {
21646 v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
21647 t->InstanceTemplate()->SetNativeDataProperty(
21648 v8_str("shouldContinue"),
21649 &ShouldContinueNativeGetter,
21650 NULL,
21651 v8::External::New(isolate_, this));
21652 env_->Global()->Set(v8_str("Klass"), t->GetFunction());
21653
21654 CompileRun("var obj = new Klass; while (obj.shouldContinue) { }");
21655 }
21656
21657 private:
21658 static void ShouldContinueNativeGetter(
21659 Local<String> property,
21660 const v8::PropertyCallbackInfo<v8::Value>& info) {
21661 RequestInterruptTestBase* test =
21662 reinterpret_cast<RequestInterruptTestBase*>(
21663 info.Data().As<v8::External>()->Value());
21664 info.GetReturnValue().Set(test->ShouldContinue());
21665 }
21666};
21667
21668
21669class RequestInterruptTestWithMethodCallAndInterceptor
21670 : public RequestInterruptTestBase {
21671 public:
21672 virtual void TestBody() {
21673 v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
21674 v8::Local<v8::Template> proto = t->PrototypeTemplate();
21675 proto->Set(v8_str("shouldContinue"), Function::New(
21676 isolate_, ShouldContinueCallback, v8::External::New(isolate_, this)));
21677 v8::Local<v8::ObjectTemplate> instance_template = t->InstanceTemplate();
21678 instance_template->SetNamedPropertyHandler(EmptyInterceptor);
21679
21680 env_->Global()->Set(v8_str("Klass"), t->GetFunction());
21681
21682 CompileRun("var obj = new Klass; while (obj.shouldContinue()) { }");
21683 }
21684
21685 private:
21686 static void EmptyInterceptor(
21687 Local<String> property,
21688 const v8::PropertyCallbackInfo<v8::Value>& info) {
21689 }
21690};
21691
21692
21693class RequestInterruptTestWithMathAbs : public RequestInterruptTestBase {
21694 public:
21695 virtual void TestBody() {
21696 env_->Global()->Set(v8_str("WakeUpInterruptor"), Function::New(
21697 isolate_,
21698 WakeUpInterruptorCallback,
21699 v8::External::New(isolate_, this)));
21700
21701 env_->Global()->Set(v8_str("ShouldContinue"), Function::New(
21702 isolate_,
21703 ShouldContinueCallback,
21704 v8::External::New(isolate_, this)));
21705
21706 i::FLAG_allow_natives_syntax = true;
21707 CompileRun("function loopish(o) {"
21708 " var pre = 10;"
21709 " while (o.abs(1) > 0) {"
21710 " if (o.abs(1) >= 0 && !ShouldContinue()) break;"
21711 " if (pre > 0) {"
21712 " if (--pre === 0) WakeUpInterruptor(o === Math);"
21713 " }"
21714 " }"
21715 "}"
21716 "var i = 50;"
21717 "var obj = {abs: function () { return i-- }, x: null};"
21718 "delete obj.x;"
21719 "loopish(obj);"
21720 "%OptimizeFunctionOnNextCall(loopish);"
21721 "loopish(Math);");
21722
21723 i::FLAG_allow_natives_syntax = false;
21724 }
21725
21726 private:
21727 static void WakeUpInterruptorCallback(
21728 const v8::FunctionCallbackInfo<Value>& info) {
21729 if (!info[0]->BooleanValue()) return;
21730
21731 RequestInterruptTestBase* test =
21732 reinterpret_cast<RequestInterruptTestBase*>(
21733 info.Data().As<v8::External>()->Value());
21734 test->WakeUpInterruptor();
21735 }
21736
21737 static void ShouldContinueCallback(
21738 const v8::FunctionCallbackInfo<Value>& info) {
21739 RequestInterruptTestBase* test =
21740 reinterpret_cast<RequestInterruptTestBase*>(
21741 info.Data().As<v8::External>()->Value());
21742 info.GetReturnValue().Set(test->should_continue());
21743 }
21744};
21745
21746
21747TEST(RequestInterruptTestWithFunctionCall) {
21748 RequestInterruptTestWithFunctionCall().RunTest();
21749}
21750
21751
21752TEST(RequestInterruptTestWithMethodCall) {
21753 RequestInterruptTestWithMethodCall().RunTest();
21754}
21755
21756
21757TEST(RequestInterruptTestWithAccessor) {
21758 RequestInterruptTestWithAccessor().RunTest();
21759}
21760
21761
21762TEST(RequestInterruptTestWithNativeAccessor) {
21763 RequestInterruptTestWithNativeAccessor().RunTest();
21764}
21765
21766
21767TEST(RequestInterruptTestWithMethodCallAndInterceptor) {
21768 RequestInterruptTestWithMethodCallAndInterceptor().RunTest();
21769}
21770
21771
21772TEST(RequestInterruptTestWithMathAbs) {
21773 RequestInterruptTestWithMathAbs().RunTest();
21774}
dslomov@chromium.org639bac02013-09-09 11:58:54 +000021775
21776
21777static Local<Value> function_new_expected_env;
21778static void FunctionNewCallback(const v8::FunctionCallbackInfo<Value>& info) {
21779 CHECK_EQ(function_new_expected_env, info.Data());
21780 info.GetReturnValue().Set(17);
21781}
21782
21783
21784THREADED_TEST(FunctionNew) {
21785 LocalContext env;
21786 v8::Isolate* isolate = env->GetIsolate();
21787 v8::HandleScope scope(isolate);
ulan@chromium.org0f13e742014-01-03 15:51:11 +000021788 Local<Object> data = v8::Object::New(isolate);
dslomov@chromium.org639bac02013-09-09 11:58:54 +000021789 function_new_expected_env = data;
21790 Local<Function> func = Function::New(isolate, FunctionNewCallback, data);
21791 env->Global()->Set(v8_str("func"), func);
21792 Local<Value> result = CompileRun("func();");
ulan@chromium.org0f13e742014-01-03 15:51:11 +000021793 CHECK_EQ(v8::Integer::New(isolate, 17), result);
dslomov@chromium.org639bac02013-09-09 11:58:54 +000021794 // Verify function not cached
21795 int serial_number =
21796 i::Smi::cast(v8::Utils::OpenHandle(*func)
21797 ->shared()->get_api_func_data()->serial_number())->value();
21798 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
21799 i::Object* elm = i_isolate->native_context()->function_cache()
21800 ->GetElementNoExceptionThrown(i_isolate, serial_number);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000021801 CHECK(elm->IsUndefined());
21802 // Verify that each Function::New creates a new function instance
ulan@chromium.org0f13e742014-01-03 15:51:11 +000021803 Local<Object> data2 = v8::Object::New(isolate);
machenbach@chromium.org528ce022013-09-23 14:09:36 +000021804 function_new_expected_env = data2;
21805 Local<Function> func2 = Function::New(isolate, FunctionNewCallback, data2);
21806 CHECK(!func2->IsNull());
21807 CHECK_NE(func, func2);
21808 env->Global()->Set(v8_str("func2"), func2);
21809 Local<Value> result2 = CompileRun("func2();");
ulan@chromium.org0f13e742014-01-03 15:51:11 +000021810 CHECK_EQ(v8::Integer::New(isolate, 17), result2);
dslomov@chromium.org639bac02013-09-09 11:58:54 +000021811}
21812
machenbach@chromium.orgcfdf67d2013-09-27 07:27:26 +000021813
21814TEST(EscapeableHandleScope) {
21815 HandleScope outer_scope(CcTest::isolate());
21816 LocalContext context;
21817 const int runs = 10;
21818 Local<String> values[runs];
21819 for (int i = 0; i < runs; i++) {
21820 v8::EscapableHandleScope inner_scope(CcTest::isolate());
21821 Local<String> value;
21822 if (i != 0) value = v8_str("escape value");
21823 values[i] = inner_scope.Escape(value);
21824 }
21825 for (int i = 0; i < runs; i++) {
21826 Local<String> expected;
21827 if (i != 0) {
21828 CHECK_EQ(v8_str("escape value"), values[i]);
21829 } else {
21830 CHECK(values[i].IsEmpty());
21831 }
21832 }
21833}
machenbach@chromium.org43c51e52014-01-20 07:57:28 +000021834
21835
21836static void SetterWhichExpectsThisAndHolderToDiffer(
21837 Local<String>, Local<Value>, const v8::PropertyCallbackInfo<void>& info) {
21838 CHECK(info.Holder() != info.This());
21839}
21840
21841
21842TEST(Regress239669) {
21843 LocalContext context;
21844 v8::Isolate* isolate = context->GetIsolate();
21845 v8::HandleScope scope(isolate);
21846 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
21847 templ->SetAccessor(v8_str("x"), 0, SetterWhichExpectsThisAndHolderToDiffer);
21848 context->Global()->Set(v8_str("P"), templ->NewInstance());
21849 CompileRun(
21850 "function C1() {"
21851 " this.x = 23;"
21852 "};"
21853 "C1.prototype = P;"
21854 "for (var i = 0; i < 4; i++ ) {"
21855 " new C1();"
21856 "}");
21857}
machenbach@chromium.org57a54ac2014-01-31 14:01:53 +000021858
21859
21860class ApiCallOptimizationChecker {
21861 private:
21862 static Local<Object> data;
21863 static Local<Object> receiver;
21864 static Local<Object> holder;
21865 static Local<Object> callee;
21866 static int count;
21867
21868 static void OptimizationCallback(
21869 const v8::FunctionCallbackInfo<v8::Value>& info) {
21870 CHECK(callee == info.Callee());
21871 CHECK(data == info.Data());
21872 CHECK(receiver == info.This());
21873 CHECK(holder == info.Holder());
21874 count++;
21875 }
21876
21877 public:
21878 void Run(bool use_signature, bool global) {
21879 v8::Isolate* isolate = CcTest::isolate();
21880 v8::HandleScope scope(isolate);
21881 // Build a template for signature checks.
21882 Local<v8::ObjectTemplate> signature_template;
21883 Local<v8::Signature> signature;
21884 {
21885 Local<v8::FunctionTemplate> parent_template =
21886 FunctionTemplate::New(isolate);
21887 parent_template->SetHiddenPrototype(true);
21888 Local<v8::FunctionTemplate> function_template
21889 = FunctionTemplate::New(isolate);
21890 function_template->Inherit(parent_template);
21891 if (use_signature) {
21892 signature = v8::Signature::New(isolate, parent_template);
21893 }
21894 signature_template = function_template->InstanceTemplate();
21895 }
21896 // Global object must pass checks.
21897 Local<v8::Context> context =
21898 v8::Context::New(isolate, NULL, signature_template);
21899 v8::Context::Scope context_scope(context);
21900 // Install regular object that can pass signature checks.
21901 Local<Object> function_receiver = signature_template->NewInstance();
21902 context->Global()->Set(v8_str("function_receiver"), function_receiver);
21903 // Get the holder objects.
21904 Local<Object> inner_global =
21905 Local<Object>::Cast(context->Global()->GetPrototype());
21906 Local<Object> function_holder =
21907 Local<Object>::Cast(function_receiver->GetPrototype());
21908 // Install function on hidden prototype object.
21909 data = Object::New(isolate);
21910 Local<FunctionTemplate> function_template = FunctionTemplate::New(
21911 isolate, OptimizationCallback, data, signature);
21912 Local<Function> function = function_template->GetFunction();
21913 Local<Object>::Cast(
21914 inner_global->GetPrototype())->Set(v8_str("global_f"), function);
21915 function_holder->Set(v8_str("f"), function);
21916 // Initialize expected values.
21917 callee = function;
21918 count = 0;
21919 if (global) {
21920 receiver = context->Global();
21921 holder = inner_global;
21922 } else {
21923 holder = function_receiver;
21924 // If not using a signature, add something else to the prototype chain
21925 // to test the case that holder != receiver
21926 if (!use_signature) {
21927 receiver = Local<Object>::Cast(CompileRun(
21928 "var receiver_subclass = {};\n"
21929 "receiver_subclass.__proto__ = function_receiver;\n"
21930 "receiver_subclass"));
21931 } else {
21932 receiver = Local<Object>::Cast(CompileRun(
21933 "var receiver_subclass = function_receiver;\n"
21934 "receiver_subclass"));
21935 }
21936 }
21937 // With no signature, the holder is not set.
21938 if (!use_signature) holder = receiver;
21939 // build wrap_function
21940 int key = (use_signature ? 1 : 0) + 2 * (global ? 1 : 0);
21941 i::ScopedVector<char> wrap_function(100);
21942 if (global) {
21943 i::OS::SNPrintF(
21944 wrap_function,
21945 "function wrap_%d() { var f = global_f; return f(); }\n",
21946 key);
21947 } else {
21948 i::OS::SNPrintF(
21949 wrap_function,
21950 "function wrap_%d() { return receiver_subclass.f(); }\n",
21951 key);
21952 }
21953 // build source string
21954 i::ScopedVector<char> source(500);
21955 i::OS::SNPrintF(
21956 source,
21957 "%s\n" // wrap_function
21958 "function wrap2() { wrap_%d(); }\n"
21959 "wrap2();\n"
21960 "wrap2();\n"
21961 "%%OptimizeFunctionOnNextCall(wrap_%d);\n"
21962 "wrap2();\n",
21963 wrap_function.start(), key, key);
21964 v8::TryCatch try_catch;
21965 CompileRun(source.start());
21966 ASSERT(!try_catch.HasCaught());
21967 CHECK_EQ(3, count);
21968 }
21969};
21970
21971
21972Local<Object> ApiCallOptimizationChecker::data;
21973Local<Object> ApiCallOptimizationChecker::receiver;
21974Local<Object> ApiCallOptimizationChecker::holder;
21975Local<Object> ApiCallOptimizationChecker::callee;
21976int ApiCallOptimizationChecker::count = 0;
21977
21978
21979TEST(TestFunctionCallOptimization) {
21980 i::FLAG_allow_natives_syntax = true;
21981 ApiCallOptimizationChecker checker;
21982 checker.Run(true, true);
21983 checker.Run(false, true);
21984 checker.Run(true, false);
21985 checker.Run(false, false);
21986}